SLikeNet  0.1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ReliabilityLayer.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) 2016-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 
19 
20 
21 #ifndef __RELIABILITY_LAYER_H
22 #define __RELIABILITY_LAYER_H
23 
24 #include "memoryoverride.h"
25 #include "MTUSize.h"
26 #include "DS_LinkedList.h"
27 #include "DS_List.h"
28 #include "SocketLayer.h"
29 #include "PacketPriority.h"
30 #include "DS_Queue.h"
31 #include "BitStream.h"
32 #include "InternalPacket.h"
33 #include "statistics.h"
34 #include "DR_SHA1.h"
35 #include "DS_OrderedList.h"
36 #include "DS_RangeList.h"
37 #include "DS_BPlusTree.h"
38 #include "DS_MemoryPool.h"
39 #include "defines.h"
40 #include "DS_Heap.h"
41 #include "BitStream.h"
42 #include "NativeFeatureIncludes.h"
43 #include "SecureHandshake.h"
44 #include "PluginInterface2.h"
45 #include "Rand.h"
46 #include "socket2.h"
47 
48 #if USE_SLIDING_WINDOW_CONGESTION_CONTROL!=1
49 #include "CCRakNetUDT.h"
50 #define INCLUDE_TIMESTAMP_WITH_DATAGRAMS 1
51 #else
52 #include "CCRakNetSlidingWindow.h"
53 #define INCLUDE_TIMESTAMP_WITH_DATAGRAMS 0
54 #endif
55 
57 #define NUMBER_OF_ORDERED_STREAMS 32 // 2^5
58 
59 #define RESEND_TREE_ORDER 32
60 
61 namespace SLNet {
62 
64 class PluginInterface2;
67 
68 // int SplitPacketIndexComp( SplitPacketIndexType const &key, InternalPacket* const &data );
69 struct SplitPacketChannel//<SplitPacketChannel>
70 {
72 
74 
75 #if PREALLOCATE_LARGE_MESSAGES==1
76  InternalPacket *returnedPacket;
77  bool gotFirstPacket;
78  unsigned int stride;
79  unsigned int splitPacketsArrived;
80 #else
81  // This is here for progress notifications, since progress notifications return the first packet data, if available
83 #endif
84 
85 };
87 
88 // Helper class
89 struct BPSTracker
90 {
91  BPSTracker();
92  ~BPSTracker();
93  void Reset(const char *file, unsigned int line);
94  inline void Push1(CCTimeType time, uint64_t value1) {dataQueue.Push(TimeAndValue2(time,value1),_FILE_AND_LINE_); total1+=value1; lastSec1+=value1;}
95 // void Push2(SLNet::TimeUS time, uint64_t value1, uint64_t value2);
96  inline uint64_t GetBPS1(CCTimeType time) {(void) time; return lastSec1;}
97  inline uint64_t GetBPS1Threadsafe(CCTimeType time) {(void) time; return lastSec1;}
98 // uint64_t GetBPS2(RakNetTimeUS time);
99 // void GetBPS1And2(RakNetTimeUS time, uint64_t &out1, uint64_t &out2);
100  uint64_t GetTotal1(void) const;
101 // uint64_t GetTotal2(void) const;
102 
104  {
105  TimeAndValue2();
106  ~TimeAndValue2();
108  // TimeAndValue2(SLNet::TimeUS t, uint64_t v1, uint64_t v2);
109  // uint64_t value1, value2;
112  };
113 
115 // uint64_t total2, lastSec2;
117  void ClearExpired1(CCTimeType time);
118 // void ClearExpired2(SLNet::TimeUS time);
119 };
120 
122 class ReliabilityLayer//<ReliabilityLayer>
123 {
124 public:
125 
126  // Constructor
128 
129  // Destructor
131 
133  void Reset( bool resetVariables, int MTUSize, bool _useSecurity );
134 
138  void SetTimeoutTime(SLNet::TimeMS time );
139 
143 
154  const char *buffer, unsigned int length, SystemAddress &systemAddress, DataStructures::List<PluginInterface2*> &messageHandlerList, int MTUSize,
155  RakNetSocket2 *s, RakNetRandom *rnr, CCTimeType timeRead, BitStream &updateBitStream);
156 
160  BitSize_t Receive( unsigned char**data );
161 
173  bool Send( char *data, BitSize_t numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, unsigned char orderingChannel, bool makeDataCopy, int MTUSize, CCTimeType currentTime, uint32_t receipt );
174 
182  void Update( RakNetSocket2 *s, SystemAddress &systemAddress, int MTUSize, CCTimeType time,
183  unsigned bitsPerSecondLimit,
184  DataStructures::List<PluginInterface2*> &messageHandlerList,
185  RakNetRandom *rnr, BitStream &updateBitStream);
186 
189  bool IsDeadConnection( void ) const;
190 
192  void KillConnection(void);
193 
197 
199  bool IsOutgoingDataWaiting(void);
200  bool AreAcksWaiting(void);
201 
202  // Set outgoing lag and packet loss properties
203  void ApplyNetworkSimulator( double _maxSendBPS, SLNet::TimeMS _minExtraPing, SLNet::TimeMS _extraPingVariance );
204 
207  bool IsNetworkSimulatorActive( void );
208 
209  void SetSplitMessageProgressInterval(int interval);
210  void SetUnreliableTimeout(SLNet::TimeMS timeoutMS);
212  bool AckTimeout(SLNet::Time curTime);
213  CCTimeType GetNextSendTime(void) const;
214  CCTimeType GetTimeBetweenPackets(void) const;
215 #if INCLUDE_TIMESTAMP_WITH_DATAGRAMS==1
216  CCTimeType GetAckPing(void) const;
217 #endif
218  SLNet::TimeMS GetTimeLastDatagramArrived(void) const {return timeLastDatagramArrived;}
219 
220  // If true, will update time between packets quickly based on ping calculations
221  //void SetDoFastThroughputReactions(bool fast);
222 
223  // Encoded as numMessages[unsigned int], message1BitLength[unsigned int], message1Data (aligned), ...
224  //void GetUndeliveredMessages(SLNet::BitStream *messages, int MTUSize);
225 
226 private:
231  void SendBitStream( RakNetSocket2 *s, SystemAddress &systemAddress, SLNet::BitStream *bitStream, RakNetRandom *rnr, CCTimeType currentTime);
232 
235  BitSize_t WriteToBitStreamFromInternalPacket(SLNet::BitStream *bitStream, const InternalPacket *const internalPacket, CCTimeType curTime );
236 
237 
239  InternalPacket* CreateInternalPacketFromBitStream(SLNet::BitStream *bitStream, CCTimeType time );
240 
242  unsigned RemovePacketFromResendListAndDeleteOlderReliableSequenced( const MessageNumberType messageNumber, CCTimeType time, DataStructures::List<PluginInterface2*> &messageHandlerList, const SystemAddress &systemAddress );
243 
245  void SendAcknowledgementPacket( const DatagramSequenceNumberType messageNumber, CCTimeType time);
246 
248  bool IsSendThrottled( int MTUSize );
249 
251  void UpdateWindowFromPacketloss( CCTimeType time );
252 
254  void UpdateWindowFromAck( CCTimeType time );
255 
257  BitSize_t GetMaxMessageHeaderLengthBits( void );
258  BitSize_t GetMessageHeaderLengthBits( const InternalPacket *const internalPacket );
259 
261  void GetSHA1( unsigned char * const buffer, unsigned int nbytes, char code[ SHA1_LENGTH ] );
262 
264  bool CheckSHA1( char code[ SHA1_LENGTH ], unsigned char * const buffer, unsigned int nbytes );
265 
267 // void DeleteSequencedPacketsInList( unsigned char orderingChannel, DataStructures::List<InternalPacket*>&theList, int splitPacketId = -1 );
268 
270 // void DeleteSequencedPacketsInList( unsigned char orderingChannel, DataStructures::Queue<InternalPacket*>&theList );
271 
273  bool IsOlderOrderedPacket( OrderingIndexType newPacketOrderingIndex, OrderingIndexType waitingForPacketOrderingIndex );
274 
276  void SplitPacket( InternalPacket *internalPacket );
277 
279  void InsertIntoSplitPacketList( InternalPacket * internalPacket, CCTimeType time );
280 
282  InternalPacket * BuildPacketFromSplitPacketList( SplitPacketIdType inSplitPacketId, CCTimeType time,
283  RakNetSocket2 *s, SystemAddress &systemAddress, RakNetRandom *rnr, BitStream &updateBitStream);
284  InternalPacket * BuildPacketFromSplitPacketList( SplitPacketChannel *splitPacketChannel, CCTimeType time );
285 
287  //void DeleteOldUnreliableSplitPackets( CCTimeType time );
288 
291  InternalPacket * CreateInternalPacketCopy( InternalPacket *original, int dataByteOffset, int dataByteLength, CCTimeType time );
292 
294  // DataStructures::LinkedList<InternalPacket*> *GetOrderingListAtOrderingStream( unsigned char orderingChannel );
295 
297  // void AddToOrderingList( InternalPacket * internalPacket );
298 
300  void InsertPacketIntoResendList( InternalPacket *internalPacket, CCTimeType time, bool firstResend, bool modifyUnacknowledgedBytes );
301 
303  void FreeMemory( bool freeAllImmediately );
304 
306  void FreeThreadSafeMemory( void );
307 
308  // Initialize the variables
309  void InitializeVariables( void );
310 
312  bool IsExpiredTime(unsigned int input, CCTimeType currentTime) const;
313 
314  // Make it so we don't do resends within a minimum threshold of time
315  void UpdateNextActionTime(void);
316 
317 
319  //unsigned int IsReceivedPacketHole(unsigned int input, SLNet::TimeMS currentTime) const;
320 
322  //unsigned int MakeReceivedPacketHole(unsigned int input) const;
323 
325  unsigned int GetResendListDataSize(void) const;
326 
328  void UpdateThreadedMemory(void);
329 
330  void CalculateHistogramAckSize(void);
331 
332  // Used ONLY for RELIABLE_ORDERED
333  // RELIABLE_SEQUENCED just returns the newest one
334  // DataStructures::List<DataStructures::LinkedList<InternalPacket*>*> orderingList;
336  int splitMessageProgressInterval;
337  CCTimeType unreliableTimeout;
338 
339  struct MessageNumberNode
340  {
341  DatagramSequenceNumberType messageNumber;
342  MessageNumberNode *next;
343  };
344  struct DatagramHistoryNode
345  {
346  DatagramHistoryNode() {}
347  DatagramHistoryNode(MessageNumberNode *_head, CCTimeType ts
348  ) :
349  head(_head), timeSent(ts)
350  {}
351  MessageNumberNode *head;
352  CCTimeType timeSent;
353  };
354  // Queue length is programmatically restricted to DATAGRAM_MESSAGE_ID_ARRAY_LENGTH
355  // This is essentially an O(1) lookup to get a DatagramHistoryNode given an index
356  // datagramHistory holds a linked list of MessageNumberNode. Each MessageNumberNode refers to one element in resendList which can be cleared on an ack.
358  DataStructures::MemoryPool<MessageNumberNode> datagramHistoryMessagePool;
359 
360  struct UnreliableWithAckReceiptNode
361  {
362  UnreliableWithAckReceiptNode() {}
363  UnreliableWithAckReceiptNode(DatagramSequenceNumberType _datagramNumber, uint32_t _sendReceiptSerial, SLNet::TimeUS _nextActionTime) :
364  datagramNumber(_datagramNumber), sendReceiptSerial(_sendReceiptSerial), nextActionTime(_nextActionTime)
365  {}
366  DatagramSequenceNumberType datagramNumber;
367  uint32_t sendReceiptSerial;
368  SLNet::TimeUS nextActionTime;
369  };
370  DataStructures::List<UnreliableWithAckReceiptNode> unreliableWithAckReceiptHistory;
371 
372  void RemoveFromDatagramHistory(DatagramSequenceNumberType index);
373  MessageNumberNode* GetMessageNumberNodeByDatagramIndex(DatagramSequenceNumberType index, CCTimeType *timeSent);
374  void AddFirstToDatagramHistory(DatagramSequenceNumberType datagramNumber, CCTimeType timeSent);
375  MessageNumberNode* AddFirstToDatagramHistory(DatagramSequenceNumberType datagramNumber, DatagramSequenceNumberType messageNumber, CCTimeType timeSent);
376  MessageNumberNode* AddSubsequentToDatagramHistory(MessageNumberNode *messageNumberNode, DatagramSequenceNumberType messageNumber);
377  DatagramSequenceNumberType datagramHistoryPopCount;
378 
380  // DataStructures::BPlusTree<DatagramSequenceNumberType, InternalPacket*, RESEND_TREE_ORDER> resendTree;
381  InternalPacket *resendBuffer[RESEND_BUFFER_ARRAY_LENGTH];
382  InternalPacket *resendLinkedListHead;
383  InternalPacket *unreliableLinkedListHead;
384  void RemoveFromUnreliableLinkedList(InternalPacket *internalPacket);
385  void AddToUnreliableLinkedList(InternalPacket *internalPacket);
386 // unsigned int numPacketsOnResendBuffer;
387  //unsigned int blockWindowIncreaseUntilTime;
388  // DataStructures::RangeList<DatagramSequenceNumberType> acknowlegements;
389  // Resend list is a tree of packets we need to resend
390 
391  // Set to the current time when the resend queue is no longer empty
392  // Set to zero when it becomes empty
393  // Set to the current time if it is not zero, and we get incoming data
394  // If the current time - timeResendQueueNonEmpty is greater than a threshold, we are disconnected
395 // CCTimeType timeResendQueueNonEmpty;
396  SLNet::TimeMS timeLastDatagramArrived;
397 
398 
399  // If we backoff due to packetloss, don't remeasure until all waiting resends have gone out or else we overcount
400 // bool packetlossThisSample;
401 // int backoffThisSample;
402 // unsigned packetlossThisSampleResendCount;
403 // CCTimeType lastPacketlossTime;
404 
405  //DataStructures::Queue<InternalPacket*> sendPacketSet[ NUMBER_OF_PRIORITIES ];
407  reliabilityHeapWeightType outgoingPacketBufferNextWeights[NUMBER_OF_PRIORITIES];
408  void InitHeapWeights(void);
409  reliabilityHeapWeightType GetNextWeight(int priorityLevel);
410 // unsigned int messageInSendBuffer[NUMBER_OF_PRIORITIES];
411 // double bytesInSendBuffer[NUMBER_OF_PRIORITIES];
412 
413 
415 
416  MessageNumberType sendReliableMessageNumberIndex;
417  MessageNumberType internalOrderIndex;
418  //unsigned int windowSize;
419  //SLNet::BitStream updateBitStream;
420  bool deadConnection, cheater;
421  SplitPacketIdType splitPacketId;
422  SLNet::TimeMS timeoutTime; // How long to wait in MS before timing someone out
423  //int MAX_AVERAGE_PACKETS_PER_SECOND; // Name says it all
424 // int RECEIVED_PACKET_LOG_LENGTH, requestedReceivedPacketLogLength; // How big the receivedPackets array is
425 // unsigned int *receivedPackets;
426  RakNetStatistics statistics;
427 
428  // Algorithm for blending ordered and sequenced on the same channel:
429  // 1. Each ordered message transmits OrderingIndexType orderedWriteIndex. There are NUMBER_OF_ORDERED_STREAMS independent values of these. The value
430  // starts at 0. Every time an ordered message is sent, the value increments by 1
431  // 2. Each sequenced message contains the current value of orderedWriteIndex for that channel, and additionally OrderingIndexType sequencedWriteIndex.
432  // sequencedWriteIndex resets to 0 every time orderedWriteIndex increments. It increments by 1 every time a sequenced message is sent.
433  // 3. The receiver maintains the next expected value for the orderedWriteIndex, stored in orderedReadIndex.
434  // 4. As messages arrive:
435  // If a message has the current ordering index, and is sequenced, and is < the current highest sequence value, discard
436  // If a message has the current ordering index, and is sequenced, and is >= the current highest sequence value, return immediately
437  // If a message has a greater ordering index, and is sequenced or ordered, buffer it
438  // If a message has the current ordering index, and is ordered, buffer, then push off messages from buffer
439  // 5. Pushing off messages from buffer:
440  // Messages in buffer are put in a minheap. The value of each node is calculated such that messages are returned:
441  // A. (lowest ordering index, lowest sequence index)
442  // B. (lowest ordering index, no sequence index)
443  // Messages are pushed off until the heap is empty, or the next message to be returned does not preserve the ordered index
444  // For an empty heap, the heap weight should start at the lowest value based on the next expected ordering index, to avoid variable overflow
445 
446  // Sender increments this by 1 for every ordered message sent
447  OrderingIndexType orderedWriteIndex[NUMBER_OF_ORDERED_STREAMS];
448  // Sender increments by 1 for every sequenced message sent. Resets to 0 when an ordered message is sent
449  OrderingIndexType sequencedWriteIndex[NUMBER_OF_ORDERED_STREAMS];
450  // Next expected index for ordered messages.
452  // Highest value received for sequencedWriteIndex for the current value of orderedReadIndex on the same channel.
453  OrderingIndexType highestSequencedReadIndex[NUMBER_OF_ORDERED_STREAMS];
456 
457 
458 
459 
460 
461 
462 
463 // CCTimeType histogramStart;
464 // unsigned histogramBitsSent;
465 
466 
475  // DataStructures::Queue<CCTimeType> hasReceivedPacketQueue;
476  DataStructures::Queue<bool> hasReceivedPacketQueue;
477  DatagramSequenceNumberType receivedPacketsBaseIndex;
478  bool resetReceivedPackets;
479 
480  CCTimeType lastUpdateTime;
481  CCTimeType timeBetweenPackets, nextSendTime;
482 #if INCLUDE_TIMESTAMP_WITH_DATAGRAMS==1
483  CCTimeType ackPing;
484 #endif
485 // CCTimeType ackPingSamples[ACK_PING_SAMPLES_SIZE]; // Must be range of unsigned char to wrap ackPingIndex properly
486  CCTimeType ackPingSum;
487  unsigned char ackPingIndex;
488  //CCTimeType nextLowestPingReset;
489  RemoteSystemTimeType remoteSystemTime;
490 // bool continuousSend;
491 // CCTimeType lastTimeBetweenPacketsIncrease,lastTimeBetweenPacketsDecrease;
492  // Limit changes in throughput to once per ping - otherwise even if lag starts we don't know about it
493  // In the meantime the connection is flooded and overrun.
494  CCTimeType nextAllowedThroughputSample;
495  bool bandwidthExceededStatistic;
496 
497  // If Update::maxBitsPerSecond > 0, then throughputCapCountdown is used as a timer to prevent sends for some amount of time after each send, depending on
498  // the amount of data sent
499  long long throughputCapCountdown;
500 
501  unsigned receivePacketCount;
502 
503 #ifdef _DEBUG
504  struct DataAndTime//<InternalPacket>
505  {
506  RakNetSocket2 *s;
507  char data[ MAXIMUM_MTU_SIZE ];
508  unsigned int length;
509  SLNet::TimeMS sendTime;
510  // SystemAddress systemAddress;
511  unsigned short remotePortRakNetWasStartedOn_PS3;
512  unsigned int extraSocketOptions;
513  };
515 
516  // Internet simulator
517  double packetloss;
518  SLNet::TimeMS minExtraPing, extraPingVariance;
519 #endif
520 
521  CCTimeType elapsedTimeSinceLastUpdate;
522 
523  CCTimeType nextAckTimeToSend;
524 
525 
526 #if USE_SLIDING_WINDOW_CONGESTION_CONTROL==1
527  SLNet::CCRakNetSlidingWindow congestionManager;
528 #else
529  SLNet::CCRakNetUDT congestionManager;
530 #endif
531 
532 
533  uint32_t unacknowledgedBytes;
534 
535  bool ResendBufferOverflow(void) const;
536  void ValidateResendList(void) const;
537  void ResetPacketsAndDatagrams(void);
538  void PushPacket(CCTimeType time, InternalPacket *internalPacket, bool isReliable);
539  void PushDatagram(void);
540  bool TagMostRecentPushAsSecondOfPacketPair(void);
541  void ClearPacketsAndDatagrams(void);
542  void MoveToListHead(InternalPacket *internalPacket);
543  void RemoveFromList(InternalPacket *internalPacket, bool modifyUnacknowledgedBytes);
544  void AddToListTail(InternalPacket *internalPacket, bool modifyUnacknowledgedBytes);
545  void PopListHead(bool modifyUnacknowledgedBytes);
546  bool IsResendQueueEmpty(void) const;
547  void SortSplitPacketList(DataStructures::List<InternalPacket*> &data, unsigned int leftEdge, unsigned int rightEdge) const;
548  void SendACKs(RakNetSocket2 *s, SystemAddress &systemAddress, CCTimeType time, RakNetRandom *rnr, BitStream &updateBitStream);
549 
550  DataStructures::List<InternalPacket*> packetsToSendThisUpdate;
551  DataStructures::List<bool> packetsToDeallocThisUpdate;
552  // boundary is in packetsToSendThisUpdate, inclusive
553  DataStructures::List<unsigned int> packetsToSendThisUpdateDatagramBoundaries;
554  DataStructures::List<bool> datagramsToSendThisUpdateIsPair;
555  DataStructures::List<unsigned int> datagramSizesInBytes;
556  BitSize_t datagramSizeSoFar;
557  BitSize_t allDatagramSizesSoFar;
558  double totalUserDataBytesAcked;
559  CCTimeType timeOfLastContinualSend;
560  CCTimeType timeToNextUnreliableCull;
561 
562  // This doesn't need to be a member, but I do it to avoid reallocations
564 
565  // Every 16 datagrams, we make sure the 17th datagram goes out the same update tick, and is the same size as the 16th
566  int countdownToNextPacketPair;
567  InternalPacket* AllocateFromInternalPacketPool(void);
568  void ReleaseToInternalPacketPool(InternalPacket *ip);
569 
572  bool remoteSystemNeedsBAndAS;
573 
574  unsigned int GetMaxDatagramSizeExcludingMessageHeaderBytes(void);
575  BitSize_t GetMaxDatagramSizeExcludingMessageHeaderBits(void);
576 
577  // ourOffset refers to a section within externallyAllocatedPtr. Do not deallocate externallyAllocatedPtr until all references are lost
578  void AllocInternalPacketData(InternalPacket *internalPacket, InternalPacketRefCountedData **refCounter, unsigned char *externallyAllocatedPtr, unsigned char *ourOffset);
579  // Set the data pointer to externallyAllocatedPtr, do not allocate
580  void AllocInternalPacketData(InternalPacket *internalPacket, unsigned char *externallyAllocatedPtr);
581  // Allocate new
582  void AllocInternalPacketData(InternalPacket *internalPacket, unsigned int numBytes, bool allowStack, const char *file, unsigned int line);
583  void FreeInternalPacketData(InternalPacket *internalPacket, const char *file, unsigned int line);
585 
586  BPSTracker bpsMetrics[RNS_PER_SECOND_METRICS_COUNT];
587  CCTimeType lastBpsClear;
588 
589 #if LIBCAT_SECURITY==1
590 public:
591  cat::AuthenticatedEncryption* GetAuthenticatedEncryption(void) { return &auth_enc; }
592 
593 protected:
594  cat::AuthenticatedEncryption auth_enc;
595  bool useSecurity;
596 #endif // LIBCAT_SECURITY
597 };
598 
599 } // namespace SLNet
600 
601 #endif