SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
48 class RAK_DLL_EXPORT CloudServerQueryFilter
49 {
50 public:
51 CloudServerQueryFilter() {}
52 virtual ~CloudServerQueryFilter() {}
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
75 class RAK_DLL_EXPORT CloudServer : public PluginInterface2, CloudAllocator
76 {
77 public:
78 // GetInstance() and DestroyInstance(instance*)
79 STATIC_FACTORY_DECLARATIONS(CloudServer)
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 {
154 CloudData() {}
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
162 uint32_t dataLengthBytes;
163 bool isUploaded;
164
166 SystemAddress serverSystemAddress;
167
169 SystemAddress clientSystemAddress;
170
172 RakNetGUID serverGUID;
173
175 RakNetGUID clientGUID;
176
179 DataStructures::OrderedList<RakNetGUID, RakNetGUID> specificSubscribers;
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 );
185 struct CloudDataList
186 {
187 bool IsUnused(void) const {return keyData.Size()==0 && nonSpecificSubscribers.Size()==0;}
188 bool IsNotUploaded(void) const {return uploaderCount==0;}
189 bool RemoveSubscriber(RakNetGUID g) {
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;
203 CloudKey key;
204
205 // Data uploaded from or subscribed to for various systems
206 DataStructures::OrderedList<RakNetGUID, CloudData*, CloudServer::KeyDataPtrComp> keyData;
207
210 DataStructures::OrderedList<RakNetGUID, RakNetGUID> nonSpecificSubscribers;
211 };
212
213 static int KeyDataListComp( const CloudKey &key, CloudDataList * const &data );
214 DataStructures::OrderedList<CloudKey, CloudDataList*, CloudServer::KeyDataListComp> dataRepository;
215
216 struct KeySubscriberID
217 {
218 CloudKey key;
219 DataStructures::OrderedList<RakNetGUID, RakNetGUID> specificSystemsSubscribedTo;
220 };
221 static int KeySubscriberIDComp(const CloudKey &key, KeySubscriberID * const &data );
222
223 // Remote systems
224 struct RemoteCloudClient
225 {
226 bool IsUnused(void) const {return uploadedKeys.Size()==0 && subscribedKeys.Size()==0;}
227
228 DataStructures::OrderedList<CloudKey,CloudKey,CloudKeyComp> uploadedKeys;
229 DataStructures::OrderedList<CloudKey,KeySubscriberID*,CloudServer::KeySubscriberIDComp> subscribedKeys;
230 uint64_t uploadedBytes;
231 };
232 DataStructures::Hash<RakNetGUID, RemoteCloudClient*, 2048, RakNetGUID::ToUint32> remoteSystems;
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
244 struct RemoteServer
245 {
246 RakNetGUID serverAddress;
247 // This server needs to know about these keys when they are updated or deleted
248 DataStructures::OrderedList<CloudKey,CloudKey,CloudKeyComp> subscribedKeys;
249 // This server has uploaded these keys, and needs to know about Get() requests
250 DataStructures::OrderedList<CloudKey,CloudKey,CloudKeyComp> uploadedKeys;
251
252 // Just for processing
253 bool workingFlag;
254
255 // If false, we don't know what keys they have yet, so send everything
256 bool gotSubscribedAndUploadedKeys;
257 };
258
259 static int RemoteServerComp(const RakNetGUID &key, RemoteServer* const &data );
260 DataStructures::OrderedList<RakNetGUID, RemoteServer*, CloudServer::RemoteServerComp> remoteServers;
261
262 struct BufferedGetResponseFromServer
263 {
264 void Clear(CloudAllocator *allocator);
265
266 RakNetGUID serverAddress;
267 CloudQueryResult queryResult;
268 bool gotResult;
269 };
270
271 struct CloudQueryWithAddresses
272 {
273 // Inputs
274 CloudQuery cloudQuery;
275 DataStructures::List<RakNetGUID> specificSystems;
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;
285 CloudQueryWithAddresses cloudQueryWithAddresses;
286
287 // When request started. If takes too long for a response from another system, can abort remaining systems
288 SLNet::Time requestStartTime;
289
290 // Assigned by server that gets the request to identify response. See nextGetRequestId
291 uint32_t requestId;
292
293 RakNetGUID requestingClient;
294
295 DataStructures::OrderedList<RakNetGUID, BufferedGetResponseFromServer*, CloudServer::BufferedGetResponseFromServerComp> remoteServerResponses;
296 };
297 static int GetRequestComp(const uint32_t &key, GetRequest* const &data );
298 DataStructures::OrderedList<uint32_t, GetRequest*, CloudServer::GetRequestComp> getRequests;
299 SLNet::Time nextGetRequestsCheck;
300
301 uint32_t nextGetRequestId;
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(
325 DataStructures::List<CloudKey> &keys,
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
334 DataStructures::List<CloudServerQueryFilter*> queryFilters;
335
336 SystemAddress forceAddress;
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_*