SLikeNet  0.1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CloudServer.h
Go to the documentation of this file.
1 /*
2  * Original work: Copyright (c) 2014, Oculus VR, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7  * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8  *
9  *
10  * Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
11  *
12  * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13  * license found in the license.txt file in the root directory of this source tree.
14  */
15 
20 
21 
22 #include "NativeFeatureIncludes.h"
23 #if _RAKNET_SUPPORT_CloudServer==1
24 
25 #ifndef __CLOUD_SERVER_H
26 #define __CLOUD_SERVER_H
27 
28 #include "PluginInterface2.h"
29 #include "memoryoverride.h"
30 #include "NativeTypes.h"
31 #include "string.h"
32 #include "DS_Hash.h"
33 #include "CloudCommon.h"
34 #include "DS_OrderedList.h"
35 
37 #define CLOUD_SERVER_DATA_STACK_SIZE 32
38 
39 namespace SLNet
40 {
42 class RakPeerInterface;
43 
49 {
50 public:
53 
56  virtual bool OnPostRequest(RakNetGUID clientGuid, SystemAddress clientAddress, CloudKey key, uint32_t dataLength, const char *data)=0;
57 
60  virtual bool OnReleaseRequest(RakNetGUID clientGuid, SystemAddress clientAddress, DataStructures::List<CloudKey> &cloudKeys)=0;
61 
65  virtual bool OnGetRequest(RakNetGUID clientGuid, SystemAddress clientAddress, CloudQuery &query, DataStructures::List<RakNetGUID> &specificSystems)=0;
66 
70  virtual bool OnUnsubscribeRequest(RakNetGUID clientGuid, SystemAddress clientAddress, DataStructures::List<CloudKey> &cloudKeys, DataStructures::List<RakNetGUID> &specificSystems)=0;
71 };
72 
76 {
77 public:
78  // GetInstance() and DestroyInstance(instance*)
80 
81  CloudServer();
82  virtual ~CloudServer();
83 
88  void SetMaxUploadBytesPerClient(uint64_t bytes);
89 
93  void SetMaxBytesPerDownload(uint64_t bytes);
94 
100  void AddServer(RakNetGUID systemIdentifier);
101 
104  void RemoveServer(RakNetGUID systemIdentifier);
105 
108  void GetRemoteServers(DataStructures::List<RakNetGUID> &remoteServersOut);
109 
111  void Clear(void);
112 
117  void ForceExternalSystemAddress(SystemAddress forcedAddress);
118 
122  void AddQueryFilter(CloudServerQueryFilter* filter);
123 
127  void RemoveQueryFilter(CloudServerQueryFilter* filter);
128 
131  void RemoveAllQueryFilters(void);
132 
133 protected:
134  virtual void Update(void);
135  virtual PluginReceiveResult OnReceive(Packet *packet);
136  virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
137  virtual void OnRakPeerShutdown(void);
138 
139 
140  virtual void OnPostRequest(Packet *packet);
141  virtual void OnReleaseRequest(Packet *packet);
142  virtual void OnGetRequest(Packet *packet);
143  virtual void OnUnsubscribeRequest(Packet *packet);
144  virtual void OnServerToServerGetRequest(Packet *packet);
145  virtual void OnServerToServerGetResponse(Packet *packet);
146 
147  uint64_t maxUploadBytesPerClient, maxBytesPerDowload;
148 
149  // ----------------------------------------------------------------------------
150  // For a given data key, quickly look up one or all systems that have uploaded
151  // ----------------------------------------------------------------------------
152  struct CloudData
153  {
155  ~CloudData() {if (allocatedData) rakFree_Ex(allocatedData, _FILE_AND_LINE_);}
156  bool IsUnused(void) const {return isUploaded==false && specificSubscribers.Size()==0;}
157  void Clear(void) {if (dataPtr==allocatedData) rakFree_Ex(allocatedData, _FILE_AND_LINE_); allocatedData=0; dataPtr=0; dataLengthBytes=0; isUploaded=false;}
158 
159  unsigned char stackData[CLOUD_SERVER_DATA_STACK_SIZE];
160  unsigned char *allocatedData; // Uses allocatedData instead of stackData if length of data exceeds CLOUD_SERVER_DATA_STACK_SIZE
161  unsigned char *dataPtr; // Points to either stackData or allocatedData
164 
167 
170 
173 
176 
180  };
181  void WriteCloudQueryRowFromResultList(unsigned int i, DataStructures::List<CloudData*> &cloudDataResultList, DataStructures::List<CloudKey> &cloudKeyResultList, BitStream *bsOut);
182  void WriteCloudQueryRowFromResultList(DataStructures::List<CloudData*> &cloudDataResultList, DataStructures::List<CloudKey> &cloudKeyResultList, BitStream *bsOut);
183 
184  static int KeyDataPtrComp( const RakNetGUID &key, CloudData* const &data );
186  {
187  bool IsUnused(void) const {return keyData.Size()==0 && nonSpecificSubscribers.Size()==0;}
188  bool IsNotUploaded(void) const {return uploaderCount==0;}
190  bool objectExists;
191  unsigned int index;
192  index = nonSpecificSubscribers.GetIndexFromKey(g, &objectExists);
193  if (objectExists)
194  {
195  subscriberCount--;
196  nonSpecificSubscribers.RemoveAtIndex(index);
197  return true;
198  }
199  return false;
200  }
201 
202  unsigned int uploaderCount, subscriberCount;
204 
205  // Data uploaded from or subscribed to for various systems
207 
211  };
212 
213  static int KeyDataListComp( const CloudKey &key, CloudDataList * const &data );
215 
217  {
220  };
221  static int KeySubscriberIDComp(const CloudKey &key, KeySubscriberID * const &data );
222 
223  // Remote systems
225  {
226  bool IsUnused(void) const {return uploadedKeys.Size()==0 && subscribedKeys.Size()==0;}
227 
231  };
233 
234  // For a given user, release all subscribed and uploaded keys
235  void ReleaseSystem(RakNetGUID clientAddress );
236 
237  // For a given user, release a set of keys
238  void ReleaseKeys(RakNetGUID clientAddress, DataStructures::List<CloudKey> &keys );
239 
240  void NotifyClientSubscribersOfDataChange( CloudData *cloudData, CloudKey &key, DataStructures::OrderedList<RakNetGUID, RakNetGUID> &subscribers, bool wasUpdated );
241  void NotifyClientSubscribersOfDataChange( CloudQueryRow *row, DataStructures::OrderedList<RakNetGUID, RakNetGUID> &subscribers, bool wasUpdated );
242  void NotifyServerSubscribersOfDataChange( CloudData *cloudData, CloudKey &key, bool wasUpdated );
243 
245  {
247  // This server needs to know about these keys when they are updated or deleted
249  // This server has uploaded these keys, and needs to know about Get() requests
251 
252  // Just for processing
254 
255  // If false, we don't know what keys they have yet, so send everything
257  };
258 
259  static int RemoteServerComp(const RakNetGUID &key, RemoteServer* const &data );
261 
263  {
264  void Clear(CloudAllocator *allocator);
265 
268  bool gotResult;
269  };
270 
272  {
273  // Inputs
276 
277  void Serialize(bool writeToBitstream, BitStream *bitStream);
278  };
279 
280  static int BufferedGetResponseFromServerComp(const RakNetGUID &key, BufferedGetResponseFromServer* const &data );
281  struct GetRequest
282  {
283  void Clear(CloudAllocator *allocator);
284  bool AllRemoteServersHaveResponded(void) const;
286 
287  // When request started. If takes too long for a response from another system, can abort remaining systems
289 
290  // Assigned by server that gets the request to identify response. See nextGetRequestId
292 
294 
296  };
297  static int GetRequestComp(const uint32_t &key, GetRequest* const &data );
300 
302 
303  void ProcessAndTransmitGetRequest(GetRequest *getRequest);
304 
305  void ProcessCloudQueryWithAddresses(
306  CloudServer::CloudQueryWithAddresses &cloudQueryWithAddresses,
307  DataStructures::List<CloudData*> &cloudDataResultList,
308  DataStructures::List<CloudKey> &cloudKeyResultList
309  );
310 
311  void SendUploadedAndSubscribedKeysToServer( RakNetGUID systemAddress );
312  void SendUploadedKeyToServers( CloudKey &cloudKey );
313  void SendSubscribedKeyToServers( CloudKey &cloudKey );
314  void RemoveUploadedKeyFromServers( CloudKey &cloudKey );
315  void RemoveSubscribedKeyFromServers( CloudKey &cloudKey );
316 
317  void OnSendUploadedAndSubscribedKeysToServer( Packet *packet );
318  void OnSendUploadedKeyToServers( Packet *packet );
319  void OnSendSubscribedKeyToServers( Packet *packet );
320  void OnRemoveUploadedKeyFromServers( Packet *packet );
321  void OnRemoveSubscribedKeyFromServers( Packet *packet );
322  void OnServerDataChanged( Packet *packet );
323 
324  void GetServersWithUploadedKeys(
326  DataStructures::List<RemoteServer*> &remoteServersWithData
327  );
328 
329  CloudServer::CloudDataList *GetOrAllocateCloudDataList(CloudKey key, bool *dataRepositoryExists, unsigned int &dataRepositoryIndex);
330 
331  void UnsubscribeFromKey(RemoteCloudClient *remoteCloudClient, RakNetGUID remoteCloudClientGuid, unsigned int keySubscriberIndex, CloudKey &cloudKey, DataStructures::List<RakNetGUID> &specificSystems);
332  void RemoveSpecificSubscriber(RakNetGUID specificSubscriber, CloudDataList *cloudDataList, RakNetGUID remoteCloudClientGuid);
333 
335 
337 };
338 
339 
340 } // namespace SLNet
341 
342 #endif
343 
344 
345 // Key subscription
346 //
347 // A given system can subscribe to one or more keys.
348 // The subscription can be further be defined as only subscribing to keys uploaded by or changed by a given system.
349 // It is possible to subscribe to keys not yet uploaded, or uploaded to another system
350 //
351 // Operations:
352 //
353 // 1. SubscribeToKey() - Get() operation with subscription
354 // A. Add to key subscription list for the client, which contains a keyId / specificUploaderList pair
355 // B. Send to remote servers that for this key, they should send us updates
356 // C. (Done, get operation returns current values)
357 //
358 // 2. UpdateData() - Post() operation
359 // A. Find all subscribers to this data, for the uploading system.
360 // B. Send them the uploaded data
361 // C. Find all servers that subscribe to this data
362 // D. Send them the uploaded data
363 //
364 // 3. DeleteData() - Release() operation
365 // A. Find all subscribers to this data, for the deleting system.
366 // B. Inform them of the deletion
367 // C. Find all servers that subscribe to this data
368 // D. Inform them of the deletion
369 //
370 // 4. Unsubscribe()
371 // A. Find this subscriber, and remove their subscription
372 // B. If no one else is subscribing to this key for any system, notify remote servers we no longer need subscription updates
373 //
374 // Internal operations:
375 //
376 // 1. Find if any connected client has subscribed to a given key
377 // A. This is used add and remove our subscription for this key to remote servers
378 //
379 // 2. For a given key and updating address, find all connected clients that care
380 // A. First find connected clients that have subscribed to this key, regardless of address
381 // B. Then find connected clients that have subscribed to this key for this particular address
382 //
383 // 3. Find all remote servers that have subscribed to a given key
384 // A. This is so when the key is updated or deleted, we know who to send it to
385 //
386 // 4. For a given client (such as on disconnect), remove all records of their subscriptions
387 
388 #endif // _RAKNET_SUPPORT_*