SLikeNet  0.1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RakPeer.cpp
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-2019, 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 
16 // \file
17 //
18 
19 
20 
21 #define CAT_NEUTER_EXPORT /* Neuter dllimport for libcat */
22 
23 #include "slikenet/defines.h"
24 #include "slikenet/peer.h"
25 #include "slikenet/types.h"
26 
27 #ifdef _WIN32
28 
29 #else
30 #include <unistd.h>
31 #endif
32 
33 // #if defined(new)
34 // #pragma push_macro("new")
35 // #undef new
36 // #define RMO_NEW_UNDEF_ALLOCATING_QUEUE
37 // #endif
38 
39 #include <time.h>
40 #include <ctype.h> // toupper
41 #include <string.h>
42 #include "slikenet/GetTime.h"
45 #include "slikenet/Rand.h"
48 #include "slikenet/StringTable.h"
50 #include "slikenet/types.h"
51 #include "slikenet/DR_SHA1.h"
52 #include "slikenet/sleep.h"
53 #include "slikenet/assert.h"
54 #include "slikenet/version.h"
56 #include "slikenet/gettimeofday.h"
57 #include "slikenet/SignaledEvent.h"
58 #include "slikenet/SuperFastHash.h"
59 #include "slikenet/alloca.h"
61 #include "slikenet/linux_adapter.h"
62 #include "slikenet/osx_adapter.h"
63 
64 #ifdef USE_THREADED_SEND
65 #include "slikenet/SendToThread.h"
66 #endif
67 
68 #ifdef CAT_AUDIT
69 #define CAT_AUDIT_PRINTF(...) printf(__VA_ARGS__)
70 #else
71 #define CAT_AUDIT_PRINTF(...)
72 #endif
73 
74 namespace SLNet
75 {
76 RAK_THREAD_DECLARATION(UpdateNetworkLoop);
77 RAK_THREAD_DECLARATION(RecvFromLoop);
78 RAK_THREAD_DECLARATION(UDTConnect);
79 }
80 #define REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE 8
81 
82 #if !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ )
83 #include <stdlib.h> // malloc
84 #endif
85 
86 
87 
88 #if defined(_WIN32)
89 //
90 #else
91 /*
92 #include <alloca.h> // Console 2
93 #include <stdlib.h>
94 extern bool _extern_Console2LoadModules(void);
95 extern int _extern_Console2GetConnectionStatus(void);
96 extern int _extern_Console2GetLobbyStatus(void);
97 //extern bool Console2StartupFluff(unsigned int *);
98 extern void Console2ShutdownFluff(void);
99 //extern unsigned int Console2ActivateConnection(unsigned int, void *);
100 //extern bool Console2BlockOnEstablished(void);
101 extern void Console2GetIPAndPort(unsigned int, char *, unsigned short *, unsigned int );
102 //extern void Console2DeactivateConnection(unsigned int, unsigned int);
103 */
104 #endif
105 
106 
107 static const int NUM_MTU_SIZES=3;
108 
109 
110 
111 static const int mtuSizes[NUM_MTU_SIZES]={MAXIMUM_MTU_SIZE, 1200, 576};
112 
113 
114 // Note to self - if I change this it might affect RECIPIENT_OFFLINE_MESSAGE_INTERVAL in Natpunchthrough.cpp
115 //static const int MAX_OPEN_CONNECTION_REQUESTS=8;
116 //static const int TIME_BETWEEN_OPEN_CONNECTION_REQUESTS=500;
117 
118 using namespace SLNet;
119 
121 
122 /*
123 struct RakPeerAndIndex
124 {
125  RakNetSocket2 *s;
126  RakPeer *rakPeer;
127 };
128 */
129 
130 static const unsigned int MAX_OFFLINE_DATA_LENGTH=400; // I set this because I limit ID_CONNECTION_REQUEST to 512 bytes, and the password is appended to that packet.
131 
132 // Used to distinguish between offline messages with data, and messages from the reliability layer
133 // Should be different than any message that could result from messages from the reliability layer
134 // Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false
135 static const unsigned char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78};
136 
137 struct PacketFollowedByData
138 {
139  Packet p;
140  unsigned char data[1];
141 };
142 
143 Packet *RakPeer::AllocPacket(unsigned dataSize, const char *file, unsigned int line)
144 {
145  // Crashes when dataSize is 4 bytes - not sure why
146 // unsigned char *data = (unsigned char *) rakMalloc_Ex(sizeof(PacketFollowedByData)+dataSize, file, line);
147 // Packet *p = &((PacketFollowedByData *)data)->p;
148 // p->data=((PacketFollowedByData *)data)->data;
149 // p->length=dataSize;
150 // p->bitSize=BYTES_TO_BITS(dataSize);
151 // p->deleteData=false;
152 // p->guid=UNASSIGNED_RAKNET_GUID;
153 // return p;
154 
155  SLNet::Packet *p;
157  p = packetAllocationPool.Allocate(file,line);
159  p = new ((void*)p) Packet;
160  p->data=(unsigned char*) rakMalloc_Ex(dataSize,file,line);
161  p->length=dataSize;
162  p->bitSize=BYTES_TO_BITS(dataSize);
163  p->deleteData=true;
165  p->wasGeneratedLocally=false;
166  return p;
167 }
168 
169 Packet *RakPeer::AllocPacket(unsigned dataSize, unsigned char *data, const char *file, unsigned int line)
170 {
171  // Packet *p = (Packet *)rakMalloc_Ex(sizeof(Packet), file, line);
172  SLNet::Packet *p;
174  p = packetAllocationPool.Allocate(file,line);
176  p = new ((void*)p) Packet;
177  RakAssert(p);
178  p->data=data;
179  p->length=dataSize;
180  p->bitSize=BYTES_TO_BITS(dataSize);
181  p->deleteData=true;
183  p->wasGeneratedLocally=false;
184  return p;
185 }
186 
188 
189 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
190 // Constructor
191 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
193 {
194 #if LIBCAT_SECURITY==1
195  // Encryption and security
196  CAT_AUDIT_PRINTF("AUDIT: Initializing RakPeer security flags: using_security = false, server_handshake = null, cookie_jar = null\n");
197  _using_security = false;
198  _server_handshake = 0;
199  _cookie_jar = 0;
200 #endif
201 
205 
206  defaultMTUSize = mtuSizes[NUM_MTU_SIZES-1];
207  trackFrequencyTable = false;
208  maximumIncomingConnections = 0;
209  maximumNumberOfPeers = 0;
210  //remoteSystemListSize=0;
211  remoteSystemList = 0;
212  activeSystemList = 0;
213  activeSystemListSize=0;
214  remoteSystemLookup=0;
215  bytesSentPerSecond = bytesReceivedPerSecond = 0;
216  endThreads = true;
217  isMainLoopThreadActive = false;
218  incomingDatagramEventHandler=0;
219 
220 
221 
222 
223 
224  // isRecvfromThreadActive=false;
225 #if defined(GET_TIME_SPIKE_LIMIT) && GET_TIME_SPIKE_LIMIT>0
226  occasionalPing = true;
227 #else
228  occasionalPing = false;
229 #endif
230  allowInternalRouting=false;
231  for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
232  ipList[i]=UNASSIGNED_SYSTEM_ADDRESS;
233  allowConnectionResponseIPMigration = false;
234  //incomingPasswordLength=outgoingPasswordLength=0;
235  incomingPasswordLength=0;
236  splitMessageProgressInterval=0;
237  //unreliableTimeout=0;
238  unreliableTimeout=1000;
239  maxOutgoingBPS=0;
240  firstExternalID=UNASSIGNED_SYSTEM_ADDRESS;
241  myGuid=UNASSIGNED_RAKNET_GUID;
242  userUpdateThreadPtr=0;
243  userUpdateThreadData=0;
244 
245 #ifdef _DEBUG
246  // Wait longer to disconnect in debug so I don't get disconnected while tracing
247  defaultTimeoutTime=30000;
248 #else
249  defaultTimeoutTime=10000;
250 #endif
251 
252 #ifdef _DEBUG
253  _packetloss=0.0;
254  _minExtraPing=0;
255  _extraPingVariance=0;
256 #endif
257 
258  bufferedCommands.SetPageSize(sizeof(BufferedCommandStruct)*16);
259  socketQueryOutput.SetPageSize(sizeof(SocketQueryOutput)*8);
260 
261  packetAllocationPoolMutex.Lock();
262  packetAllocationPool.SetPageSize(sizeof(DataStructures::MemoryPool<Packet>::MemoryWithPage)*32);
263  packetAllocationPoolMutex.Unlock();
264 
265  remoteSystemIndexPool.SetPageSize(sizeof(DataStructures::MemoryPool<RemoteSystemIndex>::MemoryWithPage)*32);
266 
267 
268 
269 
270 
271 
272 
273 
274 
275 
276 
277 
278 
279 
280 
281 
282 
283 
284 
285 
286 
287 
288 
289 
290 
291 
292 
293 
294 
295 
296 
297 
298 
299 
300 
301 
302 
303 
304 
305 
306 
307 
308 
309  GenerateGUID();
310 
311  quitAndDataEvents.InitEvent();
312  limitConnectionFrequencyFromTheSameIP=false;
313  ResetSendReceipt();
314 }
315 
316 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
317 // Destructor
318 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
320 {
321  Shutdown( 0, 0 );
322 
323  // Free the ban list.
324  ClearBanList();
325 
329 
331 
332 #if LIBCAT_SECURITY==1
333  // Encryption and security
334  CAT_AUDIT_PRINTF("AUDIT: Deleting RakPeer security objects, handshake = %x, cookie jar = %x\n", _server_handshake, _cookie_jar);
335  if (_server_handshake) SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
336  if (_cookie_jar) SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
337 #endif
338 
339 
340 
341 
342 
343 
344 
345 
346 
347 
348 
349 
350 
351 
352 
353 
354 // for (unsigned int i=0; i < pluginListTS.Size(); i++)
355 // pluginListTS[i]->SetRakPeerInterface(0);
356 // for (unsigned int i=0; i < pluginListNTS.Size(); i++)
357 // pluginListNTS[i]->SetRakPeerInterface(0);
358 }
359 
360 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
361 // \brief Starts the network threads, opens the listen port.
362 // You must call this before calling Connect().
363 // Multiple calls while already active are ignored. To call this function again with different settings, you must first call Shutdown().
364 // \note Call SetMaximumIncomingConnections if you want to accept incoming connections
365 // \param[in] maxConnections The maximum number of connections between this instance of RakPeer and another instance of RakPeer. Required so the network can preallocate and for thread safety. A pure client would set this to 1. A pure server would set it to the number of allowed clients.- A hybrid would set it to the sum of both types of connections
366 // \param[in] localPort The port to listen for connections on.
367 // \param[in] _threadSleepTimer How many ms to Sleep each internal update cycle. With new congestion control, the best results will be obtained by passing 10.
368 // \param[in] socketDescriptors An array of SocketDescriptor structures to force RakNet to listen on a particular IP address or port (or both). Each SocketDescriptor will represent one unique socket. Do not pass redundant structures. To listen on a specific port, you can pass &socketDescriptor, 1SocketDescriptor(myPort,0); such as for a server. For a client, it is usually OK to just pass SocketDescriptor();
369 // \param[in] socketDescriptorCount The size of the \a socketDescriptors array. Pass 1 if you are not sure what to pass.
370 // \return False on failure (can't create socket or thread), true on success.
371 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
372 StartupResult RakPeer::Startup( unsigned int maxConnections, SocketDescriptor *socketDescriptors, unsigned socketDescriptorCount, int threadPriority )
373 {
374  if (IsActive())
375  return RAKNET_ALREADY_STARTED;
376 
377  // If getting the guid failed in the constructor, try again
378  if (myGuid.g==0)
379  {
380  GenerateGUID();
381  if (myGuid.g==0)
383  }
384 
385  if (threadPriority==-99999)
386  {
387 
388 
389 #if defined(_WIN32)
390  threadPriority=0;
391 
392 
393 
394 
395 #else
396  threadPriority=1000;
397 #endif
398  }
399 
400 
401  FillIPList();
402 
404  {
406  }
407 
408  //RakPeerAndIndex rpai[32];
409  //RakAssert(socketDescriptorCount<32);
410 
411  RakAssert(socketDescriptors && socketDescriptorCount>=1);
412 
413  if (socketDescriptors==0 || socketDescriptorCount<1)
415 
416  //unsigned short localPort;
417  //localPort=socketDescriptors[0].port;
418 
419  RakAssert( maxConnections > 0 );
420 
421  if ( maxConnections <= 0 )
423 
424  DerefAllSockets();
425 
426 
427  unsigned i;
428  // Go through all socket descriptors and precreate sockets on the specified addresses
429  for (i=0; i<socketDescriptorCount; i++)
430  {
431  /*
432  const char *addrToBind;
433  if (socketDescriptors[i].hostAddress[0]==0)
434  addrToBind=0;
435  else
436  addrToBind=socketDescriptors[i].hostAddress;
437  */
438 
439 
440 
441 
442 
443 
444 
445 
446 
447  /*
448 #if RAKNET_SUPPORT_IPV6==1
449  if (SocketLayer::IsSocketFamilySupported(addrToBind, socketDescriptors[i].socketFamily)==false)
450  return SOCKET_FAMILY_NOT_SUPPORTED;
451 #endif
452 
453  if (socketDescriptors[i].port!=0 && SocketLayer::IsPortInUse(socketDescriptors[i].port, addrToBind, socketDescriptors[i].socketFamily)==true)
454  {
455  DerefAllSockets();
456  return SOCKET_PORT_ALREADY_IN_USE;
457  }
458 
459  RakNetSocket* rns = 0;
460  if (socketDescriptors[i].remotePortRakNetWasStartedOn_PS3_PSP2==0)
461  {
462  rns = SocketLayer::CreateBoundSocket( this, socketDescriptors[i].port, socketDescriptors[i].blockingSocket, addrToBind, 100, socketDescriptors[i].extraSocketOptions, socketDescriptors[i].socketFamily, socketDescriptors[i].chromeInstance );
463  }
464  else
465  {
466 #if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) || defined(_PS4)
467  rns = SocketLayer::CreateBoundSocket_PS3Lobby( socketDescriptors[i].port, socketDescriptors[i].blockingSocket, addrToBind, socketDescriptors[i].socketFamily );
468 #elif defined(SN_TARGET_PSP2)
469  rns = SocketLayer::CreateBoundSocket_PSP2( socketDescriptors[i].port, socketDescriptors[i].blockingSocket, addrToBind, socketDescriptors[i].socketFamily );
470 #endif
471  }
472  */
473 
476  #if defined(__native_client__)
477  NativeClientBindParameters ncbp;
478  RNS2_NativeClient * nativeClientSocket = (RNS2_NativeClient*) r2;
479  ncbp.eventHandler=this;
480  ncbp.forceHostAddress=(char*) socketDescriptors[i].hostAddress;
481  ncbp.is_ipv6=socketDescriptors[i].socketFamily==AF_INET6;
482  ncbp.nativeClientInstance=socketDescriptors[i].chromeInstance;
483  ncbp.port=socketDescriptors[i].port;
484  nativeClientSocket->Bind(&ncbp, _FILE_AND_LINE_);
485  #elif defined(WINDOWS_STORE_RT)
486  RNS2BindResult br;
487  ((RNS2_WindowsStore8*) r2)->SetRecvEventHandler(this);
488  br = ((RNS2_WindowsStore8*) r2)->Bind(ref new Platform::String());
489  if (br!=BR_SUCCESS)
490  {
492  DerefAllSockets();
493  return SOCKET_FAILED_TO_BIND;
494  }
495  #else
496  if (r2->IsBerkleySocket())
497  {
499  bbp.port=socketDescriptors[i].port;
500  bbp.hostAddress=(char*) socketDescriptors[i].hostAddress;
501  bbp.addressFamily=socketDescriptors[i].socketFamily;
502  bbp.type=SOCK_DGRAM;
503  bbp.protocol=socketDescriptors[i].extraSocketOptions;
504  bbp.nonBlockingSocket=false;
505  bbp.setBroadcast=true;
506  bbp.setIPHdrIncl=false;
507  bbp.doNotFragment=false;
508  bbp.pollingThreadPriority=threadPriority;
509  bbp.eventHandler=this;
511  RNS2BindResult br = ((RNS2_Berkley*) r2)->Bind(&bbp, _FILE_AND_LINE_);
512 
513  if (
514  #if RAKNET_SUPPORT_IPV6==0
515  socketDescriptors[i].socketFamily!=AF_INET ||
516  #endif
518  {
520  DerefAllSockets();
522  }
523  else if (br==BR_FAILED_TO_BIND_SOCKET)
524  {
526  DerefAllSockets();
528  }
529  else if (br==BR_FAILED_SEND_TEST)
530  {
532  DerefAllSockets();
534  }
535  else
536  {
537  RakAssert(br==BR_SUCCESS);
538  }
539  }
540  else
541  {
542  RakAssert("TODO" && 0);
543  }
544  #endif
545 /*
546 
547  SystemAddress saOut;
548  SocketLayer::GetSystemAddress( rns, &saOut );
549  rns->SetBoundAddress(saOut);
550  rns->SetRemotePortRakNetWasStartedOn(socketDescriptors[i].remotePortRakNetWasStartedOn_PS3_PSP2);
551  rns->SetChromeInstance(socketDescriptors[i].chromeInstance);
552  rns->SetExtraSocketOptions(socketDescriptors[i].extraSocketOptions);
553  rns->SetUserConnectionSocketIndex(i);
554  rns->SetBlockingSocket(socketDescriptors[i].blockingSocket);
555 
556 #if RAKNET_SUPPORT_IPV6==0
557  if (addrToBind==0)
558  rns->SetBoundAddressToLoopback(4);
559 #endif
560 
561  // GetBoundAddress is asynch, which isn't supported by this architecture
562 #if !defined(__native_client__)
563  int zero=0;
564  if (SocketLayer::SendTo(rns, (const char*) &zero,4, rns->GetBoundAddress(), _FILE_AND_LINE_)!=0)
565  {
566  DerefAllSockets();
567  return SOCKET_FAILED_TEST_SEND;
568  }
569 #endif
570  */
571 
573 
574  }
575 
576 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
577  for (i=0; i<socketDescriptorCount; i++)
578  {
579  if (socketList[i]->IsBerkleySocket())
580  ((RNS2_Berkley*) socketList[i])->CreateRecvPollingThread(threadPriority);
581  }
582 #endif
583 
584 // #if !defined(_XBOX) && !defined(_XBOX_720_COMPILE_AS_WINDOWS) && !defined(X360)
585  for (i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
586  {
588  break;
589 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
590  if (socketList[0]->IsBerkleySocket())
591  {
592  unsigned short port = ((RNS2_Berkley*)socketList[0])->GetBoundAddress().GetPort();
593  ipList[i].SetPortHostOrder(port);
594 
595  }
596 #endif
597 // ipList[i].SetPort(((RNS2_360_720*)socketList[0])->GetBoundAddress().GetPort());
598  }
599 // #endif
600 
601 
602  if ( maximumNumberOfPeers == 0 )
603  {
604  // Don't allow more incoming connections than we have peers.
605  if ( maximumIncomingConnections > maxConnections )
606  maximumIncomingConnections = maxConnections;
607 
608  maximumNumberOfPeers = maxConnections;
609  // 04/19/2006 - Don't overallocate because I'm no longer allowing connected pings.
610  // The disconnects are not consistently processed and the process was sloppy and complicated.
611  // Allocate 10% extra to handle new connections from players trying to connect when the server is full
612  //remoteSystemListSize = maxConnections;// * 11 / 10 + 1;
613 
614  // remoteSystemList in Single thread
615  //remoteSystemList = SLNet::OP_NEW<RemoteSystemStruct[ remoteSystemListSize ]>( _FILE_AND_LINE_ );
616  remoteSystemList = SLNet::OP_NEW_ARRAY<RemoteSystemStruct>(maximumNumberOfPeers, _FILE_AND_LINE_ );
617 
618  remoteSystemLookup = SLNet::OP_NEW_ARRAY<RemoteSystemIndex*>((unsigned int) maximumNumberOfPeers * REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE, _FILE_AND_LINE_ );
619 
620  activeSystemList = SLNet::OP_NEW_ARRAY<RemoteSystemStruct*>(maximumNumberOfPeers, _FILE_AND_LINE_ );
621 
622  for ( i = 0; i < maximumNumberOfPeers; i++ )
623  //for ( i = 0; i < remoteSystemListSize; i++ )
624  {
625  // remoteSystemList in Single thread
626  remoteSystemList[ i ].isActive = false;
633 #ifdef _DEBUG
634  remoteSystemList[ i ].reliabilityLayer.ApplyNetworkSimulator(_packetloss, _minExtraPing, _extraPingVariance);
635 #endif
636 
637  // All entries in activeSystemList have valid pointers all the time.
638  activeSystemList[ i ] = &remoteSystemList[ i ];
639  }
640 
641  for (i=0; i < (unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE; i++)
642  {
643  remoteSystemLookup[i]=0;
644  }
645  }
646 
647  // For histogram statistics
648  // nextReadBytesTime=0;
649  // lastSentBytes=lastReceivedBytes=0;
650 
651  if ( endThreads )
652  {
653  updateCycleIsRunning = false;
654  endThreads = false;
656 
660 
661  if ( isMainLoopThreadActive == false )
662  {
663 #if RAKPEER_USER_THREADED!=1
664 
665  int errorCode;
666 
667 
668 
669 
670 
671 
672 
673  errorCode = SLNet::RakThread::Create(UpdateNetworkLoop, this, threadPriority);
674 
675 
676  if ( errorCode != 0 )
677  {
678  Shutdown( 0, 0 );
680  }
681 // RakAssert(isRecvFromLoopThreadActive.GetValue()==0);
682 #endif // RAKPEER_USER_THREADED!=1
683 
684  /*
685  for (i=0; i<socketDescriptorCount; i++)
686  {
687  RakPeerAndIndex *rpai = SLNet::OP_NEW<RakPeerAndIndex>(_FILE_AND_LINE_);
688  rpai->s=socketList[i];
689  rpai->rakPeer=this;
690 
691 #if RAKPEER_USER_THREADED!=1
692 
693  #if defined(SN_TARGET_PSP2)
694  sprintf_s(threadName, "RecvFromLoop_%p", this);
695  //errorCode = SLNet::RakThread::Create(RecvFromLoop, rpai, threadPriority, threadName, 1+i, runtime);
696  errorCode = SLNet::RakThread::Create(RecvFromLoop, rpai, threadPriority, threadName, 1024*1);
697  #else
698  errorCode = SLNet::RakThread::Create(RecvFromLoop, rpai, threadPriority);
699  #endif
700 
701  if ( errorCode != 0 )
702  {
703  Shutdown( 0, 0 );
704  return FAILED_TO_CREATE_NETWORK_THREAD;
705  }
706 #endif // RAKPEER_USER_THREADED!=1
707  }
708  */
709 
710 
711  /*
712 #if RAKPEER_USER_THREADED!=1
713 
714  while ( isRecvFromLoopThreadActive.GetValue() < (uint32_t) socketDescriptorCount )
715  RakSleep(10);
716  #endif // RAKPEER_USER_THREADED!=1
717  */
718 
719  }
720 
721 #if RAKPEER_USER_THREADED!=1
722  // Wait for the threads to activate. When they are active they will set these variables to true
723  while ( isMainLoopThreadActive == false )
724  RakSleep(10);
725 #endif // RAKPEER_USER_THREADED!=1
726  }
727 
728  for (i=0; i < pluginListTS.Size(); i++)
729  {
730  pluginListTS[i]->OnRakPeerStartup();
731  }
732 
733  for (i=0; i < pluginListNTS.Size(); i++)
734  {
735  pluginListNTS[i]->OnRakPeerStartup();
736  }
737 
738 #ifdef USE_THREADED_SEND
739  SLNet::SendToThread::AddRef();
740 #endif
741 
742  return RAKNET_STARTED;
743 }
744 
745 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
746 // Description:
747 // Must be called while offline
748 //
749 // If you accept connections, you must call this or else security will not be enabled for incoming connections.
750 //
751 // This feature requires more round trips, bandwidth, and CPU time for the connection handshake
752 // x64 builds require under 25% of the CPU time of other builds
753 //
754 // See the Encryption sample for example usage
755 //
756 // Parameters:
757 // publicKey = A pointer to the public key for accepting new connections
758 // privateKey = A pointer to the private key for accepting new connections
759 // If the private keys are 0, then a new key will be generated when this function is called
760 // bRequireClientKey: Should be set to false for most servers. Allows the server to accept a public key from connecting clients as a proof of identity but eats twice as much CPU time as a normal connection
761 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
762 bool RakPeer::InitializeSecurity(const char *public_key, const char *private_key, bool bRequireClientKey)
763 {
764 #if LIBCAT_SECURITY==1
765  if ( endThreads == false )
766  return false;
767 
768  // Copy client public key requirement flag
769  _require_client_public_key = bRequireClientKey;
770 
771  if (_server_handshake)
772  {
773  CAT_AUDIT_PRINTF("AUDIT: Deleting old server_handshake %x\n", _server_handshake);
774  SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
775  }
776  if (_cookie_jar)
777  {
778  CAT_AUDIT_PRINTF("AUDIT: Deleting old cookie jar %x\n", _cookie_jar);
779  SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
780  }
781 
782  _server_handshake = SLNet::OP_NEW<cat::ServerEasyHandshake>(_FILE_AND_LINE_);
783  _cookie_jar = SLNet::OP_NEW<cat::CookieJar>(_FILE_AND_LINE_);
784 
785  CAT_AUDIT_PRINTF("AUDIT: Created new server_handshake %x\n", _server_handshake);
786  CAT_AUDIT_PRINTF("AUDIT: Created new cookie jar %x\n", _cookie_jar);
787  CAT_AUDIT_PRINTF("AUDIT: Running _server_handshake->Initialize()\n");
788 
789  if (_server_handshake->Initialize(public_key, private_key))
790  {
791  CAT_AUDIT_PRINTF("AUDIT: Successfully initialized, filling cookie jar with goodies, storing public key and setting using security flag to true\n");
792 
793  _server_handshake->FillCookieJar(_cookie_jar);
794 
795  memcpy(my_public_key, public_key, sizeof(my_public_key));
796 
797  _using_security = true;
798  return true;
799  }
800 
801  CAT_AUDIT_PRINTF("AUDIT: Failure to initialize so deleting server handshake and cookie jar; also setting using_security flag = false\n");
802 
803  SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
804  _server_handshake=0;
805  SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
806  _cookie_jar=0;
807  _using_security = false;
808  return false;
809 #else
810  (void) public_key;
811  (void) private_key;
812  (void) bRequireClientKey;
813 
814  return false;
815 #endif
816 }
817 
818 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
819 // Description
820 // Must be called while offline
821 // Disables security for incoming connections.
822 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
824 {
825 #if LIBCAT_SECURITY==1
826  CAT_AUDIT_PRINTF("AUDIT: DisableSecurity() called, so deleting _server_handshake %x and cookie_jar %x\n", _server_handshake, _cookie_jar);
827  SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
828  _server_handshake=0;
829  SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
830  _cookie_jar=0;
831 
832  _using_security = false;
833 #endif
834 }
835 
836 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
838 {
842 }
843 
844 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
846 {
847  if (securityExceptionList.Size()==0)
848  return;
849 
850  if (ip==0)
851  {
855  }
856  else
857  {
858  unsigned i=0;
860  while (i < securityExceptionList.Size())
861  {
862  if (securityExceptionList[i].IPAddressMatch(ip))
863  {
866  }
867  else
868  i++;
869  }
871  }
872 }
873 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
875 {
876  if (securityExceptionList.Size()==0)
877  return false;
878 
879  unsigned i=0;
881  for (; i < securityExceptionList.Size(); i++)
882  {
883  if (securityExceptionList[i].IPAddressMatch(ip))
884  {
886  return true;
887  }
888  }
890  return false;
891 }
892 
893 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
894 // Description:
895 // Sets how many incoming connections are allowed. If this is less than the number of players currently connected, no
896 // more players will be allowed to connect. If this is greater than the maximum number of peers allowed, it will be reduced
897 // to the maximum number of peers allowed. Defaults to 0.
898 //
899 // Parameters:
900 // numberAllowed - Maximum number of incoming connections allowed.
901 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
902 void RakPeer::SetMaximumIncomingConnections( unsigned short numberAllowed )
903 {
904  maximumIncomingConnections = numberAllowed;
905 }
906 
907 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
908 // Description:
909 // Returns the maximum number of incoming connections, which is always <= maxConnections
910 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
911 unsigned int RakPeer::GetMaximumIncomingConnections( void ) const
912 {
914 }
915 
916 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
917 // Returns how many open connections there are at this time
918 // \return the number of open connections
919 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
920 unsigned short RakPeer::NumberOfConnections(void) const
921 {
924  GetSystemList(addresses, guids);
925  return (unsigned short) addresses.Size();
926 }
927 
928 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
929 // Description:
930 // Sets the password incoming connections must match in the call to Connect (defaults to none)
931 // Pass 0 to passwordData to specify no password
932 //
933 // Parameters:
934 // passwordData: A data block that incoming connections must match. This can be just a password, or can be a stream of data.
935 // - Specify 0 for no password data
936 // passwordDataLength: The length in bytes of passwordData
937 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
938 void RakPeer::SetIncomingPassword( const char* passwordData, int passwordDataLength )
939 {
940  //if (passwordDataLength > MAX_OFFLINE_DATA_LENGTH)
941  // passwordDataLength=MAX_OFFLINE_DATA_LENGTH;
942 
943  if (passwordDataLength > 255)
944  passwordDataLength=255;
945 
946  if (passwordData==0)
947  passwordDataLength=0;
948 
949  // Not threadsafe but it's not important enough to lock. Who is going to change the password a lot during runtime?
950  // It won't overflow at least because incomingPasswordLength is an unsigned char
951  if (passwordDataLength>0)
952  memcpy(incomingPassword, passwordData, passwordDataLength);
953  incomingPasswordLength=(unsigned char)passwordDataLength;
954 }
955 
956 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
957 void RakPeer::GetIncomingPassword( char* passwordData, int *passwordDataLength )
958 {
959  if (passwordData==0)
960  {
961  *passwordDataLength=incomingPasswordLength;
962  return;
963  }
964 
965  if (*passwordDataLength > incomingPasswordLength)
966  *passwordDataLength=incomingPasswordLength;
967 
968  if (*passwordDataLength>0)
969  memcpy(passwordData, incomingPassword, *passwordDataLength);
970 }
971 
972 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
973 // Description:
974 // Call this to connect to the specified host (ip or domain name) and server port.
975 // Calling Connect and not calling SetMaximumIncomingConnections acts as a dedicated client. Calling both acts as a true peer.
976 // This is a non-blocking connection. You know the connection is successful when IsConnected() returns true
977 // or receive gets a packet with the type identifier ID_CONNECTION_REQUEST_ACCEPTED. If the connection is not
978 // successful, such as rejected connection or no response then neither of these things will happen.
979 // Requires that you first call Initialize
980 //
981 // Parameters:
982 // host: Either a dotted IP address or a domain name
983 // remotePort: Which port to connect to on the remote machine.
984 // passwordData: A data block that must match the data block on the server. This can be just a password, or can be a stream of data
985 // passwordDataLength: The length in bytes of passwordData
986 //
987 // Returns:
988 // True on successful initiation. False on incorrect parameters, internal error, or too many existing peers
989 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
990 ConnectionAttemptResult RakPeer::Connect( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, PublicKey *publicKey, unsigned connectionSocketIndex, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime )
991 {
992  // If endThreads is true here you didn't call Startup() first.
993  if ( host == 0 || endThreads || connectionSocketIndex>=socketList.Size() )
994  return INVALID_PARAMETER;
995 
996  RakAssert(remotePort!=0);
997 
998  connectionSocketIndex=GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
999 
1000  if (passwordDataLength>255)
1001  passwordDataLength=255;
1002 
1003  if (passwordData==0)
1004  passwordDataLength=0;
1005 
1006  // Not threadsafe but it's not important enough to lock. Who is going to change the password a lot during runtime?
1007  // It won't overflow at least because outgoingPasswordLength is an unsigned char
1008 // if (passwordDataLength>0)
1009 // memcpy(outgoingPassword, passwordData, passwordDataLength);
1010 // outgoingPasswordLength=(unsigned char) passwordDataLength;
1011 
1012  // 04/02/09 - Can't remember why I disabled connecting to self, but it seems to work
1013  // Connecting to ourselves in the same instance of the program?
1014 // if ( ( strcmp( host, "127.0.0.1" ) == 0 || strcmp( host, "0.0.0.0" ) == 0 ) && remotePort == mySystemAddress[0].port )
1015 // return false;
1016 
1017  return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, publicKey, connectionSocketIndex, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime);
1018 }
1019 
1020 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1021 
1022 ConnectionAttemptResult RakPeer::ConnectWithSocket(const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, RakNetSocket2* socket, PublicKey *publicKey, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime)
1023 {
1024  if ( host == 0 || endThreads || socket == 0 )
1025  return INVALID_PARAMETER;
1026 
1027  if (passwordDataLength>255)
1028  passwordDataLength=255;
1029 
1030  if (passwordData==0)
1031  passwordDataLength=0;
1032 
1033  return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, publicKey, 0, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime, socket );
1034 
1035 }
1036 
1037 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1038 // Description:
1039 // Stops the network threads and close all connections. Multiple calls are ok.
1040 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1041 void RakPeer::Shutdown( unsigned int blockDuration, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
1042 {
1043  unsigned i,j;
1044  bool anyActive;
1045  SLNet::TimeMS startWaitingTime;
1046 // SystemAddress systemAddress;
1047  SLNet::TimeMS time;
1048  //unsigned short systemListSize = remoteSystemListSize; // This is done for threading reasons
1049  unsigned int systemListSize = maximumNumberOfPeers;
1050 
1051  if ( blockDuration > 0 )
1052  {
1053  for ( i = 0; i < systemListSize; i++ )
1054  {
1055  // remoteSystemList in user thread
1056  if (remoteSystemList[i].isActive)
1057  NotifyAndFlagForShutdown(remoteSystemList[i].systemAddress, false, orderingChannel, disconnectionNotificationPriority);
1058  }
1059 
1060  time = SLNet::GetTimeMS();
1061  startWaitingTime = time;
1062  while ( time - startWaitingTime < blockDuration )
1063  {
1064  anyActive=false;
1065  for (j=0; j < systemListSize; j++)
1066  {
1067  // remoteSystemList in user thread
1068  if (remoteSystemList[j].isActive)
1069  {
1070  anyActive=true;
1071  break;
1072  }
1073  }
1074 
1075  // If this system is out of packets to send, then stop waiting
1076  if ( anyActive==false )
1077  break;
1078 
1079  // This will probably cause the update thread to run which will probably
1080  // send the disconnection notification
1081 
1082  RakSleep(15);
1083  time = SLNet::GetTimeMS();
1084  }
1085  }
1086  for (i=0; i < pluginListTS.Size(); i++)
1087  {
1088  pluginListTS[i]->OnRakPeerShutdown();
1089  }
1090  for (i=0; i < pluginListNTS.Size(); i++)
1091  {
1092  pluginListNTS[i]->OnRakPeerShutdown();
1093  }
1094 
1096 
1097  endThreads = true;
1098 
1099 // SLNet::TimeMS timeout;
1100 #if RAKPEER_USER_THREADED!=1
1101 
1102 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
1103  for (i=0; i < socketList.Size(); i++)
1104  {
1105  if (socketList[i]->IsBerkleySocket())
1106  {
1107  ((RNS2_Berkley *)socketList[i])->SignalStopRecvPollingThread();
1108  }
1109  }
1110 #endif
1111 
1112  /*
1113  // Get recvfrom to unblock
1114  for (i=0; i < socketList.Size(); i++)
1115  {
1116  if (SocketLayer::SendTo(socketList[i], (const char*) &i,1,socketList[i]->GetBoundAddress(), _FILE_AND_LINE_)!=0)
1117  break;
1118  }
1119  */
1120 
1121  while ( isMainLoopThreadActive )
1122  {
1123  endThreads = true;
1124  RakSleep(15);
1125  }
1126 
1128 
1129  /*
1130  timeout = SLNet::GetTimeMS()+1000;
1131  while ( isRecvFromLoopThreadActive.GetValue()>0 && SLNet::GetTimeMS()<timeout )
1132  {
1133  // Get recvfrom to unblock
1134  for (i=0; i < socketList.Size(); i++)
1135  {
1136  SocketLayer::SendTo(socketList[i], (const char*) &i,1,socketList[i]->GetBoundAddress(), _FILE_AND_LINE_);
1137  }
1138 
1139  RakSleep(30);
1140  }
1141  */
1142 
1143 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
1144  for (i=0; i < socketList.Size(); i++)
1145  {
1146  if (socketList[i]->IsBerkleySocket())
1147  {
1148  ((RNS2_Berkley *)socketList[i])->BlockOnStopRecvPollingThread();
1149  }
1150  }
1151 #endif
1152 
1153 
1154 #endif // RAKPEER_USER_THREADED!=1
1155 
1156 // char c=0;
1157 // unsigned int socketIndex;
1158  // remoteSystemList in Single thread
1159  for ( i = 0; i < systemListSize; i++ )
1160  {
1161  // Reserve this reliability layer for ourselves
1162  remoteSystemList[ i ].isActive = false;
1163 
1164  // Remove any remaining packets
1165  RakAssert(remoteSystemList[ i ].MTUSize <= MAXIMUM_MTU_SIZE);
1166  remoteSystemList[ i ].reliabilityLayer.Reset(false, remoteSystemList[ i ].MTUSize, false);
1167  remoteSystemList[ i ].rakNetSocket = 0;
1168  }
1169 
1170 
1171  // Setting maximumNumberOfPeers to 0 allows remoteSystemList to be reallocated in Initialize.
1172  // Setting remoteSystemListSize prevents threads from accessing the reliability layer
1174  //remoteSystemListSize = 0;
1175 
1176  // Free any packets the user didn't deallocate
1178  for (i=0; i < packetReturnQueue.Size(); i++)
1185 
1186  /*
1187  if (isRecvFromLoopThreadActive.GetValue()>0)
1188  {
1189  timeout = SLNet::GetTimeMS()+1000;
1190  while ( isRecvFromLoopThreadActive.GetValue()>0 && SLNet::GetTimeMS()<timeout )
1191  {
1192  RakSleep(30);
1193  }
1194  }
1195  */
1196 
1197  DerefAllSockets();
1198 
1203 
1205 
1206 
1207  // Clear out the reliability layer list in case we want to reallocate it in a successive call to Init.
1209  remoteSystemList = 0;
1212  activeSystemList=0;
1213 
1215 
1216 #ifdef USE_THREADED_SEND
1217  SLNet::SendToThread::Deref();
1218 #endif
1219 
1220  ResetSendReceipt();
1221 }
1222 
1223 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1224 // Description:
1225 // Returns true if the network threads are running
1226 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1227 inline bool RakPeer::IsActive( void ) const
1228 {
1229  return endThreads == false;
1230 }
1231 
1232 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1233 // Description:
1234 // Fills the array remoteSystems with the systemAddress of all the systems we are connected to
1235 //
1236 // Parameters:
1237 // remoteSystems (out): An array of SystemAddress structures to be filled with the SystemAddresss of the systems we are connected to
1238 // - pass 0 to remoteSystems to only get the number of systems we are connected to
1239 // numberOfSystems (int, out): As input, the size of remoteSystems array. As output, the number of elements put into the array
1240 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1241 bool RakPeer::GetConnectionList( SystemAddress *remoteSystems, unsigned short *numberOfSystems ) const
1242 {
1243  if (numberOfSystems==0)
1244  return false;
1245 
1246  if ( remoteSystemList == 0 || endThreads == true )
1247  {
1248  if (numberOfSystems)
1249  *numberOfSystems=0;
1250  return false;
1251  }
1252 
1255  GetSystemList(addresses, guids);
1256  if (remoteSystems)
1257  {
1258  unsigned short i;
1259  for (i=0; i < *numberOfSystems && i < addresses.Size(); i++)
1260  remoteSystems[i]=addresses[i];
1261  *numberOfSystems=i;
1262  }
1263  else
1264  {
1265  *numberOfSystems=(unsigned short) addresses.Size();
1266  }
1267  return true;
1268 }
1269 
1270 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1272 {
1274  uint32_t retVal = sendReceiptSerial;
1276  return retVal;
1277 }
1278 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1280 {
1282  uint32_t returned = sendReceiptSerial;
1283  if (++sendReceiptSerial==0)
1286  return returned;
1287 }
1288 
1289 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1290 // Description:
1291 // Sends a block of data to the specified system that you are connected to.
1292 // This function only works while the client is connected (Use the Connect function).
1293 // The first byte should be a message identifier starting at ID_USER_PACKET_ENUM
1294 //
1295 // Parameters:
1296 // data: The block of data to send
1297 // length: The size in bytes of the data to send
1298 // bitStream: The bitstream to send
1299 // priority: What priority level to send on.
1300 // reliability: How reliability to send this data
1301 // orderingChannel: When using ordered or sequenced packets, what channel to order these on.
1302 // - Packets are only ordered relative to other packets on the same stream
1303 // systemAddress: Who to send this packet to, or in the case of broadcasting who not to send it to. Use UNASSIGNED_SYSTEM_ADDRESS to specify none
1304 // broadcast: True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to.
1305 // Returns:
1306 // \return 0 on bad input. Otherwise a number that identifies this message. If \a reliability is a type that returns a receipt, on a later call to Receive() you will get ID_SND_RECEIPT_ACKED or ID_SND_RECEIPT_LOSS with bytes 1-4 inclusive containing this number
1307 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1308 uint32_t RakPeer::Send( const char *data, const int length, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceiptNumber )
1309 {
1310 #ifdef _DEBUG
1311  RakAssert( data && length > 0 );
1312 #endif
1313  RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
1314  RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
1315  RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
1316 
1317  if ( data == 0 || length < 0 )
1318  return 0;
1319 
1320  if ( remoteSystemList == 0 || endThreads == true )
1321  return 0;
1322 
1323  if ( broadcast == false && systemIdentifier.IsUndefined())
1324  return 0;
1325 
1326  uint32_t usedSendReceipt;
1327  if (forceReceiptNumber!=0)
1328  usedSendReceipt=forceReceiptNumber;
1329  else
1330  usedSendReceipt=IncrementNextSendReceipt();
1331 
1332  if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
1333  {
1334  SendLoopback(data,length);
1335 
1336  if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
1337  {
1338  char buff[5];
1339  buff[0]=ID_SND_RECEIPT_ACKED;
1341  memcpy(buff+1, &sendReceiptSerial, 4);
1343  SendLoopback( buff, 5 );
1344  }
1345 
1346  return usedSendReceipt;
1347  }
1348 
1349  SendBuffered(data, length*8, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1350 
1351  return usedSendReceipt;
1352 }
1353 
1354 void RakPeer::SendLoopback( const char *data, const int length )
1355 {
1356  if ( data == 0 || length < 0 )
1357  return;
1358 
1359  Packet *packet = AllocPacket(length, _FILE_AND_LINE_);
1360  memcpy(packet->data, data, length);
1361  packet->systemAddress = GetLoopbackAddress();
1362  packet->guid=myGuid;
1363  PushBackPacket(packet, false);
1364 }
1365 
1366 uint32_t RakPeer::Send( const SLNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceiptNumber )
1367 {
1368 #ifdef _DEBUG
1369  RakAssert( bitStream->GetNumberOfBytesUsed() > 0 );
1370 #endif
1371 
1372  RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
1373  RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
1374  RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
1375 
1376  if ( bitStream->GetNumberOfBytesUsed() == 0 )
1377  return 0;
1378 
1379  if ( remoteSystemList == 0 || endThreads == true )
1380  return 0;
1381 
1382  if ( broadcast == false && systemIdentifier.IsUndefined() )
1383  return 0;
1384 
1385  uint32_t usedSendReceipt;
1386  if (forceReceiptNumber!=0)
1387  usedSendReceipt=forceReceiptNumber;
1388  else
1389  usedSendReceipt=IncrementNextSendReceipt();
1390 
1391  if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
1392  {
1393  SendLoopback((const char*) bitStream->GetData(),bitStream->GetNumberOfBytesUsed());
1394  if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
1395  {
1396  char buff[5];
1397  buff[0]=ID_SND_RECEIPT_ACKED;
1399  memcpy(buff+1, &sendReceiptSerial,4);
1401  SendLoopback( buff, 5 );
1402  }
1403  return usedSendReceipt;
1404  }
1405 
1406  // Sends need to be buffered and processed in the update thread because the systemAddress associated with the reliability layer can change,
1407  // from that thread, resulting in a send to the wrong player! While I could mutex the systemAddress, that is much slower than doing this
1408  SendBuffered((const char*)bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1409 
1410 
1411  return usedSendReceipt;
1412 }
1413 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1414 // Sends multiple blocks of data, concatenating them automatically.
1415 //
1416 // This is equivalent to:
1417 // SLNet::BitStream bs;
1418 // bs.WriteAlignedBytes(block1, blockLength1);
1419 // bs.WriteAlignedBytes(block2, blockLength2);
1420 // bs.WriteAlignedBytes(block3, blockLength3);
1421 // Send(&bs, ...)
1422 //
1423 // This function only works while connected
1424 // \param[in] data An array of pointers to blocks of data
1425 // \param[in] lengths An array of integers indicating the length of each block of data
1426 // \param[in] numParameters Length of the arrays data and lengths
1427 // \param[in] priority What priority level to send on. See PacketPriority.h
1428 // \param[in] reliability How reliability to send this data. See PacketPriority.h
1429 // \param[in] orderingChannel When using ordered or sequenced messages, what channel to order these on. Messages are only ordered relative to other messages on the same stream
1430 // \param[in] systemIdentifier Who to send this packet to, or in the case of broadcasting who not to send it to. Pass either a SystemAddress structure or a RakNetGUID structure. Use UNASSIGNED_SYSTEM_ADDRESS or to specify none
1431 // \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to.
1432 // \return False if we are not connected to the specified recipient. True otherwise
1433 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1434 uint32_t RakPeer::SendList( const char **data, const int *lengths, const int numParameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceiptNumber )
1435 {
1436 #ifdef _DEBUG
1437  RakAssert( data );
1438 #endif
1439 
1440  if ( data == 0 || lengths == 0 )
1441  return 0;
1442 
1443  if ( remoteSystemList == 0 || endThreads == true )
1444  return 0;
1445 
1446  if (numParameters==0)
1447  return 0;
1448 
1449  if (lengths==0)
1450  return 0;
1451 
1452  if ( broadcast == false && systemIdentifier.IsUndefined() )
1453  return 0;
1454 
1455  uint32_t usedSendReceipt;
1456  if (forceReceiptNumber!=0)
1457  usedSendReceipt=forceReceiptNumber;
1458  else
1459  usedSendReceipt=IncrementNextSendReceipt();
1460 
1461  SendBufferedList(data, lengths, numParameters, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1462 
1463  return usedSendReceipt;
1464 }
1465 
1466 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1467 // Description:
1468 // Gets a packet from the incoming packet queue. Use DeallocatePacket to deallocate the packet after you are done with it.
1469 // Check the Packet struct at the top of CoreNetworkStructures.h for the format of the struct
1470 //
1471 // Returns:
1472 // 0 if no packets are waiting to be handled, otherwise an allocated packet
1473 // If the client is not active this will also return 0, as all waiting packets are flushed when the client is Disconnected
1474 // This also updates all memory blocks associated with synchronized memory and distributed objects
1475 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1477 {
1478  if ( !( IsActive() ) )
1479  return 0;
1480 
1481  SLNet::Packet *packet;
1482 // Packet **threadPacket;
1483  PluginReceiveResult pluginResult;
1484 
1485  int offset;
1486  unsigned int i;
1487 
1488  // User should call RunUpdateCycle and RunRecvFromOnce to do this commented code
1489  /*
1490 #if RAKPEER_SINGLE_THREADED==1
1491  RakPeer::RecvFromStruct *recvFromStruct;
1492  for (i=0; i < socketList.Size(); i++)
1493  {
1494  for(;;)
1495  {
1496  recvFromStruct=bufferedPackets.Allocate( _FILE_AND_LINE_ );
1497  recvFromStruct->s=socketList[i]->s;
1498  recvFromStruct->remotePortRakNetWasStartedOn_PS3=socketList[i]->remotePortRakNetWasStartedOn_PS3_PSP2;
1499  recvFromStruct->extraSocketOptions=socketList[i]->extraSocketOptions;
1500  SocketLayer::RecvFromBlocking(
1501  recvFromStruct->s, this, recvFromStruct->remotePortRakNetWasStartedOn_PS3,
1502  recvFromStruct->extraSocketOptions, recvFromStruct->data, &recvFromStruct->bytesRead, &recvFromStruct->systemAddress, &recvFromStruct->timeRead);
1503  if (recvFromStruct->bytesRead<=0)
1504  {
1505  bufferedPackets.Deallocate(recvFromStruct, _FILE_AND_LINE_);
1506  break;
1507  }
1508  else
1509  {
1510  RakAssert(recvFromStruct->systemAddress.GetPort());
1511  bufferedPackets.Push(recvFromStruct);
1512  }
1513  }
1514  }
1515 
1516  BitStream updateBitStream( MAXIMUM_MTU_SIZE
1517 #if LIBCAT_SECURITY==1
1518  + cat::AuthenticatedEncryption::OVERHEAD_BYTES
1519 #endif
1520  );
1521  RunUpdateCycle(0, 0, updateBitStream);
1522 #endif
1523  */
1524 
1525  for (i=0; i < pluginListTS.Size(); i++)
1526  {
1527  pluginListTS[i]->Update();
1528  }
1529  for (i=0; i < pluginListNTS.Size(); i++)
1530  {
1531  pluginListNTS[i]->Update();
1532  }
1533 
1534  do
1535  {
1537  if (packetReturnQueue.IsEmpty())
1538  packet=0;
1539  else
1540  packet = packetReturnQueue.Pop();
1542  if (packet==0)
1543  return 0;
1544 
1545 // unsigned char msgId;
1546  if ( ( packet->length >= sizeof(unsigned char) + sizeof(SLNet::Time ) ) &&
1547  ( (unsigned char) packet->data[ 0 ] == ID_TIMESTAMP ) )
1548  {
1549  offset = sizeof(unsigned char);
1550  ShiftIncomingTimestamp( packet->data + offset, packet->systemAddress );
1551 // msgId=packet->data[sizeof(unsigned char) + sizeof( SLNet::Time )];
1552  }
1553 // else
1554  // msgId=packet->data[0];
1555 
1556  // Some locally generated packets need to be processed by plugins, for example ID_FCM2_NEW_HOST
1557  // The plugin itself should intercept these messages generated remotely
1558 // if (packet->wasGeneratedLocally)
1559 // return packet;
1560 
1561 
1564 
1565  for (i=0; i < pluginListTS.Size(); i++)
1566  {
1567  pluginResult=pluginListTS[i]->OnReceive(packet);
1568  if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
1569  {
1570  DeallocatePacket( packet );
1571  packet=0; // Will do the loop again and get another packet
1572  break; // break out of the enclosing for
1573  }
1574  else if (pluginResult==RR_STOP_PROCESSING)
1575  {
1576  packet=0;
1577  break;
1578  }
1579  }
1580 
1581  for (i=0; i < pluginListNTS.Size(); i++)
1582  {
1583  pluginResult=pluginListNTS[i]->OnReceive(packet);
1584  if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
1585  {
1586  DeallocatePacket( packet );
1587  packet=0; // Will do the loop again and get another packet
1588  break; // break out of the enclosing for
1589  }
1590  else if (pluginResult==RR_STOP_PROCESSING)
1591  {
1592  packet=0;
1593  break;
1594  }
1595  }
1596 
1597  } while(packet==0);
1598 
1599 #ifdef _DEBUG
1600  RakAssert( packet->data );
1601 #endif
1602 
1603  return packet;
1604 }
1605 
1606 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1607 // Description:
1608 // Call this to deallocate a packet returned by Receive
1609 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1611 {
1612  if ( packet == 0 )
1613  return;
1614 
1615  if (packet->deleteData)
1616  {
1617  rakFree_Ex(packet->data, _FILE_AND_LINE_ );
1618  packet->~Packet();
1622  }
1623  else
1624  {
1625  rakFree_Ex(packet, _FILE_AND_LINE_ );
1626  }
1627 }
1628 
1629 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1630 // Description:
1631 // Return the total number of connections we are allowed
1632 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1633 unsigned int RakPeer::GetMaximumNumberOfPeers( void ) const
1634 {
1635  return maximumNumberOfPeers;
1636 }
1637 
1638 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1639 // Description:
1640 // Close the connection to another host (if we initiated the connection it will disconnect, if they did it will kick them out).
1641 //
1642 // Parameters:
1643 // target: Which connection to close
1644 // sendDisconnectionNotification: True to send ID_DISCONNECTION_NOTIFICATION to the recipient. False to close it silently.
1645 // channel: If blockDuration > 0, the disconnect packet will be sent on this channel
1646 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1647 void RakPeer::CloseConnection( const AddressOrGUID target, bool sendDisconnectionNotification, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
1648 {
1649  /*
1650  // This only be called from the user thread, for the user shutting down.
1651  // From the network thread, this should occur because of ID_DISCONNECTION_NOTIFICATION and ID_CONNECTION_LOST
1652  unsigned j;
1653  for (j=0; j < messageHandlerList.Size(); j++)
1654  {
1655  messageHandlerList[j]->OnClosedConnection(
1656  target.systemAddress==UNASSIGNED_SYSTEM_ADDRESS ? GetSystemAddressFromGuid(target.rakNetGuid) : target.systemAddress,
1657  target.rakNetGuid==UNASSIGNED_RAKNET_GUID ? GetGuidFromSystemAddress(target.systemAddress) : target.rakNetGuid,
1658  LCR_CLOSED_BY_USER);
1659  }
1660  */
1661 
1662  CloseConnectionInternal(target, sendDisconnectionNotification, false, orderingChannel, disconnectionNotificationPriority);
1663 
1664  // 12/14/09 Return ID_CONNECTION_LOST when calling CloseConnection with sendDisconnectionNotification==false, elsewise it is never returned
1665  if (sendDisconnectionNotification==false && GetConnectionState(target)==IS_CONNECTED)
1666  {
1667  Packet *packet=AllocPacket(sizeof( char ), _FILE_AND_LINE_);
1668  packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
1672  packet->guid.systemIndex=packet->systemAddress.systemIndex;
1673  packet->wasGeneratedLocally=true; // else processed twice
1674  AddPacketToProducer(packet);
1675  }
1676 }
1677 
1678 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1679 // Cancel a pending connection attempt
1680 // If we are already connected, the connection stays open
1681 // \param[in] target Which system to cancel
1682 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1684 {
1685  unsigned int i;
1686 
1687  // Cancel pending connection attempt, if there is one
1688  i=0;
1690  while (i < requestedConnectionQueue.Size())
1691  {
1692  if (requestedConnectionQueue[i]->systemAddress==target)
1693  {
1694 #if LIBCAT_SECURITY==1
1695  CAT_AUDIT_PRINTF("AUDIT: Deleting requestedConnectionQueue %i client_handshake %x\n", i, requestedConnectionQueue[ i ]->client_handshake);
1697 #endif
1700  break;
1701  }
1702  else
1703  i++;
1704  }
1706 
1707 }
1708 
1709 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1710 
1712 {
1713  if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
1714  {
1715  unsigned int i=0;
1717  for (; i < requestedConnectionQueue.Size(); i++)
1718  {
1719  if (requestedConnectionQueue[i]->systemAddress==systemIdentifier.systemAddress)
1720  {
1722  return IS_PENDING;
1723  }
1724  }
1726  }
1727 
1728  int index;
1729  if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
1730  {
1731  index = GetIndexFromSystemAddress(systemIdentifier.systemAddress, false);
1732  }
1733  else
1734  {
1735  index = GetIndexFromGuid(systemIdentifier.rakNetGuid);
1736  }
1737 
1738  if (index==-1)
1739  return IS_NOT_CONNECTED;
1740 
1741  if (remoteSystemList[index].isActive==false)
1742  return IS_DISCONNECTED;
1743 
1744  switch (remoteSystemList[index].connectMode)
1745  {
1747  return IS_DISCONNECTING;
1751  return IS_DISCONNECTING;
1753  return IS_CONNECTING;
1755  return IS_CONNECTING;
1757  return IS_CONNECTING;
1759  return IS_CONNECTED;
1760  default:
1761  return IS_NOT_CONNECTED;
1762  }
1763 }
1764 
1765 
1766 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1767 // Description:
1768 // Given a systemAddress, returns an index from 0 to the maximum number of players allowed - 1.
1769 //
1770 // Parameters
1771 // systemAddress - The systemAddress to search for
1772 //
1773 // Returns
1774 // An integer from 0 to the maximum number of peers -1, or -1 if that player is not found
1775 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1776 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress ) const
1777 {
1778  return GetIndexFromSystemAddress(systemAddress, false);
1779 }
1780 
1781 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1782 // Description:
1783 // This function is only useful for looping through all players.
1784 //
1785 // Parameters
1786 // index - an integer between 0 and the maximum number of players allowed - 1.
1787 //
1788 // Returns
1789 // A valid systemAddress or UNASSIGNED_SYSTEM_ADDRESS if no such player at that index
1790 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1792 {
1793  // remoteSystemList in user thread
1794  //if ( index >= 0 && index < remoteSystemListSize )
1795  if ( index < maximumNumberOfPeers )
1796  if (remoteSystemList[index].isActive && remoteSystemList[ index ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED) // Don't give the user players that aren't fully connected, since sends will fail
1797  return remoteSystemList[ index ].systemAddress;
1798 
1800 }
1801 
1802 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1803 // Same as GetSystemAddressFromIndex but returns RakNetGUID
1804 // \param[in] index Index should range between 0 and the maximum number of players allowed - 1.
1805 // \return The RakNetGUID
1806 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1808 {
1809  // remoteSystemList in user thread
1810  //if ( index >= 0 && index < remoteSystemListSize )
1811  if ( index < maximumNumberOfPeers )
1812  if (remoteSystemList[index].isActive && remoteSystemList[ index ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED) // Don't give the user players that aren't fully connected, since sends will fail
1813  return remoteSystemList[ index ].guid;
1814 
1815  return UNASSIGNED_RAKNET_GUID;
1816 }
1817 
1818 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1819 // Same as calling GetSystemAddressFromIndex and GetGUIDFromIndex for all systems, but more efficient
1820 // Indices match each other, so \a addresses[0] and \a guids[0] refer to the same system
1821 // \param[out] addresses All system addresses. Size of the list is the number of connections. Size of the list will match the size of the \a guids list.
1822 // \param[out] guids All guids. Size of the list is the number of connections. Size of the list will match the size of the \a addresses list.
1823 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1825 {
1826  addresses.Clear(false, _FILE_AND_LINE_);
1827  guids.Clear(false, _FILE_AND_LINE_);
1828 
1829  if ( remoteSystemList == 0 || endThreads == true )
1830  return;
1831 
1832  unsigned int i;
1833  for (i=0; i < activeSystemListSize; i++)
1834  {
1835  if ((activeSystemList[i])->isActive &&
1837  {
1838  addresses.Push((activeSystemList[i])->systemAddress, _FILE_AND_LINE_ );
1839  guids.Push((activeSystemList[i])->guid, _FILE_AND_LINE_ );
1840  }
1841  }
1842 }
1843 
1844 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1845 // Description:
1846 // Bans an IP from connecting. Banned IPs persist between connections.
1847 //
1848 // Parameters
1849 // IP - Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will ban
1850 // All IP addresses starting with 128.0.0
1851 // milliseconds - how many ms for a temporary ban. Use 0 for a permanent ban
1852 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1853 void RakPeer::AddToBanList( const char *IP, SLNet::TimeMS milliseconds )
1854 {
1855  unsigned index;
1857 
1858  if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
1859  return ;
1860 
1861  // If this guy is already in the ban list, do nothing
1862  index = 0;
1863 
1864  banListMutex.Lock();
1865 
1866  for ( ; index < banList.Size(); index++ )
1867  {
1868  if ( strcmp( IP, banList[ index ]->IP ) == 0 )
1869  {
1870  // Already in the ban list. Just update the time
1871  if (milliseconds==0)
1872  banList[ index ]->timeout=0; // Infinite
1873  else
1874  banList[ index ]->timeout=time+milliseconds;
1875  banListMutex.Unlock();
1876  return;
1877  }
1878  }
1879 
1880  banListMutex.Unlock();
1881 
1882  BanStruct *banStruct = SLNet::OP_NEW<BanStruct>( _FILE_AND_LINE_ );
1883  banStruct->IP = (char*) rakMalloc_Ex( 16, _FILE_AND_LINE_ );
1884  if (milliseconds==0)
1885  banStruct->timeout=0; // Infinite
1886  else
1887  banStruct->timeout=time+milliseconds;
1888  strcpy_s( banStruct->IP, 16, IP );
1889  banListMutex.Lock();
1890  banList.Insert( banStruct, _FILE_AND_LINE_ );
1891  banListMutex.Unlock();
1892 }
1893 
1894 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1895 // Description:
1896 // Allows a previously banned IP to connect.
1897 //
1898 // Parameters
1899 // IP - Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will ban
1900 // All IP addresses starting with 128.0.0
1901 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1902 void RakPeer::RemoveFromBanList( const char *IP )
1903 {
1904  unsigned index;
1905  BanStruct *temp;
1906 
1907  if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
1908  return ;
1909 
1910  index = 0;
1911  temp=0;
1912 
1913  banListMutex.Lock();
1914 
1915  for ( ; index < banList.Size(); index++ )
1916  {
1917  if ( strcmp( IP, banList[ index ]->IP ) == 0 )
1918  {
1919  temp = banList[ index ];
1920  banList[ index ] = banList[ banList.Size() - 1 ];
1921  banList.RemoveAtIndex( banList.Size() - 1 );
1922  break;
1923  }
1924  }
1925 
1926  banListMutex.Unlock();
1927 
1928  if (temp)
1929  {
1930  rakFree_Ex(temp->IP, _FILE_AND_LINE_ );
1932  }
1933 
1934 }
1935 
1936 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1937 // Description:
1938 // Allows all previously banned IPs to connect.
1939 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1941 {
1942  unsigned index;
1943  index = 0;
1944  banListMutex.Lock();
1945 
1946  for ( ; index < banList.Size(); index++ )
1947  {
1948  rakFree_Ex(banList[ index ]->IP, _FILE_AND_LINE_ );
1950  }
1951 
1952  banList.Clear(false, _FILE_AND_LINE_);
1953 
1954  banListMutex.Unlock();
1955 }
1956 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1958 {
1960 }
1961 
1962 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1963 // Description:
1964 // Determines if a particular IP is banned.
1965 //
1966 // Parameters
1967 // IP - Complete dotted IP address
1968 //
1969 // Returns
1970 // True if IP matches any IPs in the ban list, accounting for any wildcards.
1971 // False otherwise.
1972 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1973 bool RakPeer::IsBanned( const char *IP )
1974 {
1975  unsigned banListIndex, characterIndex;
1976  SLNet::TimeMS time;
1977  BanStruct *temp;
1978 
1979  if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
1980  return false;
1981 
1982  banListIndex = 0;
1983 
1984  if ( banList.Size() == 0 )
1985  return false; // Skip the mutex if possible
1986 
1987  time = SLNet::GetTimeMS();
1988 
1989  banListMutex.Lock();
1990 
1991  while ( banListIndex < banList.Size() )
1992  {
1993  if (banList[ banListIndex ]->timeout>0 && banList[ banListIndex ]->timeout<time)
1994  {
1995  // Delete expired ban
1996  temp = banList[ banListIndex ];
1997  banList[ banListIndex ] = banList[ banList.Size() - 1 ];
1998  banList.RemoveAtIndex( banList.Size() - 1 );
1999  rakFree_Ex(temp->IP, _FILE_AND_LINE_ );
2001  }
2002  else
2003  {
2004  characterIndex = 0;
2005 
2006  for(;;)
2007  {
2008  if ( banList[ banListIndex ]->IP[ characterIndex ] == IP[ characterIndex ] )
2009  {
2010  // Equal characters
2011 
2012  if ( IP[ characterIndex ] == 0 )
2013  {
2014  banListMutex.Unlock();
2015  // End of the string and the strings match
2016 
2017  return true;
2018  }
2019 
2020  characterIndex++;
2021  }
2022 
2023  else
2024  {
2025  if ( banList[ banListIndex ]->IP[ characterIndex ] == 0 || IP[ characterIndex ] == 0 )
2026  {
2027  // End of one of the strings
2028  break;
2029  }
2030 
2031  // Characters do not match
2032  if ( banList[ banListIndex ]->IP[ characterIndex ] == '*' )
2033  {
2034  banListMutex.Unlock();
2035 
2036  // Domain is banned.
2037  return true;
2038  }
2039 
2040  // Characters do not match and it is not a *
2041  break;
2042  }
2043  }
2044 
2045  banListIndex++;
2046  }
2047  }
2048 
2049  banListMutex.Unlock();
2050 
2051  // No match found.
2052  return false;
2053 }
2054 
2055 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2056 // Description:
2057 // Send a ping to the specified connected system.
2058 //
2059 // Parameters:
2060 // target - who to ping
2061 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2062 void RakPeer::Ping( const SystemAddress target )
2063 {
2064  PingInternal(target, false, UNRELIABLE);
2065 }
2066 
2067 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2068 // Description:
2069 // Send a ping to the specified unconnected system.
2070 // The remote system, if it is Initialized, will respond with ID_UNCONNECTED_PONG.
2071 // The final ping time will be encoded in the following sizeof(SLNet::TimeMS) bytes. (Default is 4 bytes - See __GET_TIME_64BIT in types.h
2072 //
2073 // Parameters:
2074 // host: Either a dotted IP address or a domain name. Can be 255.255.255.255 for LAN broadcast.
2075 // remotePort: Which port to connect to on the remote machine.
2076 // onlyReplyOnAcceptingConnections: Only request a reply if the remote system has open connections
2077 // connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on.
2078 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2079 bool RakPeer::Ping( const char* host, unsigned short remotePort, bool onlyReplyOnAcceptingConnections, unsigned connectionSocketIndex )
2080 {
2081  if ( host == 0 )
2082  return false;
2083 
2084  // If this assert hits then Startup wasn't called or the call failed.
2085  RakAssert(connectionSocketIndex < socketList.Size());
2086 
2087 // if ( IsActive() == false )
2088 // return;
2089 
2090  SLNet::BitStream bitStream( sizeof(unsigned char) + sizeof(SLNet::Time) );
2091  if ( onlyReplyOnAcceptingConnections )
2093  else
2094  bitStream.Write((MessageID)ID_UNCONNECTED_PING);
2095 
2096  bitStream.Write(SLNet::GetTime());
2097 
2098  bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
2099 
2100  bitStream.Write(GetMyGUID());
2101 
2102  // No timestamp for 255.255.255.255
2103  unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
2104  /*
2105 
2106  SystemAddress systemAddress;
2107  systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
2108  systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
2109 
2110  unsigned i;
2111  for (i=0; i < pluginListNTS.Size(); i++)
2112  pluginListNTS[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
2113  SocketLayer::SendTo( socketList[realIndex], (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
2114  */
2115 
2116  RNS2_SendParameters bsp;
2117  bsp.data = (char*) bitStream.GetData() ;
2118  bsp.length = bitStream.GetNumberOfBytesUsed();
2119  bsp.systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
2121  return false;
2122  bsp.systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
2123  unsigned i;
2124  for (i=0; i < pluginListNTS.Size(); i++)
2125  pluginListNTS[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), bsp.systemAddress);
2126  socketList[realIndex]->Send(&bsp, _FILE_AND_LINE_);
2127 
2128  return true;
2129 }
2130 
2131 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2132 // Description:
2133 // Returns the average of all ping times read for a specified target
2134 //
2135 // Parameters:
2136 // target - whose time to read
2137 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2138 int RakPeer::GetAveragePing( const AddressOrGUID systemIdentifier )
2139 {
2140  int sum, quantity;
2141  RemoteSystemStruct *remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2142 
2143  if ( remoteSystem == 0 )
2144  return -1;
2145 
2146  for ( sum = 0, quantity = 0; quantity < PING_TIMES_ARRAY_SIZE; quantity++ )
2147  {
2148  if ( remoteSystem->pingAndClockDifferential[ quantity ].pingTime == 65535 )
2149  break;
2150  else
2151  sum += remoteSystem->pingAndClockDifferential[ quantity ].pingTime;
2152  }
2153 
2154  if ( quantity > 0 )
2155  return sum / quantity;
2156  else
2157  return -1;
2158 }
2159 
2160 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2161 // Description:
2162 // Returns the last ping time read for the specific player or -1 if none read yet
2163 //
2164 // Parameters:
2165 // target - whose time to read
2166 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2167 int RakPeer::GetLastPing( const AddressOrGUID systemIdentifier ) const
2168 {
2169  RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2170 
2171  if ( remoteSystem == 0 )
2172  return -1;
2173 
2174 // return (int)(remoteSystem->reliabilityLayer.GetAckPing()/(SLNet::TimeUS)1000);
2175 
2176  if ( remoteSystem->pingAndClockDifferentialWriteIndex == 0 )
2177  return remoteSystem->pingAndClockDifferential[ PING_TIMES_ARRAY_SIZE - 1 ].pingTime;
2178  else
2179  return remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex - 1 ].pingTime;
2180 }
2181 
2182 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2183 // Description:
2184 // Returns the lowest ping time read or -1 if none read yet
2185 //
2186 // Parameters:
2187 // target - whose time to read
2188 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2189 int RakPeer::GetLowestPing( const AddressOrGUID systemIdentifier ) const
2190 {
2191  RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2192 
2193  if ( remoteSystem == 0 )
2194  return -1;
2195 
2196  return remoteSystem->lowestPing;
2197 }
2198 
2199 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2200 // Description:
2201 // Ping the remote systems every so often. This is off by default
2202 // This will work anytime
2203 //
2204 // Parameters:
2205 // doPing - True to start occasional pings. False to stop them.
2206 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2207 void RakPeer::SetOccasionalPing( bool doPing )
2208 {
2209  occasionalPing = doPing;
2210 }
2211 
2212 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2216 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2218 {
2219  RemoteSystemStruct *remoteSystem = GetRemoteSystem(systemIdentifier, false, false);
2220  if (remoteSystem == 0)
2221  return 0;
2222  return GetClockDifferentialInt(remoteSystem);
2223 }
2224 
2225 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2226 
2228 {
2229  int counter, lowestPingSoFar;
2230  SLNet::Time clockDifferential;
2231 
2232  lowestPingSoFar = 65535;
2233 
2234  clockDifferential = 0;
2235 
2236  for ( counter = 0; counter < PING_TIMES_ARRAY_SIZE; counter++ )
2237  {
2238  if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime == 65535 )
2239  break;
2240 
2241  if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime < lowestPingSoFar )
2242  {
2243  clockDifferential = remoteSystem->pingAndClockDifferential[ counter ].clockDifferential;
2244  lowestPingSoFar = remoteSystem->pingAndClockDifferential[ counter ].pingTime;
2245  }
2246  }
2247 
2248  return clockDifferential;
2249 }
2250 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2251 // Description:
2252 // Length should be under 400 bytes, as a security measure against flood attacks
2253 // Sets the data to send with an (LAN server discovery) /(offline ping) response
2254 // See the Ping sample project for how this is used.
2255 // data: a block of data to store, or 0 for none
2256 // length: The length of data in bytes, or 0 for none
2257 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2258 void RakPeer::SetOfflinePingResponse( const char *data, const unsigned int length )
2259 {
2260  RakAssert(length < 400);
2261 
2264 
2265  if ( data && length > 0 )
2266  offlinePingResponse.Write( data, length );
2267 
2269 }
2270 
2271 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2272 // Returns pointers to a copy of the data passed to SetOfflinePingResponse
2273 // \param[out] data A pointer to a copy of the data passed to \a SetOfflinePingResponse()
2274 // \param[out] length A pointer filled in with the length parameter passed to SetOfflinePingResponse()
2275 // \sa SetOfflinePingResponse
2276 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2277 void RakPeer::GetOfflinePingResponse( char **data, unsigned int *length )
2278 {
2280  *data = (char*) offlinePingResponse.GetData();
2281  *length = (int) offlinePingResponse.GetNumberOfBytesUsed();
2283 }
2284 
2285 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2286 // Description:
2287 // Return the unique SystemAddress that represents you on the the network
2288 // Note that unlike in previous versions, this is a struct and is not sequential
2289 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2290 SystemAddress RakPeer::GetInternalID( const SystemAddress systemAddress, const int index ) const
2291 {
2292  if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
2293  {
2294  return ipList[index];
2295  }
2296  else
2297  {
2298 
2299 // SystemAddress returnValue;
2300  RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, false, true );
2301  if (remoteSystem==0)
2303 
2304  return remoteSystem->theirInternalSystemAddress[index];
2305  /*
2306  sockaddr_in sa;
2307  socklen_t len = sizeof(sa);
2308  if (getsockname__(connectionSockets[remoteSystem->connectionSocketIndex], (sockaddr*)&sa, &len)!=0)
2309  return UNASSIGNED_SYSTEM_ADDRESS;
2310  returnValue.port=ntohs(sa.sin_port);
2311  returnValue.binaryAddress=sa.sin_addr.s_addr;
2312  return returnValue;
2313 */
2314 
2315 
2316 
2317  }
2318 }
2319 
2320 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2324 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2325 void RakPeer::SetInternalID(SystemAddress systemAddress, int index)
2326 {
2327  RakAssert(index >=0 && index < MAXIMUM_NUMBER_OF_INTERNAL_IDS);
2328  ipList[index]=systemAddress;
2329 }
2330 
2331 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2332 // Description:
2333 // Return the unique address identifier that represents you on the the network and is based on your external
2334 // IP / port (the IP / port the specified player uses to communicate with you)
2335 // Note that unlike in previous versions, this is a struct and is not sequential
2336 //
2337 // Parameters:
2338 // target: Which remote system you are referring to for your external ID
2339 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2341 {
2342  unsigned i;
2343  SystemAddress inactiveExternalId;
2344 
2345  inactiveExternalId=UNASSIGNED_SYSTEM_ADDRESS;
2346 
2347  if (target==UNASSIGNED_SYSTEM_ADDRESS)
2348  return firstExternalID;
2349 
2350  // First check for active connection with this systemAddress
2351  for ( i = 0; i < maximumNumberOfPeers; i++ )
2352  {
2353  if (remoteSystemList[ i ].systemAddress == target )
2354  {
2355  if ( remoteSystemList[ i ].isActive )
2357  else if (remoteSystemList[ i ].myExternalSystemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
2358  inactiveExternalId=remoteSystemList[ i ].myExternalSystemAddress;
2359  }
2360  }
2361 
2362  return inactiveExternalId;
2363 }
2364 
2365 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2366 
2368 {
2369  return myGuid;
2370 }
2371 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2373 {
2375  GetSockets( sockets );
2376  if (sockets.Size()>0)
2377  return sockets[socketIndex]->GetBoundAddress();
2378  else
2380 }
2381 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2382 
2384 {
2385  if (input==UNASSIGNED_SYSTEM_ADDRESS)
2386  return myGuid;
2387 
2389  return remoteSystemList[ input.systemIndex ].guid;
2390 
2391  unsigned int i;
2392  for ( i = 0; i < maximumNumberOfPeers; i++ )
2393  {
2394  if (remoteSystemList[ i ].systemAddress == input )
2395  {
2396  // Set the systemIndex so future lookups will be fast
2398 
2399  return remoteSystemList[ i ].guid;
2400  }
2401  }
2402 
2403  return UNASSIGNED_RAKNET_GUID;
2404 }
2405 
2406 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2407 
2408 unsigned int RakPeer::GetSystemIndexFromGuid( const RakNetGUID input ) const
2409 {
2410  if (input==UNASSIGNED_RAKNET_GUID)
2411  return (unsigned int) -1;
2412 
2413  if (input==myGuid)
2414  return (unsigned int) -1;
2415 
2416  if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
2417  return input.systemIndex;
2418 
2419  unsigned int i;
2420  for ( i = 0; i < maximumNumberOfPeers; i++ )
2421  {
2422  if (remoteSystemList[ i ].guid == input )
2423  {
2424  // Set the systemIndex so future lookups will be fast
2426 
2427  return i;
2428  }
2429  }
2430 
2431  return (unsigned int) -1;
2432 }
2433 
2434 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2435 
2437 {
2438  if (input==UNASSIGNED_RAKNET_GUID)
2440 
2441  if (input==myGuid)
2443 
2444  if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
2445  return remoteSystemList[ input.systemIndex ].systemAddress;
2446 
2447  unsigned int i;
2448  for ( i = 0; i < maximumNumberOfPeers; i++ )
2449  {
2450  if (remoteSystemList[ i ].guid == input )
2451  {
2452  // Set the systemIndex so future lookups will be fast
2454 
2455  return remoteSystemList[ i ].systemAddress;
2456  }
2457  }
2458 
2460 }
2461 
2462 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2463 
2464 bool RakPeer::GetClientPublicKeyFromSystemAddress( const SystemAddress input, char *client_public_key ) const
2465 {
2466 #if LIBCAT_SECURITY == 1
2467  if (input == UNASSIGNED_SYSTEM_ADDRESS)
2468  return false;
2469 
2470  char *copy_source = 0;
2471 
2473  {
2474  copy_source = remoteSystemList[ input.systemIndex ].client_public_key;
2475  }
2476  else
2477  {
2478  for ( unsigned int i = 0; i < maximumNumberOfPeers; i++ )
2479  {
2480  if (remoteSystemList[ i ].systemAddress == input )
2481  {
2482  copy_source = remoteSystemList[ i ].client_public_key;
2483  break;
2484  }
2485  }
2486  }
2487 
2488  if (copy_source)
2489  {
2490  // Verify that at least one byte in the public key is non-zero to indicate that the key was received
2491  for (int ii = 0; ii < cat::EasyHandshake::PUBLIC_KEY_BYTES; ++ii)
2492  {
2493  if (copy_source[ii] != 0)
2494  {
2495  memcpy(client_public_key, copy_source, cat::EasyHandshake::PUBLIC_KEY_BYTES);
2496  return true;
2497  }
2498  }
2499  }
2500 
2501 #else
2502  (void) input;
2503  (void) client_public_key;
2504 #endif
2505 
2506  return false;
2507 }
2508 
2509 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2510 // Set the time, in MS, to use before considering ourselves disconnected after not being able to deliver a reliable packet
2511 // \param[in] time Time, in MS
2512 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2514 {
2515  if (target==UNASSIGNED_SYSTEM_ADDRESS)
2516  {
2517  defaultTimeoutTime=timeMS;
2518 
2519  unsigned i;
2520  for ( i = 0; i < maximumNumberOfPeers; i++ )
2521  {
2522  if (remoteSystemList[ i ].isActive)
2523  {
2524  if ( remoteSystemList[ i ].isActive )
2526  }
2527  }
2528  }
2529  else
2530  {
2531  RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
2532 
2533  if ( remoteSystem != 0 )
2534  remoteSystem->reliabilityLayer.SetTimeoutTime(timeMS);
2535  }
2536 }
2537 
2538 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2539 
2541 {
2542  if (target==UNASSIGNED_SYSTEM_ADDRESS)
2543  {
2544  return defaultTimeoutTime;
2545  }
2546  else
2547  {
2548  RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
2549 
2550  if ( remoteSystem != 0 )
2551  return remoteSystem->reliabilityLayer.GetTimeoutTime();
2552  }
2553  return defaultTimeoutTime;
2554 }
2555 
2556 
2557 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2558 // Description:
2559 // Returns the current MTU size
2560 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2561 int RakPeer::GetMTUSize( const SystemAddress target ) const
2562 {
2563  if (target!=UNASSIGNED_SYSTEM_ADDRESS)
2564  {
2565  RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(target, false, true);
2566  if (rss)
2567  return rss->MTUSize;
2568  }
2569  return defaultMTUSize;
2570 }
2571 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2572 // Description:
2573 // Returns the number of IP addresses we have
2574 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2575 unsigned int RakPeer::GetNumberOfAddresses( void )
2576 {
2577  if (IsActive() == false) {
2578  FillIPList();
2579  }
2580 
2581  for (int i = 0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS && ipList[i] != UNASSIGNED_SYSTEM_ADDRESS; i++) {
2582  if (ipList[i] == UNASSIGNED_SYSTEM_ADDRESS) {
2583  return i; // first unassigned address entry found -> end of address list reached
2584  }
2585  }
2586 
2588 }
2589 
2590 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2591 // Returns an IP address at index 0 to GetNumberOfAddresses-1
2592 // \param[in] index index into the list of IP addresses
2593 // \return The local IP address at this index
2594 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2595 const char* RakPeer::GetLocalIP( unsigned int index )
2596 {
2597  if (IsActive()==false)
2598  {
2599  // Fill out ipList structure
2600 
2601  FillIPList();
2602 
2603  }
2604 
2605 
2606  static char str[128];
2607  ipList[index].ToString(false,str,static_cast<size_t>(128));
2608  return str;
2609 
2610 
2611 
2612 
2613 }
2614 
2615 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2616 // Is this a local IP?
2617 // \param[in] An IP address to check
2618 // \return True if this is one of the IP addresses returned by GetLocalIP
2619 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2620 bool RakPeer::IsLocalIP( const char *ip )
2621 {
2622  if (ip==0 || ip[0]==0)
2623  return false;
2624 
2625 
2626  if (strcmp(ip, "127.0.0.1")==0 || strcmp(ip, "localhost")==0)
2627  return true;
2628 
2629  int num = GetNumberOfAddresses();
2630  int i;
2631  for (i=0; i < num; i++)
2632  {
2633  if (strcmp(ip, GetLocalIP(i))==0)
2634  return true;
2635  }
2636 
2637 
2638 
2639 
2640  return false;
2641 }
2642 
2643 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2644 // Description:
2645 // Allow or disallow connection responses from any IP. Normally this should be false, but may be necessary
2646 // when connection to servers with multiple IP addresses
2647 //
2648 // Parameters:
2649 // allow - True to allow this behavior, false to not allow. Defaults to false. Value persists between connections
2650 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2652 {
2654 }
2655 
2656 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2657 // Description:
2658 // Sends a message ID_ADVERTISE_SYSTEM to the remote unconnected system.
2659 // This will tell the remote system our external IP outside the LAN, and can be used for NAT punch through
2660 //
2661 // Requires:
2662 // The sender and recipient must already be started via a successful call to Initialize
2663 //
2664 // host: Either a dotted IP address or a domain name
2665 // remotePort: Which port to connect to on the remote machine.
2666 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2667 bool RakPeer::AdvertiseSystem( const char *host, unsigned short remotePort, const char *data, int dataLength, unsigned connectionSocketIndex )
2668 {
2669  SLNet::BitStream bs;
2671  bs.WriteAlignedBytes((const unsigned char*) data,dataLength);
2672  return SendOutOfBand(host, remotePort, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), connectionSocketIndex );
2673 }
2674 
2675 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2676 // Controls how often to return ID_DOWNLOAD_PROGRESS for large message downloads.
2677 // ID_DOWNLOAD_PROGRESS is returned to indicate a new partial message chunk, roughly the MTU size, has arrived
2678 // As it can be slow or cumbersome to get this notification for every chunk, you can set the interval at which it is returned.
2679 // Defaults to 0 (never return this notification)
2680 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2682 {
2683  RakAssert(interval>=0);
2685  for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
2686  remoteSystemList[ i ].reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval);
2687 }
2688 
2689 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2690 // Returns what was passed to SetSplitMessageProgressInterval()
2691 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2693 {
2695 }
2696 
2697 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2698 // Set how long to wait before giving up on sending an unreliable message
2699 // Useful if the network is clogged up.
2700 // Set to 0 or less to never timeout. Defaults to 0.
2701 // timeoutMS How many ms to wait before simply not sending an unreliable message.
2702 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2704 {
2705  unreliableTimeout=timeoutMS;
2706  for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
2707  remoteSystemList[ i ].reliabilityLayer.SetUnreliableTimeout(unreliableTimeout);
2708 }
2709 
2710 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2711 // Send a message to host, with the IP socket option TTL set to 3
2712 // This message will not reach the host, but will open the router.
2713 // Used for NAT-Punchthrough
2714 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2715 void RakPeer::SendTTL( const char* host, unsigned short remotePort, int ttl, unsigned connectionSocketIndex )
2716 {
2717 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
2718  char fakeData[2];
2719  fakeData[0]=0;
2720  fakeData[1]=1;
2721  unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
2722  if (socketList[realIndex]->IsBerkleySocket())
2723  {
2724  RNS2_SendParameters bsp;
2725  bsp.data = (char*) fakeData;
2726  bsp.length = 2;
2727  bsp.systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
2728  bsp.systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
2729  bsp.ttl=ttl;
2730  unsigned i;
2731  for (i=0; i < pluginListNTS.Size(); i++)
2732  pluginListNTS[i]->OnDirectSocketSend((const char*)bsp.data, BYTES_TO_BITS(bsp.length), bsp.systemAddress);
2733  socketList[realIndex]->Send(&bsp, _FILE_AND_LINE_);
2734  }
2735 #endif
2736 }
2737 
2738 
2739 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2740 // Attatches a Plugin interface to run code automatically on message receipt in the Receive call
2741 //
2742 // \param messageHandler Pointer to a plugin to attach
2743 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2745 {
2746  bool isNotThreadsafe = plugin->UsesReliabilityLayer();
2747  if (isNotThreadsafe)
2748  {
2750  {
2751  plugin->SetRakPeerInterface(this);
2752  plugin->OnAttach();
2754  }
2755  }
2756  else
2757  {
2759  {
2760  plugin->SetRakPeerInterface(this);
2761  plugin->OnAttach();
2763  }
2764  }
2765 }
2766 
2767 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2768 // Detaches a Plugin interface to run code automatically on message receipt
2769 //
2770 // \param messageHandler Pointer to a plugin to detach
2771 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2773 {
2774  if (plugin==0)
2775  return;
2776 
2777  unsigned int index;
2778 
2779  bool isNotThreadsafe = plugin->UsesReliabilityLayer();
2780  if (isNotThreadsafe)
2781  {
2782  index = pluginListNTS.GetIndexOf(plugin);
2783  if (index!=MAX_UNSIGNED_LONG)
2784  {
2785  // Unordered list so delete from end for speed
2788  }
2789  }
2790  else
2791  {
2792  index = pluginListTS.GetIndexOf(plugin);
2793  if (index!=MAX_UNSIGNED_LONG)
2794  {
2795  // Unordered list so delete from end for speed
2798  }
2799  }
2800  plugin->OnDetach();
2801  plugin->SetRakPeerInterface(0);
2802 }
2803 
2804 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2805 // Put a packet back at the end of the receive queue in case you don't want to deal with it immediately
2806 //
2807 // packet The packet you want to push back.
2808 // pushAtHead True to push the packet so that the next receive call returns it. False to push it at the end of the queue (obviously pushing it at the end makes the packets out of order)
2809 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2810 void RakPeer::PushBackPacket( Packet *packet, bool pushAtHead)
2811 {
2812  if (packet==0)
2813  return;
2814 
2815  unsigned i;
2816  for (i=0; i < pluginListTS.Size(); i++)
2817  pluginListTS[i]->OnPushBackPacket((const char*) packet->data, packet->bitSize, packet->systemAddress);
2818  for (i=0; i < pluginListNTS.Size(); i++)
2819  pluginListNTS[i]->OnPushBackPacket((const char*) packet->data, packet->bitSize, packet->systemAddress);
2820 
2822  if (pushAtHead)
2824  else
2827 }
2828 
2829 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2831 {
2832  BufferedCommandStruct *bcs;
2833 
2835  bcs->data = 0;
2836  bcs->systemIdentifier.systemAddress=systemAddress;
2837  bcs->systemIdentifier.rakNetGuid=guid;
2839  bufferedCommands.Push(bcs);
2840 }
2841 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2842 Packet* RakPeer::AllocatePacket(unsigned dataSize)
2843 {
2844  return AllocPacket(dataSize, _FILE_AND_LINE_);
2845 }
2846 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2848 {
2849  // Send a query to the thread to get the socket, and return when we got it
2850  BufferedCommandStruct *bcs;
2853  bcs->systemIdentifier=target;
2854  bcs->data=0;
2855  bufferedCommands.Push(bcs);
2856 
2857  // Block up to one second to get the socket, although it should actually take virtually no time
2858  SocketQueryOutput *sqo;
2859  SLNet::TimeMS stopWaiting = SLNet::GetTimeMS()+1000;
2861  while (SLNet::GetTimeMS() < stopWaiting)
2862  {
2863  if (isMainLoopThreadActive==false)
2864  return 0;
2865 
2866  RakSleep(0);
2867 
2868  sqo = socketQueryOutput.Pop();
2869  if (sqo)
2870  {
2871  output=sqo->sockets;
2872  sqo->sockets.Clear(false, _FILE_AND_LINE_);
2874  if (output.Size())
2875  return output[0];
2876  break;
2877  }
2878  }
2879  return 0;
2880 }
2881 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2883 {
2884  sockets.Clear(false, _FILE_AND_LINE_);
2885 
2886  // Send a query to the thread to get the socket, and return when we got it
2887  BufferedCommandStruct *bcs;
2888 
2892  bcs->data=0;
2893  bufferedCommands.Push(bcs);
2894 
2895  // Block up to one second to get the socket, although it should actually take virtually no time
2896  SocketQueryOutput *sqo;
2897 // RakNetSocket2* output;
2898  for(;;)
2899  {
2900  if (isMainLoopThreadActive==false)
2901  return;
2902 
2903  RakSleep(0);
2904 
2905  sqo = socketQueryOutput.Pop();
2906  if (sqo)
2907  {
2908  sockets=sqo->sockets;
2909  sqo->sockets.Clear(false, _FILE_AND_LINE_);
2911  return;
2912  }
2913  }
2914  return;
2915 }
2917 {
2918  sockets.Clear(false,_FILE_AND_LINE_);
2919 }
2920 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2921 
2922 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2923 // Adds simulated ping and packet loss to the outgoing data flow.
2924 // To simulate bi-directional ping and packet loss, you should call this on both the sender and the recipient, with half the total ping and maxSendBPS value on each.
2925 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2926 void RakPeer::ApplyNetworkSimulator( float packetloss, unsigned short minExtraPing, unsigned short extraPingVariance)
2927 {
2928 #ifdef _DEBUG
2929  if (remoteSystemList)
2930  {
2931  unsigned short i;
2932  for (i=0; i < maximumNumberOfPeers; i++)
2933  //for (i=0; i < remoteSystemListSize; i++)
2934  remoteSystemList[i].reliabilityLayer.ApplyNetworkSimulator(packetloss, minExtraPing, extraPingVariance);
2935  }
2936 
2937  _packetloss=packetloss;
2938  _minExtraPing=minExtraPing;
2939  _extraPingVariance=extraPingVariance;
2940 #endif
2941 }
2942 
2943 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2944 
2945 void RakPeer::SetPerConnectionOutgoingBandwidthLimit( unsigned maxBitsPerSecond )
2946 {
2947  maxOutgoingBPS=maxBitsPerSecond;
2948 }
2949 
2950 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2951 // Returns if you previously called ApplyNetworkSimulator
2952 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2954 {
2955 #ifdef _DEBUG
2956  return _packetloss>0 || _minExtraPing>0 || _extraPingVariance>0;
2957 #else
2958  return false;
2959 #endif
2960 }
2961 
2962 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2964 {
2966  bitStream->Write(myGuid);
2967  bitStream->WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
2968 }
2969 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2970 void RakPeer::SetUserUpdateThread(void (*_userUpdateThreadPtr)(RakPeerInterface *, void *), void *_userUpdateThreadData)
2971 {
2972  userUpdateThreadPtr=_userUpdateThreadPtr;
2973  userUpdateThreadData=_userUpdateThreadData;
2974 }
2975 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2976 void RakPeer::SetIncomingDatagramEventHandler( bool (*_incomingDatagramEventHandler)(RNS2RecvStruct *) )
2977 {
2978  incomingDatagramEventHandler=_incomingDatagramEventHandler;
2979 }
2980 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2981 bool RakPeer::SendOutOfBand(const char *host, unsigned short remotePort, const char *data, BitSize_t dataLength, unsigned connectionSocketIndex )
2982 {
2983  if ( IsActive() == false )
2984  return false;
2985 
2986  if (host==0 || host[0]==0)
2987  return false;
2988 
2989  // If this assert hits then Startup wasn't called or the call failed.
2990  RakAssert(connectionSocketIndex < socketList.Size());
2991 
2992  // This is a security measure. Don't send data longer than this value
2993  RakAssert(dataLength <= (MAX_OFFLINE_DATA_LENGTH + sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID)));
2994 
2995  if (host==0)
2996  return false;
2997 
2998  // 34 bytes
2999  SLNet::BitStream bitStream;
3000  WriteOutOfBandHeader(&bitStream);
3001 
3002  if (dataLength>0)
3003  {
3004  bitStream.Write(data, dataLength);
3005  }
3006 
3007  unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
3008 
3009  /*
3010  SystemAddress systemAddress;
3011  systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
3012  systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
3013 
3014  unsigned i;
3015  for (i=0; i < pluginListNTS.Size(); i++)
3016  pluginListNTS[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
3017 
3018  SocketLayer::SendTo( socketList[realIndex], (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
3019  */
3020 
3021  RNS2_SendParameters bsp;
3022  bsp.data = (char*) bitStream.GetData();
3023  bsp.length = bitStream.GetNumberOfBytesUsed();
3024  bsp.systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
3025  bsp.systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
3026  unsigned i;
3027  for (i=0; i < pluginListNTS.Size(); i++)
3028  pluginListNTS[i]->OnDirectSocketSend((const char*)bsp.data, BYTES_TO_BITS(bsp.length), bsp.systemAddress);
3029  socketList[realIndex]->Send(&bsp, _FILE_AND_LINE_);
3030 
3031  return true;
3032 }
3033 
3034 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3036 {
3037  static RakNetStatistics staticStatistics;
3038  RakNetStatistics *systemStats;
3039  if (rns==0)
3040  systemStats=&staticStatistics;
3041  else
3042  systemStats=rns;
3043 
3044  if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
3045  {
3046  bool firstWrite=false;
3047  // Return a crude sum
3048  for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
3049  {
3050  if (remoteSystemList[ i ].isActive)
3051  {
3052  RakNetStatistics rnsTemp;
3054 
3055  if (firstWrite==false)
3056  {
3057  memcpy(systemStats, &rnsTemp, sizeof(RakNetStatistics));
3058  firstWrite=true;
3059  }
3060  else
3061  (*systemStats)+=rnsTemp;
3062  }
3063  }
3064  return systemStats;
3065  }
3066  else
3067  {
3068  RemoteSystemStruct * rss;
3069  rss = GetRemoteSystemFromSystemAddress( systemAddress, false, false );
3070  if ( rss && endThreads==false )
3071  {
3072  rss->reliabilityLayer.GetStatistics(systemStats);
3073  return systemStats;
3074  }
3075  }
3076 
3077  return 0;
3078 }
3079 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3081 {
3082  addresses.Clear(false, _FILE_AND_LINE_);
3083  guids.Clear(false, _FILE_AND_LINE_);
3084  statistics.Clear(false, _FILE_AND_LINE_);
3085 
3086  if ( remoteSystemList == 0 || endThreads == true )
3087  return;
3088 
3089  unsigned int i;
3090  for (i=0; i < activeSystemListSize; i++)
3091  {
3092  if ((activeSystemList[i])->isActive &&
3094  {
3095  addresses.Push((activeSystemList[i])->systemAddress, _FILE_AND_LINE_ );
3096  guids.Push((activeSystemList[i])->guid, _FILE_AND_LINE_ );
3097  RakNetStatistics rns;
3098  (activeSystemList[i])->reliabilityLayer.GetStatistics(&rns);
3099  statistics.Push(rns, _FILE_AND_LINE_);
3100  }
3101  }
3102 }
3103 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3104 bool RakPeer::GetStatistics( const unsigned int index, RakNetStatistics *rns )
3105 {
3106  if (index < maximumNumberOfPeers && remoteSystemList[ index ].isActive)
3107  {
3109  return true;
3110  }
3111  return false;
3112 }
3113 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3115 {
3116  unsigned int size;
3118  size=packetReturnQueue.Size();
3120  return size;
3121 }
3122 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3123 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread ) const
3124 {
3125  unsigned i;
3126 
3127  if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
3128  return -1;
3129 
3130  if (systemAddress.systemIndex!=(SystemIndex)-1 && systemAddress.systemIndex < maximumNumberOfPeers && remoteSystemList[systemAddress.systemIndex].systemAddress==systemAddress && remoteSystemList[ systemAddress.systemIndex ].isActive)
3131  return systemAddress.systemIndex;
3132 
3133  if (calledFromNetworkThread)
3134  {
3135  return GetRemoteSystemIndex(systemAddress);
3136  }
3137  else
3138  {
3139  // remoteSystemList in user and network thread
3140  for ( i = 0; i < maximumNumberOfPeers; i++ )
3141  if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].systemAddress == systemAddress )
3142  return i;
3143 
3144  // If no active results found, try previously active results.
3145  for ( i = 0; i < maximumNumberOfPeers; i++ )
3146  if ( remoteSystemList[ i ].systemAddress == systemAddress )
3147  return i;
3148  }
3149 
3150  return -1;
3151 }
3152 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3154 {
3155  unsigned i;
3156 
3157  if ( guid == UNASSIGNED_RAKNET_GUID )
3158  return -1;
3159 
3161  return guid.systemIndex;
3162 
3163  // remoteSystemList in user and network thread
3164  for ( i = 0; i < maximumNumberOfPeers; i++ )
3165  if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].guid == guid )
3166  return i;
3167 
3168  // If no active results found, try previously active results.
3169  for ( i = 0; i < maximumNumberOfPeers; i++ )
3170  if ( remoteSystemList[ i ].guid == guid )
3171  return i;
3172 
3173  return -1;
3174 }
3175 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3176 #if LIBCAT_SECURITY==1
3177 bool RakPeer::GenerateConnectionRequestChallenge(RequestedConnectionStruct *rcs,PublicKey *publicKey)
3178 {
3179  CAT_AUDIT_PRINTF("AUDIT: In GenerateConnectionRequestChallenge()\n");
3180 
3181  rcs->client_handshake = 0;
3182  rcs->publicKeyMode = PKM_INSECURE_CONNECTION;
3183 
3184  if (!publicKey) return true;
3185 
3186  switch (publicKey->publicKeyMode)
3187  {
3188  default:
3190  break;
3191 
3193  CAT_OBJCLR(rcs->remote_public_key);
3194  rcs->client_handshake = SLNet::OP_NEW<cat::ClientEasyHandshake>(_FILE_AND_LINE_);
3195 
3196  rcs->publicKeyMode = PKM_ACCEPT_ANY_PUBLIC_KEY;
3197  break;
3198 
3200  if (publicKey->myPublicKey == 0 || publicKey->myPrivateKey == 0 ||
3201  publicKey->remoteServerPublicKey == 0)
3202  {
3203  return false;
3204  }
3205 
3206  rcs->client_handshake = SLNet::OP_NEW<cat::ClientEasyHandshake>(_FILE_AND_LINE_);
3207  memcpy(rcs->remote_public_key, publicKey->remoteServerPublicKey, cat::EasyHandshake::PUBLIC_KEY_BYTES);
3208 
3209  if (!rcs->client_handshake->Initialize(publicKey->remoteServerPublicKey) ||
3210  !rcs->client_handshake->SetIdentity(publicKey->myPublicKey, publicKey->myPrivateKey) ||
3211  !rcs->client_handshake->GenerateChallenge(rcs->handshakeChallenge))
3212  {
3213  CAT_AUDIT_PRINTF("AUDIT: Failure initializing new client_handshake object with identity for this RequestedConnectionStruct\n");
3214  SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3215  rcs->client_handshake=0;
3216  return false;
3217  }
3218 
3219  CAT_AUDIT_PRINTF("AUDIT: Success initializing new client handshake object with identity for this RequestedConnectionStruct -- pre-generated challenge\n");
3220 
3221  rcs->publicKeyMode = PKM_USE_TWO_WAY_AUTHENTICATION;
3222  break;
3223 
3225  if (publicKey->remoteServerPublicKey == 0)
3226  return false;
3227 
3228  rcs->client_handshake = SLNet::OP_NEW<cat::ClientEasyHandshake>(_FILE_AND_LINE_);
3229  memcpy(rcs->remote_public_key, publicKey->remoteServerPublicKey, cat::EasyHandshake::PUBLIC_KEY_BYTES);
3230 
3231  if (!rcs->client_handshake->Initialize(publicKey->remoteServerPublicKey) ||
3232  !rcs->client_handshake->GenerateChallenge(rcs->handshakeChallenge))
3233  {
3234  CAT_AUDIT_PRINTF("AUDIT: Failure initializing new client_handshake object for this RequestedConnectionStruct\n");
3235  SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3236  rcs->client_handshake=0;
3237  return false;
3238  }
3239 
3240  CAT_AUDIT_PRINTF("AUDIT: Success initializing new client handshake object for this RequestedConnectionStruct -- pre-generated challenge\n");
3241 
3242  rcs->publicKeyMode = PKM_USE_KNOWN_PUBLIC_KEY;
3243  break;
3244  }
3245 
3246  return true;
3247 }
3248 #endif
3249 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3250 ConnectionAttemptResult RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, PublicKey *publicKey, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime )
3251 {
3252  RakAssert(passwordDataLength <= 256);
3253  RakAssert(remotePort!=0);
3254  SystemAddress systemAddress;
3255  if (!systemAddress.FromStringExplicitPort(host,remotePort,socketList[connectionSocketIndex]->GetBoundAddress().GetIPVersion()))
3257 
3258  // Already connected?
3259  if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
3261 
3262  //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), _FILE_AND_LINE_);
3263  RequestedConnectionStruct *rcs = SLNet::OP_NEW<RequestedConnectionStruct>(_FILE_AND_LINE_);
3264 
3265  rcs->systemAddress=systemAddress;
3267  rcs->requestsMade=0;
3268  rcs->data=0;
3269  rcs->socket=0;
3270  rcs->extraData=extraData;
3271  rcs->socketIndex=connectionSocketIndex;
3273  rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
3274  rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
3275  memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
3276  rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
3277  rcs->timeoutTime=timeoutTime;
3278 
3279 #if LIBCAT_SECURITY==1
3280  CAT_AUDIT_PRINTF("AUDIT: In SendConnectionRequest()\n");
3281  if (!GenerateConnectionRequestChallenge(rcs,publicKey))
3283 #else
3284  (void) publicKey;
3285 #endif
3286 
3287  // Return false if already pending, else push on queue
3288  unsigned int i=0;
3290  for (; i < requestedConnectionQueue.Size(); i++)
3291  {
3292  if (requestedConnectionQueue[i]->systemAddress==systemAddress)
3293  {
3295  // Not necessary
3296  //SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3299  }
3300  }
3303 
3305 }
3306 ConnectionAttemptResult RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, PublicKey *publicKey, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime, RakNetSocket2* socket )
3307 {
3308  RakAssert(passwordDataLength <= 256);
3309  SystemAddress systemAddress;
3310  systemAddress.FromStringExplicitPort(host,remotePort);
3311 
3312  // Already connected?
3313  if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
3315 
3316  //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), _FILE_AND_LINE_);
3317  RequestedConnectionStruct *rcs = SLNet::OP_NEW<RequestedConnectionStruct>(_FILE_AND_LINE_);
3318 
3319  rcs->systemAddress=systemAddress;
3321  rcs->requestsMade=0;
3322  rcs->data=0;
3323  rcs->socket=0;
3324  rcs->extraData=extraData;
3325  rcs->socketIndex=connectionSocketIndex;
3327  rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
3328  rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
3329  memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
3330  rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
3331  rcs->timeoutTime=timeoutTime;
3332  rcs->socket=socket;
3333 
3334 #if LIBCAT_SECURITY==1
3335  if (!GenerateConnectionRequestChallenge(rcs,publicKey))
3337 #else
3338  (void) publicKey;
3339 #endif
3340 
3341  // Return false if already pending, else push on queue
3342  unsigned int i=0;
3344  for (; i < requestedConnectionQueue.Size(); i++)
3345  {
3346  if (requestedConnectionQueue[i]->systemAddress==systemAddress)
3347  {
3349  // Not necessary
3350  //SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3353  }
3354  }
3357 
3359 }
3360 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3362 {
3363 }
3364 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3365 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystem( const AddressOrGUID systemIdentifier, bool calledFromNetworkThread, bool onlyActive ) const
3366 {
3367  if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
3368  return GetRemoteSystemFromGUID(systemIdentifier.rakNetGuid, onlyActive);
3369  else
3370  return GetRemoteSystemFromSystemAddress(systemIdentifier.systemAddress, calledFromNetworkThread, onlyActive);
3371 }
3372 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3373 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread, bool onlyActive ) const
3374 {
3375  unsigned i;
3376 
3377  if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
3378  return 0;
3379 
3380  if (calledFromNetworkThread)
3381  {
3382  unsigned int index = GetRemoteSystemIndex(systemAddress);
3383  if (index!=(unsigned int) -1)
3384  {
3385  if (onlyActive==false || remoteSystemList[ index ].isActive==true )
3386  {
3387  RakAssert(remoteSystemList[index].systemAddress==systemAddress);
3388  return remoteSystemList + index;
3389  }
3390  }
3391  }
3392  else
3393  {
3394  int deadConnectionIndex=-1;
3395 
3396  // Active connections take priority. But if there are no active connections, return the first systemAddress match found
3397  for ( i = 0; i < maximumNumberOfPeers; i++ )
3398  {
3399  if (remoteSystemList[ i ].systemAddress == systemAddress)
3400  {
3401  if ( remoteSystemList[ i ].isActive )
3402  return remoteSystemList + i;
3403  else if (deadConnectionIndex==-1)
3404  deadConnectionIndex=i;
3405  }
3406  }
3407 
3408  if (deadConnectionIndex!=-1 && onlyActive==false)
3409  return remoteSystemList + deadConnectionIndex;
3410  }
3411 
3412  return 0;
3413 }
3414 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3416 {
3417  if (guid==UNASSIGNED_RAKNET_GUID)
3418  return 0;
3419 
3420  unsigned i;
3421  for ( i = 0; i < maximumNumberOfPeers; i++ )
3422  {
3423  if (remoteSystemList[ i ].guid == guid && (onlyActive==false || remoteSystemList[ i ].isActive))
3424  {
3425  return remoteSystemList + i;
3426  }
3427  }
3428  return 0;
3429 }
3430 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3431 void RakPeer::ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, const SystemAddress &systemAddress, const char *data, int byteSize )
3432 {
3433  SLNet::BitStream bs((unsigned char*) data,byteSize,false);
3434  bs.IgnoreBytes(sizeof(MessageID));
3435  RakNetGUID guid;
3436  bs.Read(guid);
3437  SLNet::Time incomingTimestamp;
3438  bs.Read(incomingTimestamp);
3439  unsigned char doSecurity;
3440  bs.Read(doSecurity);
3441 
3442 #if LIBCAT_SECURITY==1
3443  unsigned char doClientKey;
3444  if (_using_security)
3445  {
3446  // Ignore message on bad state
3447  if (doSecurity != 1 || !remoteSystem->reliabilityLayer.GetAuthenticatedEncryption())
3448  return;
3449 
3450  // Validate client proof of key
3451  unsigned char proof[cat::EasyHandshake::PROOF_BYTES];
3452  bs.ReadAlignedBytes(proof, sizeof(proof));
3453  if (!remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()->ValidateProof(proof, sizeof(proof)))
3454  {
3456  return;
3457  }
3458 
3459  CAT_OBJCLR(remoteSystem->client_public_key);
3460 
3461  bs.Read(doClientKey);
3462 
3463  // Check if client wants to prove identity
3464  if (doClientKey == 1)
3465  {
3466  // Read identity proof
3467  unsigned char ident[cat::EasyHandshake::IDENTITY_BYTES];
3468  bs.ReadAlignedBytes(ident, sizeof(ident));
3469 
3470  // If we are listening to these proofs,
3471  if (_require_client_public_key)
3472  {
3473  // Validate client identity
3474  if (!_server_handshake->VerifyInitiatorIdentity(remoteSystem->answer, ident, remoteSystem->client_public_key))
3475  {
3476  SLNet::BitStream bitStream;
3477  bitStream.Write((MessageID)ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY); // Report an error since the client is not providing an identity when it is necessary to connect
3478  bitStream.Write((unsigned char)2); // Indicate client identity is invalid
3479  SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3481  return;
3482  }
3483  }
3484 
3485  // Otherwise ignore the client public key
3486  }
3487  else
3488  {
3489  // If no client key was provided but it is required,
3490  if (_require_client_public_key)
3491  {
3492  SLNet::BitStream bitStream;
3493  bitStream.Write((MessageID)ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY); // Report an error since the client is not providing an identity when it is necessary to connect
3494  bitStream.Write((unsigned char)1); // Indicate client identity is missing
3495  SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3497  return;
3498  }
3499  }
3500  }
3501 #endif // LIBCAT_SECURITY
3502 
3503  unsigned char *password = bs.GetData()+BITS_TO_BYTES(bs.GetReadOffset());
3504  int passwordLength = byteSize - BITS_TO_BYTES(bs.GetReadOffset());
3505  if ( incomingPasswordLength != passwordLength ||
3506  memcmp( password, incomingPassword, incomingPasswordLength ) != 0 )
3507  {
3508  CAT_AUDIT_PRINTF("AUDIT: Invalid password\n");
3509  // This one we only send once since we don't care if it arrives.
3510  SLNet::BitStream bitStream;
3511  bitStream.Write((MessageID)ID_INVALID_PASSWORD);
3513  SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3515  return;
3516  }
3517 
3518  // OK
3520 
3521  OnConnectionRequest( remoteSystem, incomingTimestamp );
3522 }
3523 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3525 {
3526  SLNet::BitStream bitStream;
3528  bitStream.Write(remoteSystem->systemAddress);
3529  SystemIndex systemIndex = (SystemIndex) GetIndexFromSystemAddress( remoteSystem->systemAddress, true );
3530  RakAssert(systemIndex!=65535);
3531  bitStream.Write(systemIndex);
3532  for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
3533  bitStream.Write(ipList[i]);
3534  bitStream.Write(incomingTimestamp);
3535  bitStream.Write(SLNet::GetTime());
3536 
3537  SendImmediate((char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, remoteSystem->systemAddress, false, false, SLNet::GetTimeUS(), 0);
3538 }
3539 
3540 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3541 void RakPeer::NotifyAndFlagForShutdown( const SystemAddress systemAddress, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
3542 {
3543  SLNet::BitStream temp( sizeof(unsigned char) );
3545  if (performImmediate)
3546  {
3547  SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3548  RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(systemAddress, true, true);
3549  rss->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
3550  }
3551  else
3552  {
3553  SendBuffered((const char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, RemoteSystemStruct::DISCONNECT_ASAP, 0);
3554  }
3555 }
3556 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3558 {
3559  if ( remoteSystemList == 0 || endThreads == true )
3560  return 0;
3561 
3562  unsigned int numberOfIncomingConnections;
3563  numberOfIncomingConnections = 0;
3564  unsigned int i;
3565  for (i=0; i < activeSystemListSize; i++)
3566  {
3567  if ((activeSystemList[i])->isActive &&
3569  (activeSystemList[i])->weInitiatedTheConnection==false
3570  )
3571  {
3572  numberOfIncomingConnections++;
3573  }
3574  }
3575  return numberOfIncomingConnections;
3576 }
3577 
3578 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3579 RakPeer::RemoteSystemStruct * RakPeer::AssignSystemAddressToRemoteSystemList( const SystemAddress systemAddress, RemoteSystemStruct::ConnectMode connectionMode, RakNetSocket2* incomingRakNetSocket, bool *thisIPConnectedRecently, SystemAddress bindingAddress, int incomingMTU, RakNetGUID guid, bool useSecurity )
3580 {
3581  RemoteSystemStruct * remoteSystem;
3582  unsigned i,j,assignedIndex;
3584 #ifdef _DEBUG
3585  RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
3586 #endif
3587 
3589  {
3590  if (IsLoopbackAddress(systemAddress,false)==false)
3591  {
3592  for ( i = 0; i < maximumNumberOfPeers; i++ )
3593  {
3594  if ( remoteSystemList[ i ].isActive==true &&
3595  remoteSystemList[ i ].systemAddress.EqualsExcludingPort(systemAddress) &&
3596  time >= remoteSystemList[ i ].connectionTime &&
3597  time - remoteSystemList[ i ].connectionTime < 100
3598  )
3599  {
3600  // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
3601  // Ignore connection attempts if this IP address connected within the last 100 milliseconds
3602  *thisIPConnectedRecently=true;
3604  return 0;
3605  }
3606  }
3607  }
3608  }
3609 
3610  // Don't use a different port than what we received on
3611  bindingAddress.CopyPort(incomingRakNetSocket->GetBoundAddress());
3612 
3613  *thisIPConnectedRecently=false;
3614  for ( assignedIndex = 0; assignedIndex < maximumNumberOfPeers; assignedIndex++ )
3615  {
3616  if ( remoteSystemList[ assignedIndex ].isActive==false )
3617  {
3618  // printf("--- Address %s has become active\n", systemAddress.ToString());
3619 
3620  remoteSystem=remoteSystemList+assignedIndex;
3621  ReferenceRemoteSystem(systemAddress, assignedIndex);
3622  remoteSystem->MTUSize=defaultMTUSize;
3623  remoteSystem->guid=guid;
3624  remoteSystem->isActive = true; // This one line causes future incoming packets to go through the reliability layer
3625  // Reserve this reliability layer for ourselves.
3626  if (incomingMTU > remoteSystem->MTUSize)
3627  remoteSystem->MTUSize=incomingMTU;
3628  RakAssert(remoteSystem->MTUSize <= MAXIMUM_MTU_SIZE);
3629  remoteSystem->reliabilityLayer.Reset(true, remoteSystem->MTUSize, useSecurity);
3633  AddToActiveSystemList(assignedIndex);
3634  if (incomingRakNetSocket->GetBoundAddress()==bindingAddress)
3635  {
3636  remoteSystem->rakNetSocket=incomingRakNetSocket;
3637  }
3638  else
3639  {
3640  char str[256];
3641  bindingAddress.ToString(true,str,static_cast<size_t>(256));
3642  // See if this is an internal IP address.
3643  // If so, force binding on it so we reply on the same IP address as they sent to.
3644  unsigned int ipListIndex, foundIndex=(unsigned int)-1;
3645 
3646  for (ipListIndex=0; ipListIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipListIndex++)
3647  {
3648  if (ipList[ipListIndex]==UNASSIGNED_SYSTEM_ADDRESS)
3649  break;
3650 
3651  if (bindingAddress.EqualsExcludingPort(ipList[ipListIndex]))
3652  {
3653  foundIndex=ipListIndex;
3654  break;
3655  }
3656  }
3657 
3658  // 06/26/09 Unconfirmed report that Vista firewall blocks the reply if we force a binding
3659  // For now use the incoming socket only
3660  // Originally this code was to force a machine with multiple IP addresses to reply back on the IP
3661  // that the datagram came in on
3662  //if (1 || foundIndex==(unsigned int)-1)
3663  //{
3664  // Must not be an internal LAN address. Just use whatever socket it came in on
3665  remoteSystem->rakNetSocket=incomingRakNetSocket;
3666  //}
3667  //else
3668  //{
3669  /*
3670  // Force binding
3671  unsigned int socketListIndex;
3672  for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
3673  {
3674  if (socketList[socketListIndex]->GetBoundAddress()==bindingAddress)
3675  {
3676  // Force binding with existing socket
3677  remoteSystem->rakNetSocket=socketList[socketListIndex];
3678  break;
3679  }
3680  }
3681 
3682  if (socketListIndex==socketList.Size())
3683  {
3684  char ipListFoundIndexStr[128];
3685  ipList[foundIndex].ToString(false,str);
3686 
3687  // Force binding with new socket
3688  RakNetSocket* rns(SLNet::OP_NEW<RakNetSocket>(_FILE_AND_LINE_));
3689  if (incomingRakNetSocket->GetRemotePortRakNetWasStartedOn()==0)
3690  rns = SocketLayer::CreateBoundSocket( this, bindingAddress.GetPort(), incomingRakNetSocket->GetBlockingSocket(), ipListFoundIndexStr, 0, incomingRakNetSocket->GetExtraSocketOptions(), incomingRakNetSocket->GetSocketFamily(), incomingRakNetSocket->GetChromeInstance() );
3691  else
3692  rns = SocketLayer::CreateBoundSocket_PS3Lobby( bindingAddress.GetPort(), incomingRakNetSocket->GetBlockingSocket(), ipListFoundIndexStr, incomingRakNetSocket->GetSocketFamily() );
3693 
3694 
3695  if (rns==0)
3696  {
3697  // Can't bind. Just use whatever socket it came in on
3698  remoteSystem->rakNetSocket=incomingRakNetSocket;
3699  }
3700  else
3701  {
3702  rns->GetBoundAddress()=bindingAddress;
3703  rns->SetUserConnectionSocketIndex((unsigned int)-1);
3704  socketList.Push(rns, _FILE_AND_LINE_ );
3705  remoteSystem->rakNetSocket=rns;
3706 
3707 
3708 #ifdef _WIN32
3709  int highPriority=THREAD_PRIORITY_ABOVE_NORMAL;
3710 #else
3711  int highPriority=-10;
3712 #endif
3713 
3714  highPriority=0;
3715 
3716 
3717  }
3718  }
3719 
3720  */
3721  //}
3722  }
3723 
3724  for ( j = 0; j < (unsigned) PING_TIMES_ARRAY_SIZE; j++ )
3725  {
3726  remoteSystem->pingAndClockDifferential[ j ].pingTime = 65535;
3727  remoteSystem->pingAndClockDifferential[ j ].clockDifferential = 0;
3728  }
3729 
3730  remoteSystem->connectMode=connectionMode;
3731  remoteSystem->pingAndClockDifferentialWriteIndex = 0;
3732  remoteSystem->lowestPing = 65535;
3733  remoteSystem->nextPingTime = 0; // Ping immediately
3734  remoteSystem->weInitiatedTheConnection = false;
3735  remoteSystem->connectionTime = time;
3737  remoteSystem->lastReliableSend=time;
3738 
3739 #ifdef _DEBUG
3740  int indexLoopupCheck=GetIndexFromSystemAddress( systemAddress, true );
3741  if ((int) indexLoopupCheck!=(int) assignedIndex)
3742  {
3743  RakAssert((int) indexLoopupCheck==(int) assignedIndex);
3744  }
3745 #endif
3746 
3747  return remoteSystem;
3748  }
3749  }
3750 
3751  return 0;
3752 }
3753 
3754 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3755 // Adjust the first four bytes (treated as unsigned int) of the pointer
3756 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3757 void RakPeer::ShiftIncomingTimestamp( unsigned char *data, const SystemAddress &systemAddress ) const
3758 {
3759 #ifdef _DEBUG
3760  RakAssert( IsActive() );
3761  RakAssert( data );
3762 #endif
3763 
3764  SLNet::BitStream timeBS( data, sizeof(SLNet::Time), false);
3765  SLNet::Time encodedTimestamp;
3766  timeBS.Read(encodedTimestamp);
3767 
3768  encodedTimestamp = encodedTimestamp - GetBestClockDifferential( systemAddress );
3769  timeBS.SetWriteOffset(0);
3770  timeBS.Write(encodedTimestamp);
3771 }
3772 
3773 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3774 // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
3776 {
3777  RemoteSystemStruct *remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, true, true );
3778 
3779  if ( remoteSystem == 0 )
3780  return 0;
3781 
3782  return GetClockDifferentialInt(remoteSystem);
3783 }
3784 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3786 {
3788 }
3789 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3790 void RakPeer::ReferenceRemoteSystem(const SystemAddress &sa, unsigned int remoteSystemListIndex)
3791 {
3792 // #ifdef _DEBUG
3793 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
3794 // {
3795 // if (remoteSystemList[remoteSystemIndex].isActive )
3796 // {
3797 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
3798 // RakAssert(hashIndex==remoteSystemIndex);
3799 // }
3800 // }
3801 // #endif
3802 
3803 
3804  SystemAddress oldAddress = remoteSystemList[remoteSystemListIndex].systemAddress;
3805  if (oldAddress!=UNASSIGNED_SYSTEM_ADDRESS)
3806  {
3807  // The system might be active if rerouting
3808 // RakAssert(remoteSystemList[remoteSystemListIndex].isActive==false);
3809 
3810  // Remove the reference if the reference is pointing to this inactive system
3811  if (GetRemoteSystem(oldAddress)==&remoteSystemList[remoteSystemListIndex])
3812  DereferenceRemoteSystem(oldAddress);
3813  }
3815 
3816 // #ifdef _DEBUG
3817 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
3818 // {
3819 // if (remoteSystemList[remoteSystemIndex].isActive )
3820 // {
3821 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
3822 // if (hashIndex!=remoteSystemIndex)
3823 // {
3824 // RakAssert(hashIndex==remoteSystemIndex);
3825 // }
3826 // }
3827 // }
3828 // #endif
3829 
3830 
3831  remoteSystemList[remoteSystemListIndex].systemAddress=sa;
3832 
3833  unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
3834  RemoteSystemIndex *rsi;
3836  if (remoteSystemLookup[hashIndex]==0)
3837  {
3838  rsi->next=0;
3839  rsi->index=remoteSystemListIndex;
3840  remoteSystemLookup[hashIndex]=rsi;
3841  }
3842  else
3843  {
3844  RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
3845  while (cur->next!=0)
3846  {
3847  cur=cur->next;
3848  }
3849 
3851  rsi->next=0;
3852  rsi->index=remoteSystemListIndex;
3853  cur->next=rsi;
3854  }
3855 
3856 // #ifdef _DEBUG
3857 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
3858 // {
3859 // if (remoteSystemList[remoteSystemIndex].isActive )
3860 // {
3861 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
3862 // RakAssert(hashIndex==remoteSystemIndex);
3863 // }
3864 // }
3865 // #endif
3866 
3867 
3868  RakAssert(GetRemoteSystemIndex(sa)==remoteSystemListIndex);
3869 }
3870 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3872 {
3873  unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
3874  RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
3875  RemoteSystemIndex *last = 0;
3876  while (cur!=0)
3877  {
3878  if (remoteSystemList[cur->index].systemAddress==sa)
3879  {
3880  if (last==0)
3881  {
3882  remoteSystemLookup[hashIndex]=cur->next;
3883  }
3884  else
3885  {
3886  last->next=cur->next;
3887  }
3889  break;
3890  }
3891  last=cur;
3892  cur=cur->next;
3893  }
3894 }
3895 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3896 unsigned int RakPeer::GetRemoteSystemIndex(const SystemAddress &sa) const
3897 {
3898  unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
3899  RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
3900  while (cur!=0)
3901  {
3902  if (remoteSystemList[cur->index].systemAddress==sa)
3903  return cur->index;
3904  cur=cur->next;
3905  }
3906  return (unsigned int) -1;
3907 }
3908 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3910 {
3911  unsigned int remoteSystemIndex = GetRemoteSystemIndex(sa);
3912  if (remoteSystemIndex==(unsigned int)-1)
3913  return 0;
3914  return remoteSystemList + remoteSystemIndex;
3915 }
3916 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3918 {
3922 }
3923 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3924 void RakPeer::AddToActiveSystemList(unsigned int remoteSystemListIndex)
3925 {
3926  activeSystemList[activeSystemListSize++]=remoteSystemList+remoteSystemListIndex;
3927 }
3928 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3930 {
3931  unsigned int i;
3932  for (i=0; i < activeSystemListSize; i++)
3933  {
3935  if (rss->systemAddress==sa)
3936  {
3937  activeSystemList[i]=activeSystemList[activeSystemListSize-1];
3938  activeSystemListSize--;
3939  return;
3940  }
3941  }
3942  RakAssert("activeSystemList invalid, entry not found in RemoveFromActiveSystemList. Ensure that AddToActiveSystemList and RemoveFromActiveSystemList are called by the same thread." && 0);
3943 }
3944 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3945 /*
3946 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3947 unsigned int RakPeer::LookupIndexUsingHashIndex(const SystemAddress &sa) const
3948 {
3949  unsigned int scanCount=0;
3950  unsigned int index = RemoteSystemLookupHashIndex(sa);
3951  if (remoteSystemLookup[index].index==(unsigned int)-1)
3952  return (unsigned int) -1;
3953  while (remoteSystemList[remoteSystemLookup[index].index].systemAddress!=sa)
3954  {
3955  if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
3956  index=0;
3957  if (++scanCount>(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
3958  return (unsigned int) -1;
3959  if (remoteSystemLookup[index].index==-1)
3960  return (unsigned int) -1;
3961  }
3962  return index;
3963 }
3964 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3965 unsigned int RakPeer::RemoteSystemListIndexUsingHashIndex(const SystemAddress &sa) const
3966 {
3967  unsigned int index = LookupIndexUsingHashIndex(sa);
3968  if (index!=(unsigned int) -1)
3969  {
3970  return remoteSystemLookup[index].index;
3971  }
3972  return (unsigned int) -1;
3973 }
3974 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3975 unsigned int RakPeer::FirstFreeRemoteSystemLookupIndex(const SystemAddress &sa) const
3976 {
3977 // unsigned int collisionCount=0;
3978  unsigned int index = RemoteSystemLookupHashIndex(sa);
3979  while (remoteSystemLookup[index].index!=(unsigned int)-1)
3980  {
3981  if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
3982  index=0;
3983 // collisionCount++;
3984  }
3985 // printf("%i collisions. Using index %i\n", collisionCount, index);
3986  return index;
3987 }
3988 */
3989 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3990 bool RakPeer::IsLoopbackAddress(const AddressOrGUID &systemIdentifier, bool matchPort) const
3991 {
3992  if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
3993  return systemIdentifier.rakNetGuid==myGuid;
3994 
3995  for (int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS && ipList[i]!=UNASSIGNED_SYSTEM_ADDRESS; i++)
3996  {
3997  if (matchPort)
3998  {
3999  if (ipList[i]==systemIdentifier.systemAddress)
4000  return true;
4001  }
4002  else
4003  {
4004  if (ipList[i].EqualsExcludingPort(systemIdentifier.systemAddress))
4005  return true;
4006  }
4007  }
4008 
4009  return (matchPort==true && systemIdentifier.systemAddress==firstExternalID) ||
4010  (matchPort==false && systemIdentifier.systemAddress.EqualsExcludingPort(firstExternalID));
4011 }
4012 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4014 {
4015 
4016  return ipList[0];
4017 
4018 
4019 
4020 }
4021 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4023 {
4025 }
4026 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4027 void RakPeer::DeallocRNS2RecvStruct(RNS2RecvStruct *s, const char *file, unsigned int line)
4028 {
4030  bufferedPacketsFreePool.Push(s, file, line);
4032 }
4033 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4034 RNS2RecvStruct *RakPeer::AllocRNS2RecvStruct(const char *file, unsigned int line)
4035 {
4037  if (bufferedPacketsFreePool.Size()>0)
4038  {
4041  return s;
4042  }
4043  else
4044  {
4046  return SLNet::OP_NEW<RNS2RecvStruct>(file,line);
4047  }
4048 }
4049 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4051 {
4053  while (bufferedPacketsFreePool.Size()>0)
4056 
4058  while (bufferedPacketsQueue.Size()>0)
4061 }
4062 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4064 {
4065 }
4066 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4068 {
4072 }
4073 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4075 {
4077  if (bufferedPacketsQueue.Size()>0)
4078  {
4081  return s;
4082  }
4084  return 0;
4085 }
4086 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4087 void RakPeer::PingInternal( const SystemAddress target, bool performImmediate, PacketReliability reliability )
4088 {
4089  if ( IsActive() == false )
4090  return ;
4091 
4092  SLNet::BitStream bitStream(sizeof(unsigned char)+sizeof(SLNet::Time));
4093  bitStream.Write((MessageID)ID_CONNECTED_PING);
4094  bitStream.Write(SLNet::GetTime());
4095  if (performImmediate)
4096  SendImmediate( (char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, reliability, 0, target, false, false, SLNet::GetTimeUS(), 0 );
4097  else
4098  Send( &bitStream, IMMEDIATE_PRIORITY, reliability, 0, target, false );
4099 }
4100 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4101 void RakPeer::CloseConnectionInternal( const AddressOrGUID& systemIdentifier, bool sendDisconnectionNotification, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
4102 {
4103 #ifdef _DEBUG
4104  RakAssert(orderingChannel < 32);
4105 #endif
4106 
4107  if (systemIdentifier.IsUndefined())
4108  return;
4109 
4110  if ( remoteSystemList == 0 || endThreads == true )
4111  return;
4112 
4113  SystemAddress target;
4114  if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
4115  {
4116  target=systemIdentifier.systemAddress;
4117  }
4118  else
4119  {
4120  target=GetSystemAddressFromGuid(systemIdentifier.rakNetGuid);
4121  }
4122 
4123  if (target!=UNASSIGNED_SYSTEM_ADDRESS && performImmediate)
4124  target.FixForIPVersion(socketList[0]->GetBoundAddress());
4125 
4126  if (sendDisconnectionNotification)
4127  {
4128  NotifyAndFlagForShutdown(target, performImmediate, orderingChannel, disconnectionNotificationPriority);
4129  }
4130  else
4131  {
4132  if (performImmediate)
4133  {
4134  unsigned int index = GetRemoteSystemIndex(target);
4135  if (index!=(unsigned int) -1)
4136  {
4137  if ( remoteSystemList[index].isActive )
4138  {
4140 
4141  // Found the index to stop
4142  // printf("--- Address %s has become inactive\n", remoteSystemList[index].systemAddress.ToString());
4143  remoteSystemList[index].isActive = false;
4144 
4146 
4147  // Reserve this reliability layer for ourselves
4148  //remoteSystemList[ remoteSystemLookup[index].index ].systemAddress = UNASSIGNED_SYSTEM_ADDRESS;
4149 
4150  // Clear any remaining messages
4151  RakAssert(remoteSystemList[index].MTUSize <= MAXIMUM_MTU_SIZE);
4152  remoteSystemList[index].reliabilityLayer.Reset(false, remoteSystemList[index].MTUSize, false);
4153 
4154  // Not using this socket
4155  remoteSystemList[index].rakNetSocket = 0;
4156  }
4157  }
4158  }
4159  else
4160  {
4161  BufferedCommandStruct *bcs;
4164  bcs->systemIdentifier=target;
4165  bcs->data=0;
4166  bcs->orderingChannel=orderingChannel;
4167  bcs->priority=disconnectionNotificationPriority;
4168  bufferedCommands.Push(bcs);
4169  }
4170  }
4171 }
4172 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4173 void RakPeer::SendBuffered( const char *data, BitSize_t numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RemoteSystemStruct::ConnectMode connectionMode, uint32_t receipt )
4174 {
4175  BufferedCommandStruct *bcs;
4176 
4178  bcs->data = (char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES(numberOfBitsToSend), _FILE_AND_LINE_ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
4179  if (bcs->data==0)
4180  {
4183  return;
4184  }
4185 
4186  RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
4187  RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
4188  RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
4189 
4190  memcpy(bcs->data, data, (size_t) BITS_TO_BYTES(numberOfBitsToSend));
4191  bcs->numberOfBitsToSend=numberOfBitsToSend;
4192  bcs->priority=priority;
4193  bcs->reliability=reliability;
4194  bcs->orderingChannel=orderingChannel;
4195  bcs->systemIdentifier=systemIdentifier;
4196  bcs->broadcast=broadcast;
4197  bcs->connectionMode=connectionMode;
4198  bcs->receipt=receipt;
4200  bufferedCommands.Push(bcs);
4201 
4202  if (priority==IMMEDIATE_PRIORITY)
4203  {
4204  // Forces pending sends to go out now, rather than waiting to the next update interval
4206  }
4207 }
4208 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4209 void RakPeer::SendBufferedList( const char **data, const int *lengths, const int numParameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RemoteSystemStruct::ConnectMode connectionMode, uint32_t receipt )
4210 {
4211  BufferedCommandStruct *bcs;
4212  unsigned int totalLength=0;
4213  unsigned int lengthOffset;
4214  int i;
4215  for (i=0; i < numParameters; i++)
4216  {
4217  if (lengths[i]>0)
4218  totalLength+=lengths[i];
4219  }
4220  if (totalLength==0)
4221  return;
4222 
4223  char *dataAggregate;
4224  dataAggregate = (char*) rakMalloc_Ex( (size_t) totalLength, _FILE_AND_LINE_ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
4225  if (dataAggregate==0)
4226  {
4228  return;
4229  }
4230  for (i=0, lengthOffset=0; i < numParameters; i++)
4231  {
4232  if (lengths[i]>0)
4233  {
4234  memcpy(dataAggregate+lengthOffset, data[i], lengths[i]);
4235  lengthOffset+=lengths[i];
4236  }
4237  }
4238 
4239  if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
4240  {
4241  SendLoopback(dataAggregate,totalLength);
4242  rakFree_Ex(dataAggregate,_FILE_AND_LINE_);
4243  return;
4244  }
4245 
4246  RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
4247  RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
4248  RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
4249 
4251  bcs->data = dataAggregate;
4252  bcs->numberOfBitsToSend=BYTES_TO_BITS(totalLength);
4253  bcs->priority=priority;
4254  bcs->reliability=reliability;
4255  bcs->orderingChannel=orderingChannel;
4256  bcs->systemIdentifier=systemIdentifier;
4257  bcs->broadcast=broadcast;
4258  bcs->connectionMode=connectionMode;
4259  bcs->receipt=receipt;
4261  bufferedCommands.Push(bcs);
4262 
4263  if (priority==IMMEDIATE_PRIORITY)
4264  {
4265  // Forces pending sends to go out now, rather than waiting to the next update interval
4267  }
4268 }
4269 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4270 bool RakPeer::SendImmediate( char *data, BitSize_t numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, bool useCallerDataAllocation, SLNet::TimeUS currentTime, uint32_t receipt )
4271 {
4272  unsigned *sendList;
4273  unsigned sendListSize;
4274  bool callerDataAllocationUsed;
4275  unsigned int remoteSystemIndex, sendListIndex; // Iterates into the list of remote systems
4276 // unsigned numberOfBytesUsed = (unsigned) BITS_TO_BYTES(numberOfBitsToSend);
4277  callerDataAllocationUsed=false;
4278 
4279  sendListSize=0;
4280 
4281  if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
4282  remoteSystemIndex=GetIndexFromSystemAddress( systemIdentifier.systemAddress, true );
4283  else if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
4284  remoteSystemIndex=GetSystemIndexFromGuid(systemIdentifier.rakNetGuid);
4285  else
4286  remoteSystemIndex=(unsigned int) -1;
4287 
4288  // 03/06/06 - If broadcast is false, use the optimized version of GetIndexFromSystemAddress
4289  if (broadcast==false)
4290  {
4291  if (remoteSystemIndex==(unsigned int) -1)
4292  {
4293 #ifdef _DEBUG
4294 // int debugIndex = GetRemoteSystemIndex(systemIdentifier.systemAddress);
4295 #endif
4296  return false;
4297  }
4298 
4299  #if USE_ALLOCA==1
4300  sendList=(unsigned *)alloca(sizeof(unsigned));
4301  #else
4302  sendList = (unsigned *) rakMalloc_Ex(sizeof(unsigned), _FILE_AND_LINE_);
4303  #endif
4304 
4305  if (remoteSystemList[remoteSystemIndex].isActive &&
4306  remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP &&
4307  remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY &&
4308  remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
4309  {
4310  sendList[0]=remoteSystemIndex;
4311  sendListSize=1;
4312  }
4313  }
4314  else
4315  {
4316  #if USE_ALLOCA==1
4317  sendList=(unsigned *)alloca(sizeof(unsigned)*maximumNumberOfPeers);
4318  #else
4319  sendList = (unsigned *) rakMalloc_Ex(sizeof(unsigned)*maximumNumberOfPeers, _FILE_AND_LINE_);
4320  #endif
4321 
4322  // remoteSystemList in network thread
4323  unsigned int idx;
4324  for ( idx = 0; idx < maximumNumberOfPeers; idx++ )
4325  {
4326  if (remoteSystemIndex!=(unsigned int) -1 && idx==remoteSystemIndex)
4327  continue;
4328 
4329  if ( remoteSystemList[ idx ].isActive && remoteSystemList[ idx ].systemAddress != UNASSIGNED_SYSTEM_ADDRESS )
4330  sendList[sendListSize++]=idx;
4331  }
4332  }
4333 
4334  if (sendListSize==0)
4335  {
4336  #if !defined(USE_ALLOCA)
4337  rakFree_Ex(sendList, _FILE_AND_LINE_ );
4338  #endif
4339 
4340  return false;
4341  }
4342 
4343  for (sendListIndex=0; sendListIndex < sendListSize; sendListIndex++)
4344  {
4345  // Send may split the packet and thus deallocate data. Don't assume data is valid if we use the callerAllocationData
4346  bool useData = useCallerDataAllocation && callerDataAllocationUsed==false && sendListIndex+1==sendListSize;
4347  remoteSystemList[sendList[sendListIndex]].reliabilityLayer.Send( data, numberOfBitsToSend, priority, reliability, orderingChannel, useData==false, remoteSystemList[sendList[sendListIndex]].MTUSize, currentTime, receipt );
4348  if (useData)
4349  callerDataAllocationUsed=true;
4350 
4351  if (reliability==RELIABLE ||
4352  reliability==RELIABLE_ORDERED ||
4353  reliability==RELIABLE_SEQUENCED ||
4354  reliability==RELIABLE_WITH_ACK_RECEIPT ||
4356 // ||
4357 // reliability==RELIABLE_SEQUENCED_WITH_ACK_RECEIPT
4358  )
4359  remoteSystemList[sendList[sendListIndex]].lastReliableSend=(SLNet::TimeMS)(currentTime/(SLNet::TimeUS)1000);
4360  }
4361 
4362 #if !defined(USE_ALLOCA)
4363  rakFree_Ex(sendList, _FILE_AND_LINE_ );
4364 #endif
4365 
4366  // Return value only meaningful if true was passed for useCallerDataAllocation. Means the reliability layer used that data copy, so the caller should not deallocate it
4367  return callerDataAllocationUsed;
4368 }
4369 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4371 {
4375 }
4376 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4377 void RakPeer::OnConnectedPong(SLNet::Time sendPingTime, SLNet::Time sendPongTime, RemoteSystemStruct *remoteSystem)
4378 {
4379  SLNet::Time ping;
4380 // SLNet::TimeMS lastPing;
4381  SLNet::Time time = SLNet::GetTime(); // Update the time value to be accurate
4382  if (time > sendPingTime)
4383  ping = time - sendPingTime;
4384  else
4385  ping=0;
4386 
4387 // lastPing = remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime;
4388 
4389  remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime = ( unsigned short ) ping;
4390  // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
4391  // Divide each integer by 2, rather than the sum by 2, to prevent overflow
4392  remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].clockDifferential = sendPongTime - ( time/2 + sendPingTime/2 );
4393 
4394  if ( remoteSystem->lowestPing == (unsigned short)-1 || remoteSystem->lowestPing > (int) ping )
4395  remoteSystem->lowestPing = (unsigned short) ping;
4396 
4398  remoteSystem->pingAndClockDifferentialWriteIndex = 0;
4399 }
4400 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4402 {
4403  BufferedCommandStruct *bcs;
4404 
4405  while ((bcs=bufferedCommands.Pop())!=0)
4406  {
4407  if (bcs->data)
4409 
4411  }
4413 }
4414 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4416 {
4418 }
4419 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4421 {
4424  while (requestedConnectionQueue.Size())
4427  unsigned i;
4428  for (i=0; i < freeQueue.Size(); i++)
4429  {
4430 #if LIBCAT_SECURITY==1
4431  CAT_AUDIT_PRINTF("AUDIT: In ClearRequestedConnectionList(), Deleting freeQueue index %i client_handshake %x\n", i, freeQueue[i]->client_handshake);
4432  SLNet::OP_DELETE(freeQueue[i]->client_handshake,_FILE_AND_LINE_);
4433 #endif
4434  SLNet::OP_DELETE(freeQueue[i], _FILE_AND_LINE_ );
4435  }
4436 }
4438 {
4442 }
4443 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4444 union Buff6AndBuff8
4445 {
4446  unsigned char buff6[6];
4447  uint64_t buff8;
4448 };
4450 {
4451  // Mac address is a poor solution because you can't have multiple connections from the same system
4452 
4453 
4454 
4455 
4456 
4457 
4458 
4459 
4460 
4461 
4462 
4463 
4464 
4465 
4466 
4467 
4468 
4469 
4470 
4471 
4472 
4473 
4474 
4475 
4476 
4477 
4478 
4479 
4480 
4481 
4482 #if defined(_WIN32)
4484 
4485  SLNet::TimeUS lastTime, thisTime;
4486  int j;
4487  // Sleep a small random time, then use the last 4 bits as a source of randomness
4488  for (j=0; j < 8; j++)
4489  {
4490  lastTime = SLNet::GetTimeUS();
4491  RakSleep(1);
4492  RakSleep(0);
4493  thisTime = SLNet::GetTimeUS();
4494  SLNet::TimeUS diff = thisTime-lastTime;
4495  unsigned int diff4Bits = (unsigned int) (diff & 15);
4496  diff4Bits <<= 32-4;
4497  diff4Bits >>= j*4;
4498  ((char*)&g)[j] ^= diff4Bits;
4499  }
4500  return g;
4501 
4502 #else
4503  struct timeval tv;
4504  gettimeofday(&tv, NULL);
4505  return tv.tv_usec + tv.tv_sec * 1000000;
4506 #endif
4507 }
4508 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4510 {
4512 
4513 }
4514 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4515 // void SLNet::ProcessPortUnreachable( SystemAddress systemAddress, RakPeer *rakPeer )
4516 // {
4517 // (void) binaryAddress;
4518 // (void) port;
4519 // (void) rakPeer;
4520 //
4521 // }
4522 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4523 namespace SLNet {
4524 bool ProcessOfflineNetworkPacket( SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSocket2* rakNetSocket, bool *isOfflineMessage, SLNet::TimeUS timeRead )
4525 {
4526  (void) timeRead;
4527  RakPeer::RemoteSystemStruct *remoteSystem;
4528  SLNet::Packet *packet;
4529  unsigned i;
4530 
4531 
4532  char str1[64];
4533  systemAddress.ToString(false, str1,static_cast<size_t>(64));
4534  if (rakPeer->IsBanned( str1 ))
4535  {
4536  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4537  rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4538 
4539  SLNet::BitStream bs;
4541  bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
4543 
4544 
4545  RNS2_SendParameters bsp;
4546  bsp.data = (char*) bs.GetData();
4547  bsp.length = bs.GetNumberOfBytesUsed();
4548  bsp.systemAddress = systemAddress;
4549  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4550  rakPeer->pluginListNTS[i]->OnDirectSocketSend((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
4551  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
4552 
4553 /*
4554  unsigned i;
4555  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4556  rakPeer->pluginListNTS[i]->OnDirectSocketSend((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
4557  SocketLayer::SendTo( rakNetSocket, (char*) bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
4558  */
4559 
4560  return true;
4561  }
4562 
4563 
4564 
4565  // The reason for all this is that the reliability layer has no way to tell between offline messages that arrived late for a player that is now connected,
4566  // and a regular encoding. So I insert OFFLINE_MESSAGE_DATA_ID into the stream, the encoding of which is essentially impossible to hit by chance
4567  if (length <=2)
4568  {
4569  *isOfflineMessage=true;
4570  }
4571  else if (
4572  ((unsigned char)data[0] == ID_UNCONNECTED_PING ||
4573  (unsigned char)data[0] == ID_UNCONNECTED_PING_OPEN_CONNECTIONS) &&
4574  length >= sizeof(unsigned char) + sizeof(SLNet::Time) + sizeof(OFFLINE_MESSAGE_DATA_ID))
4575  {
4576  *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(SLNet::Time), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4577  }
4578  else if ((unsigned char)data[0] == ID_UNCONNECTED_PONG && (size_t) length >= sizeof(unsigned char) + sizeof(SLNet::TimeMS) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
4579  {
4580  *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(SLNet::Time) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4581  }
4582  else if (
4583  (unsigned char)data[0] == ID_OUT_OF_BAND_INTERNAL &&
4584  (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
4585  {
4586  *isOfflineMessage=memcmp(data+sizeof(MessageID) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4587  }
4588  else if (
4589  (
4590  (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY_1 ||
4591  (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY_2 ||
4592  (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST_1 ||
4593  (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST_2 ||
4594  (unsigned char)data[0] == ID_CONNECTION_ATTEMPT_FAILED ||
4595  (unsigned char)data[0] == ID_NO_FREE_INCOMING_CONNECTIONS ||
4596  (unsigned char)data[0] == ID_CONNECTION_BANNED ||
4597  (unsigned char)data[0] == ID_ALREADY_CONNECTED ||
4598  (unsigned char)data[0] == ID_IP_RECENTLY_CONNECTED) &&
4599  (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
4600  {
4601  *isOfflineMessage=memcmp(data+sizeof(MessageID), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4602  }
4603  else if (((unsigned char)data[0] == ID_INCOMPATIBLE_PROTOCOL_VERSION&&
4604  (size_t) length == sizeof(MessageID)*2 + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID)))
4605  {
4606  *isOfflineMessage=memcmp(data+sizeof(MessageID)*2, OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4607  }
4608  else
4609  {
4610  *isOfflineMessage=false;
4611  }
4612 
4613  if (*isOfflineMessage)
4614  {
4615  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4616  rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4617 
4618  // These are all messages from unconnected systems. Messages here can be any size, but are never processed from connected systems.
4619  if ( ( (unsigned char) data[ 0 ] == ID_UNCONNECTED_PING_OPEN_CONNECTIONS
4620  || (unsigned char)(data)[0] == ID_UNCONNECTED_PING) && length >= sizeof(unsigned char)+sizeof(SLNet::Time)+sizeof(OFFLINE_MESSAGE_DATA_ID) )
4621  {
4622  if ( (unsigned char)(data)[0] == ID_UNCONNECTED_PING ||
4623  rakPeer->AllowIncomingConnections() ) // Open connections with players
4624  {
4625  SLNet::BitStream inBitStream( (unsigned char *) data, length, false );
4626  inBitStream.IgnoreBits(8);
4627  SLNet::Time sendPingTime;
4628  inBitStream.Read(sendPingTime);
4629  inBitStream.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
4631  inBitStream.Read(remoteGuid);
4632 
4633  SLNet::BitStream outBitStream;
4634  outBitStream.Write((MessageID)ID_UNCONNECTED_PONG); // Should be named ID_UNCONNECTED_PONG eventually
4635  outBitStream.Write(sendPingTime);
4636  outBitStream.Write(rakPeer->myGuid);
4637  outBitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
4638 
4640  // They are connected, so append offline ping data
4641  outBitStream.Write( (char*)rakPeer->offlinePingResponse.GetData(), rakPeer->offlinePingResponse.GetNumberOfBytesUsed() );
4643 
4644  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4645  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*)outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), systemAddress);
4646 
4647  RNS2_SendParameters bsp;
4648  bsp.data = (char*) outBitStream.GetData();
4649  bsp.length = outBitStream.GetNumberOfBytesUsed();
4650  bsp.systemAddress = systemAddress;
4651  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
4652 
4653  // SocketLayer::SendTo( rakNetSocket, (const char*)outBitStream.GetData(), (unsigned int) outBitStream.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
4654 
4655  packet=rakPeer->AllocPacket(sizeof(MessageID), _FILE_AND_LINE_);
4656  packet->data[0]=data[0];
4657  packet->systemAddress = systemAddress;
4658  packet->guid=remoteGuid;
4659  packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
4660  packet->guid.systemIndex=packet->systemAddress.systemIndex;
4661  rakPeer->AddPacketToProducer(packet);
4662  }
4663  }
4664  // UNCONNECTED MESSAGE Pong with no data.
4665  else if ((unsigned char) data[ 0 ] == ID_UNCONNECTED_PONG && (size_t) length >= sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID) && (size_t) length < sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID)+MAX_OFFLINE_DATA_LENGTH)
4666  {
4667  packet=rakPeer->AllocPacket((unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()-sizeof(SLNet::Time)+sizeof(SLNet::TimeMS)), _FILE_AND_LINE_);
4668  SLNet::BitStream bsIn((unsigned char*) data, length, false);
4669  bsIn.IgnoreBytes(sizeof(unsigned char));
4670  SLNet::Time ping;
4671  bsIn.Read(ping);
4672  bsIn.Read(packet->guid);
4673 
4674  SLNet::BitStream bsOut((unsigned char*) packet->data, packet->length, false);
4675  bsOut.ResetWritePointer();
4676  bsOut.Write((unsigned char)ID_UNCONNECTED_PONG);
4677  SLNet::TimeMS pingMS=(SLNet::TimeMS)ping;
4678  bsOut.Write(pingMS);
4679  bsOut.WriteAlignedBytes(
4680  (const unsigned char*)data+sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID),
4681  length-sizeof(unsigned char)-sizeof(SLNet::Time)-RakNetGUID::size()-sizeof(OFFLINE_MESSAGE_DATA_ID)
4682  );
4683 
4684  packet->systemAddress = systemAddress;
4685  packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
4686  packet->guid.systemIndex=packet->systemAddress.systemIndex;
4687  rakPeer->AddPacketToProducer(packet);
4688  }
4689  else if ((unsigned char) data[ 0 ] == ID_OUT_OF_BAND_INTERNAL &&
4690  (size_t) length > sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)+RakNetGUID::size() &&
4691  (size_t) length < MAX_OFFLINE_DATA_LENGTH+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)+RakNetGUID::size())
4692  {
4693  unsigned int dataLength = (unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()-sizeof(MessageID));
4694  RakAssert(dataLength<1024);
4695  packet=rakPeer->AllocPacket(dataLength+1, _FILE_AND_LINE_);
4696  RakAssert(packet->length<1024);
4697 
4698  SLNet::BitStream bs2((unsigned char*) data, length, false);
4699  bs2.IgnoreBytes(sizeof(MessageID));
4700  bs2.Read(packet->guid);
4701 
4703  {
4704  packet->length--;
4705  packet->bitSize=BYTES_TO_BITS(packet->length);
4706  packet->data[0]=ID_ADVERTISE_SYSTEM;
4707  memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)*2 + RakNetGUID::size(), dataLength-1);
4708  }
4709  else
4710  {
4711  packet->data[0]=ID_OUT_OF_BAND_INTERNAL;
4712  memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID) + RakNetGUID::size(), dataLength);
4713  }
4714 
4715  packet->systemAddress = systemAddress;
4716  packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
4717  packet->guid.systemIndex=packet->systemAddress.systemIndex;
4718  rakPeer->AddPacketToProducer(packet);
4719  }
4720  else if ((unsigned char)(data)[0] == (MessageID)ID_OPEN_CONNECTION_REPLY_1)
4721  {
4722  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4723  rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4724 
4725  SLNet::BitStream bsIn((unsigned char*) data,length,false);
4726  bsIn.IgnoreBytes(sizeof(MessageID));
4727  bsIn.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
4728  RakNetGUID serverGuid;
4729  bsIn.Read(serverGuid);
4730  unsigned char serverHasSecurity;
4731  uint32_t cookie;
4732  (void) cookie;
4733  bsIn.Read(serverHasSecurity);
4734  // Even if the server has security, it may not be required of us if we are in the security exception list
4735  if (serverHasSecurity)
4736  {
4737  bsIn.Read(cookie);
4738  }
4739 
4740  SLNet::BitStream bsOut;
4742  bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
4743  if (serverHasSecurity)
4744  bsOut.Write(cookie);
4745 
4747  for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
4748  {
4750  rcs=rakPeer->requestedConnectionQueue[i];
4751  if (rcs->systemAddress==systemAddress)
4752  {
4753  if (serverHasSecurity)
4754  {
4755 #if LIBCAT_SECURITY==1
4756  unsigned char public_key[cat::EasyHandshake::PUBLIC_KEY_BYTES];
4757  bsIn.ReadAlignedBytes(public_key, sizeof(public_key));
4758 
4760  {
4761  memcpy(rcs->remote_public_key, public_key, cat::EasyHandshake::PUBLIC_KEY_BYTES);
4762  if (!rcs->client_handshake->Initialize(public_key) ||
4763  !rcs->client_handshake->GenerateChallenge(rcs->handshakeChallenge))
4764  {
4765  CAT_AUDIT_PRINTF("AUDIT: Server passed a bad public key with PKM_ACCEPT_ANY_PUBLIC_KEY");
4767  return true;
4768  }
4769  }
4770 
4771  if (cat::SecureEqual(public_key,
4772  rcs->remote_public_key,
4773  cat::EasyHandshake::PUBLIC_KEY_BYTES)==false)
4774  {
4776  CAT_AUDIT_PRINTF("AUDIT: Expected public key does not match what was sent by server -- Reporting back ID_PUBLIC_KEY_MISMATCH to user\n");
4777 
4778  packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
4779  packet->data[ 0 ] = ID_PUBLIC_KEY_MISMATCH; // Attempted a connection and couldn't
4780  packet->bitSize = ( sizeof( char ) * 8);
4781  packet->systemAddress = rcs->systemAddress;
4782  packet->guid=serverGuid;
4783  rakPeer->AddPacketToProducer(packet);
4784  return true;
4785  }
4786 
4787  if (rcs->client_handshake==0)
4788  {
4789  // Message does not contain a challenge
4790  // We might still pass if we are in the security exception list
4791  bsOut.Write((unsigned char)0);
4792  }
4793  else
4794  {
4795  // Message contains a challenge
4796  bsOut.Write((unsigned char)1);
4797  // challenge
4798  CAT_AUDIT_PRINTF("AUDIT: Sending challenge\n");
4799  bsOut.WriteAlignedBytes((const unsigned char*) rcs->handshakeChallenge,cat::EasyHandshake::CHALLENGE_BYTES);
4800  }
4801 #else // LIBCAT_SECURITY
4802  // Message does not contain a challenge
4803  bsOut.Write((unsigned char)0);
4804 #endif // LIBCAT_SECURITY
4805  }
4806  else
4807  {
4808  // Server does not need security
4809 #if LIBCAT_SECURITY==1
4810  if (rcs->client_handshake!=0)
4811  {
4813  CAT_AUDIT_PRINTF("AUDIT: Security disabled by server but we expected security (indicated by client_handshake not null) so failing!\n");
4814 
4815  packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
4816  packet->data[ 0 ] = ID_OUR_SYSTEM_REQUIRES_SECURITY; // Attempted a connection and couldn't
4817  packet->bitSize = ( sizeof( char ) * 8);
4818  packet->systemAddress = rcs->systemAddress;
4819  packet->guid=serverGuid;
4820  rakPeer->AddPacketToProducer(packet);
4821  return true;
4822  }
4823 #endif // LIBCAT_SECURITY
4824 
4825  }
4826 
4827  uint16_t mtu;
4828  bsIn.Read(mtu);
4829 
4830  // Binding address
4831  bsOut.Write(rcs->systemAddress);
4833  // MTU
4834  bsOut.Write(mtu);
4835  // Our guid
4837 
4838  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4839  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), rcs->systemAddress);
4840 
4841  // SocketLayer::SendTo( rakPeer->socketList[rcs->socketIndex], (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), rcs->systemAddress, _FILE_AND_LINE_ );
4842 
4843  RNS2_SendParameters bsp;
4844  bsp.data = (char*) bsOut.GetData();
4845  bsp.length = bsOut.GetNumberOfBytesUsed();
4846  bsp.systemAddress = systemAddress;
4847  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
4848 
4849  return true;
4850  }
4851  }
4853  }
4854  else if ((unsigned char)(data)[0] == (MessageID)ID_OPEN_CONNECTION_REPLY_2)
4855  {
4856  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4857  rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4858 
4859  SLNet::BitStream bs((unsigned char*) data,length,false);
4860  bs.IgnoreBytes(sizeof(MessageID));
4862  RakNetGUID guid;
4863  bs.Read(guid);
4864  SystemAddress bindingAddress;
4865  bool b = bs.Read(bindingAddress);
4866  RakAssert(b);
4867  uint16_t mtu;
4868  b=bs.Read(mtu);
4869  RakAssert(b);
4870  bool doSecurity=false;
4871  b=bs.Read(doSecurity);
4872  RakAssert(b);
4873 
4874 #if LIBCAT_SECURITY==1
4875  char answer[cat::EasyHandshake::ANSWER_BYTES];
4876  CAT_AUDIT_PRINTF("AUDIT: Got ID_OPEN_CONNECTION_REPLY_2 and given doSecurity=%i\n", (int)doSecurity);
4877  if (doSecurity)
4878  {
4879  CAT_AUDIT_PRINTF("AUDIT: Reading cookie and public key\n");
4880  bs.ReadAlignedBytes((unsigned char*) answer, sizeof(answer));
4881  }
4882  cat::ClientEasyHandshake *client_handshake=0;
4883 #endif // LIBCAT_SECURITY
4884 
4886  bool unlock=true;
4888  for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
4889  {
4890  rcs=rakPeer->requestedConnectionQueue[i];
4891 
4892 
4893  if (rcs->systemAddress==systemAddress)
4894  {
4895 #if LIBCAT_SECURITY==1
4896  CAT_AUDIT_PRINTF("AUDIT: System address matches an entry in the requestedConnectionQueue and doSecurity=%i\n", (int)doSecurity);
4897  if (doSecurity)
4898  {
4899  if (rcs->client_handshake==0)
4900  {
4901  CAT_AUDIT_PRINTF("AUDIT: Server wants security but we didn't set a public key -- Reporting back ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY to user\n");
4903 
4904  packet=rakPeer->AllocPacket(2, _FILE_AND_LINE_);
4905  packet->data[ 0 ] = ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY; // Attempted a connection and couldn't
4906  packet->data[ 1 ] = 0; // Indicate server public key is missing
4907  packet->bitSize = ( sizeof( char ) * 8);
4908  packet->systemAddress = rcs->systemAddress;
4909  packet->guid=guid;
4910  rakPeer->AddPacketToProducer(packet);
4911  return true;
4912  }
4913 
4914  CAT_AUDIT_PRINTF("AUDIT: Looks good, preparing to send challenge to server! client_handshake = %x\n", client_handshake);
4915  }
4916 
4917 #endif // LIBCAT_SECURITY
4918 
4920  unlock=false;
4921 
4923  // You might get this when already connected because of cross-connections
4924  bool thisIPConnectedRecently=false;
4925  remoteSystem=rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
4926  if (remoteSystem==0)
4927  {
4928  if (rcs->socket == 0)
4929  {
4930  remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, mtu, guid, doSecurity);
4931  }
4932  else
4933  {
4934  remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rcs->socket, &thisIPConnectedRecently, bindingAddress, mtu, guid, doSecurity);
4935  }
4936  }
4937 
4938  // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
4939  // Ignore connection attempts if this IP address connected within the last 100 milliseconds
4940  if (thisIPConnectedRecently==false)
4941  {
4942  // Don't check GetRemoteSystemFromGUID, server will verify
4943  if (remoteSystem)
4944  {
4945  // Move pointer from RequestedConnectionStruct to RemoteSystemStruct
4946 #if LIBCAT_SECURITY==1
4947  cat::u8 ident[cat::EasyHandshake::IDENTITY_BYTES];
4948  bool doIdentity = false;
4949 
4950  if (rcs->client_handshake)
4951  {
4952  CAT_AUDIT_PRINTF("AUDIT: Processing answer\n");
4954  {
4955  if (!rcs->client_handshake->ProcessAnswerWithIdentity(answer, ident, remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()))
4956  {
4957  CAT_AUDIT_PRINTF("AUDIT: Processing answer -- Invalid Answer\n");
4958  return true;
4959  }
4960 
4961  doIdentity = true;
4962  }
4963  else
4964  {
4965  if (!rcs->client_handshake->ProcessAnswer(answer, remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()))
4966  {
4967  CAT_AUDIT_PRINTF("AUDIT: Processing answer -- Invalid Answer\n");
4968  return true;
4969  }
4970  }
4971  CAT_AUDIT_PRINTF("AUDIT: Success!\n");
4972 
4973  SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
4974  rcs->client_handshake=0;
4975  }
4976 #endif // LIBCAT_SECURITY
4977 
4978  remoteSystem->weInitiatedTheConnection=true;
4980  if (rcs->timeoutTime!=0)
4981  remoteSystem->reliabilityLayer.SetTimeoutTime(rcs->timeoutTime);
4982 
4983  SLNet::BitStream temp;
4986  temp.Write(SLNet::GetTime());
4987 
4988 #if LIBCAT_SECURITY==1
4989  temp.Write((unsigned char)(doSecurity ? 1 : 0));
4990 
4991  if (doSecurity)
4992  {
4993  unsigned char proof[32];
4994  remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()->GenerateProof(proof, sizeof(proof));
4995  temp.WriteAlignedBytes(proof, sizeof(proof));
4996 
4997  temp.Write((unsigned char)(doIdentity ? 1 : 0));
4998 
4999  if (doIdentity)
5000  {
5001  temp.WriteAlignedBytes(ident, sizeof(ident));
5002  }
5003  }
5004 #else
5005  temp.Write((unsigned char)0);
5006 #endif // LIBCAT_SECURITY
5007 
5008  if ( rcs->outgoingPasswordLength > 0 )
5009  temp.Write( ( char* ) rcs->outgoingPassword, rcs->outgoingPasswordLength );
5010 
5011  rakPeer->SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, timeRead, 0 );
5012  }
5013  else
5014  {
5015  // Failed, no connections available anymore
5016  packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5017  packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
5018  packet->bitSize = ( sizeof( char ) * 8);
5019  packet->systemAddress = rcs->systemAddress;
5020  packet->guid=guid;
5021  rakPeer->AddPacketToProducer(packet);
5022  }
5023  }
5024 
5026  for (unsigned int k=0; k < rakPeer->requestedConnectionQueue.Size(); k++)
5027  {
5028  if (rakPeer->requestedConnectionQueue[k]->systemAddress==systemAddress)
5029  {
5031  break;
5032  }
5033  }
5035 
5036 #if LIBCAT_SECURITY==1
5037  CAT_AUDIT_PRINTF("AUDIT: Deleting client_handshake object %x and rcs->client_handshake object %x\n", client_handshake, rcs->client_handshake);
5038  SLNet::OP_DELETE(client_handshake,_FILE_AND_LINE_);
5039  SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
5040 #endif // LIBCAT_SECURITY
5042 
5043  break;
5044  }
5045  }
5046 
5047  if (unlock)
5049 
5050  return true;
5051 
5052  }
5053  else if ((unsigned char)(data)[0] == (MessageID)ID_CONNECTION_ATTEMPT_FAILED ||
5054  (unsigned char)(data)[0] == (MessageID)ID_NO_FREE_INCOMING_CONNECTIONS ||
5055  (unsigned char)(data)[0] == (MessageID)ID_CONNECTION_BANNED ||
5056  (unsigned char)(data)[0] == (MessageID)ID_ALREADY_CONNECTED ||
5057  (unsigned char)(data)[0] == (MessageID)ID_INVALID_PASSWORD ||
5058  (unsigned char)(data)[0] == (MessageID)ID_IP_RECENTLY_CONNECTED ||
5059  (unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
5060  {
5061 
5062  SLNet::BitStream bs((unsigned char*) data,length,false);
5063  bs.IgnoreBytes(sizeof(MessageID));
5065  if ((unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
5066  bs.IgnoreBytes(sizeof(unsigned char));
5067 
5068  RakNetGUID guid;
5069  bs.Read(guid);
5070 
5072  bool connectionAttemptCancelled=false;
5074  for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
5075  {
5076  rcs=rakPeer->requestedConnectionQueue[i];
5078  {
5079  connectionAttemptCancelled=true;
5081 
5082 #if LIBCAT_SECURITY==1
5083  CAT_AUDIT_PRINTF("AUDIT: Connection attempt canceled so deleting rcs->client_handshake object %x\n", rcs->client_handshake);
5084  SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
5085 #endif // LIBCAT_SECURITY
5087  break;
5088  }
5089  }
5090 
5092 
5093  if (connectionAttemptCancelled)
5094  {
5095  // Tell user of connection attempt failed
5096  packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5097  packet->data[ 0 ] = data[0]; // Attempted a connection and couldn't
5098  packet->bitSize = ( sizeof( char ) * 8);
5099  packet->systemAddress = systemAddress;
5100  packet->guid=guid;
5101  rakPeer->AddPacketToProducer(packet);
5102  }
5103  }
5104  else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST_1 && length > (int) (1+sizeof(OFFLINE_MESSAGE_DATA_ID)))
5105  {/*
5106  static int x = 0;
5107  ++x;
5108 
5109  SystemAddress *addr = (SystemAddress*)&systemAddress;
5110  addr->binaryAddress += x;*/
5111 
5112  //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
5113  char remoteProtocol=data[1+sizeof(OFFLINE_MESSAGE_DATA_ID)];
5114  if (remoteProtocol!=RAKNET_PROTOCOL_VERSION)
5115  {
5116  SLNet::BitStream bs;
5117  bs.Write((MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION);
5118  bs.Write((unsigned char)RAKNET_PROTOCOL_VERSION);
5119  bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5121 
5122  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5123  rakPeer->pluginListNTS[i]->OnDirectSocketSend((char*)bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
5124 
5125  // SocketLayer::SendTo( rakNetSocket, (char*)bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5126 
5127  RNS2_SendParameters bsp;
5128  bsp.data = (char*) bs.GetData();
5129  bsp.length = bs.GetNumberOfBytesUsed();
5130  bsp.systemAddress = systemAddress;
5131 
5132  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5133  return true;
5134  }
5135 
5136  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5137  rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
5138 
5139  SLNet::BitStream bsOut;
5140  bsOut.Write((MessageID)ID_OPEN_CONNECTION_REPLY_1);
5141  bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5143 #if LIBCAT_SECURITY==1
5144  if (rakPeer->_using_security)
5145  {
5146  bsOut.Write((unsigned char) 1); // HasCookie Yes
5147  // Write cookie
5148  uint32_t cookie = rakPeer->_cookie_jar->Generate(&systemAddress.address,sizeof(systemAddress.address));
5149  CAT_AUDIT_PRINTF("AUDIT: Writing cookie %i to %i:%i\n", cookie, systemAddress);
5150  bsOut.Write(cookie);
5151  // Write my public key
5152  bsOut.WriteAlignedBytes((const unsigned char *) rakPeer->my_public_key,sizeof(rakPeer->my_public_key));
5153  }
5154  else
5155 #endif // LIBCAT_SECURITY
5156  bsOut.Write((unsigned char) 0); // HasCookie oN
5157 
5158  // MTU. Lower MTU if it is exceeds our own limit
5159  if (length+UDP_HEADER_SIZE > MAXIMUM_MTU_SIZE)
5161  else
5162  bsOut.WriteCasted<uint16_t>(length+UDP_HEADER_SIZE);
5163 
5164  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5165  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5166  // SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5167 
5168  RNS2_SendParameters bsp;
5169  bsp.data = (char*) bsOut.GetData();
5170  bsp.length = bsOut.GetNumberOfBytesUsed();
5171  bsp.systemAddress = systemAddress;
5172  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5173  }
5174  else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST_2)
5175  {
5176  SystemAddress bindingAddress;
5177  RakNetGUID guid;
5178  SLNet::BitStream bsOut;
5179  SLNet::BitStream bs((unsigned char*) data, length, false);
5180  bs.IgnoreBytes(sizeof(MessageID));
5182 
5183  bool requiresSecurityOfThisClient=false;
5184 #if LIBCAT_SECURITY==1
5185  char remoteHandshakeChallenge[cat::EasyHandshake::CHALLENGE_BYTES];
5186 
5187  if (rakPeer->_using_security)
5188  {
5189  systemAddress.ToString(false, str1, static_cast<size_t>(64));
5190  requiresSecurityOfThisClient=rakPeer->IsInSecurityExceptionList(str1)==false;
5191 
5192  uint32_t cookie;
5193  bs.Read(cookie);
5194  CAT_AUDIT_PRINTF("AUDIT: Got cookie %i from %i:%i\n", cookie, systemAddress);
5195  if (rakPeer->_cookie_jar->Verify(&systemAddress.address,sizeof(systemAddress.address), cookie)==false)
5196  {
5197  return true;
5198  }
5199  CAT_AUDIT_PRINTF("AUDIT: Cookie good!\n");
5200 
5201  unsigned char clientWroteChallenge;
5202  bs.Read(clientWroteChallenge);
5203 
5204  if (requiresSecurityOfThisClient==true && clientWroteChallenge==0)
5205  {
5206  // Fail, client doesn't support security, and it is required
5207  return true;
5208  }
5209 
5210  if (clientWroteChallenge)
5211  {
5212  bs.ReadAlignedBytes((unsigned char*) remoteHandshakeChallenge, cat::EasyHandshake::CHALLENGE_BYTES);
5213 #ifdef CAT_AUDIT
5214  printf("AUDIT: RECV CHALLENGE ");
5215  for (int ii = 0; ii < sizeof(remoteHandshakeChallenge); ++ii)
5216  {
5217  printf("%02x", (cat::u8)remoteHandshakeChallenge[ii]);
5218  }
5219  printf("\n");
5220 #endif
5221  }
5222  }
5223 #endif // LIBCAT_SECURITY
5224 
5225  bs.Read(bindingAddress);
5226  uint16_t mtu;
5227  bs.Read(mtu);
5228  bs.Read(guid);
5229 
5230  RakPeer::RemoteSystemStruct *rssFromSA = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
5231  bool IPAddrInUse = rssFromSA != 0 && rssFromSA->isActive;
5232  RakPeer::RemoteSystemStruct *rssFromGuid = rakPeer->GetRemoteSystemFromGUID(guid, true);
5233  bool GUIDInUse = rssFromGuid != 0 && rssFromGuid->isActive;
5234 
5235  // IPAddrInUse, GuidInUse, outcome
5236  // TRUE, , TRUE , ID_OPEN_CONNECTION_REPLY if they are the same, else ID_ALREADY_CONNECTED
5237  // FALSE, , TRUE , ID_ALREADY_CONNECTED (someone else took this guid)
5238  // TRUE, , FALSE , ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
5239  // FALSE , FALSE , Allow connection
5240 
5241  int outcome;
5242  if (IPAddrInUse & GUIDInUse)
5243  {
5244  if (rssFromSA==rssFromGuid && rssFromSA->connectMode==RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER)
5245  {
5246  // ID_OPEN_CONNECTION_REPLY if they are the same
5247  outcome=1;
5248 
5249  // Note to self: If REQUESTED_CONNECTION, this means two systems attempted to connect to each other at the same time, and one finished first.
5250  // Returns ID)_CONNECTION_REQUEST_ACCEPTED to one system, and ID_ALREADY_CONNECTED followed by ID_NEW_INCOMING_CONNECTION to another
5251  }
5252  else
5253  {
5254  // ID_ALREADY_CONNECTED (restarted raknet, connected again from same ip, plus someone else took this guid)
5255  outcome=2;
5256  }
5257  }
5258  else if (IPAddrInUse==false && GUIDInUse==true)
5259  {
5260  // ID_ALREADY_CONNECTED (someone else took this guid)
5261  outcome=3;
5262  }
5263  else if (IPAddrInUse==true && GUIDInUse==false)
5264  {
5265  // ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
5266  outcome=4;
5267  }
5268  else
5269  {
5270  // Allow connection
5271  outcome=0;
5272  }
5273 
5274  SLNet::BitStream bsAnswer;
5275  bsAnswer.Write((MessageID)ID_OPEN_CONNECTION_REPLY_2);
5276  bsAnswer.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5278  bsAnswer.Write(systemAddress);
5279  bsAnswer.Write(mtu);
5280  bsAnswer.Write(requiresSecurityOfThisClient);
5281 
5282  if (outcome==1)
5283  {
5284  // Duplicate connection request packet from packetloss
5285  // Send back the same answer
5286 #if LIBCAT_SECURITY==1
5287  if (requiresSecurityOfThisClient)
5288  {
5289  CAT_AUDIT_PRINTF("AUDIT: Resending public key and answer from packetloss. Sending ID_OPEN_CONNECTION_REPLY_2\n");
5290  bsAnswer.WriteAlignedBytes((const unsigned char *) rssFromSA->answer,sizeof(rssFromSA->answer));
5291  }
5292 #endif // LIBCAT_SECURITY
5293 
5294  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5295  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBitsUsed(), systemAddress);
5296  // SocketLayer::SendTo( rakNetSocket, (const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5297 
5298  RNS2_SendParameters bsp;
5299  bsp.data = (char*) bsAnswer.GetData();
5300  bsp.length = bsAnswer.GetNumberOfBytesUsed();
5301  bsp.systemAddress = systemAddress;
5302  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5303 
5304  return true;
5305  }
5306  else if (outcome!=0)
5307  {
5309  bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5310  bsOut.Write(rakPeer->myGuid);
5311  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5312  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5313  // SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5314  RNS2_SendParameters bsp;
5315  bsp.data = (char*) bsOut.GetData();
5316  bsp.length = bsOut.GetNumberOfBytesUsed();
5317  bsp.systemAddress = systemAddress;
5318  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5319 
5320  return true;
5321  }
5322 
5323  if (rakPeer->AllowIncomingConnections()==false)
5324  {
5326  bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5327  bsOut.Write(rakPeer->myGuid);
5328  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5329  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5330  //SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5331  RNS2_SendParameters bsp;
5332  bsp.data = (char*) bsOut.GetData();
5333  bsp.length = bsOut.GetNumberOfBytesUsed();
5334  bsp.systemAddress = systemAddress;
5335  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5336 
5337  return true;
5338  }
5339 
5340  bool thisIPConnectedRecently=false;
5341  rssFromSA = rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, mtu, guid, requiresSecurityOfThisClient);
5342 
5343  if (thisIPConnectedRecently==true)
5344  {
5346  bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5347  bsOut.Write(rakPeer->myGuid);
5348  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5349  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5350  //SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5351 
5352  RNS2_SendParameters bsp;
5353  bsp.data = (char*) bsOut.GetData();
5354  bsp.length = bsOut.GetNumberOfBytesUsed();
5355  bsp.systemAddress = systemAddress;
5356  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5357 
5358  return true;
5359  }
5360 
5361 #if LIBCAT_SECURITY==1
5362  if (requiresSecurityOfThisClient)
5363  {
5364  CAT_AUDIT_PRINTF("AUDIT: Writing public key. Sending ID_OPEN_CONNECTION_REPLY_2\n");
5365  if (rakPeer->_server_handshake->ProcessChallenge(remoteHandshakeChallenge, rssFromSA->answer, rssFromSA->reliabilityLayer.GetAuthenticatedEncryption() ))
5366  {
5367  CAT_AUDIT_PRINTF("AUDIT: Challenge good!\n");
5368  // Keep going to OK block
5369  }
5370  else
5371  {
5372  CAT_AUDIT_PRINTF("AUDIT: Challenge BAD!\n");
5373 
5374  // Unassign this remote system
5375  rakPeer->DereferenceRemoteSystem(systemAddress);
5376  return true;
5377  }
5378 
5379  bsAnswer.WriteAlignedBytes((const unsigned char *) rssFromSA->answer,sizeof(rssFromSA->answer));
5380  }
5381 #endif // LIBCAT_SECURITY
5382 
5383  for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5384  rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBitsUsed(), systemAddress);
5385  // SocketLayer::SendTo( rakNetSocket, (const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5386  RNS2_SendParameters bsp;
5387  bsp.data = (char*) bsAnswer.GetData();
5388  bsp.length = bsAnswer.GetNumberOfBytesUsed();
5389  bsp.systemAddress = systemAddress;
5390  rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5391  }
5392  return true;
5393  }
5394 
5395  return false;
5396 }
5397 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5398 void ProcessNetworkPacket( SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, SLNet::TimeUS timeRead, BitStream &updateBitStream )
5399 {
5400  ProcessNetworkPacket(systemAddress,data,length,rakPeer,rakPeer->socketList[0],timeRead, updateBitStream);
5401 }
5402 void ProcessNetworkPacket( SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSocket2* rakNetSocket, SLNet::TimeUS timeRead, BitStream &updateBitStream )
5403 {
5404 #if LIBCAT_SECURITY==1
5405 #ifdef CAT_AUDIT
5406  printf("AUDIT: RECV ");
5407  for (int ii = 0; ii < length; ++ii)
5408  {
5409  printf("%02x", (cat::u8)data[ii]);
5410  }
5411  printf("\n");
5412 #endif
5413 #endif // LIBCAT_SECURITY
5414 
5415  RakAssert(systemAddress.GetPort());
5416  bool isOfflineMessage;
5417  if (ProcessOfflineNetworkPacket(systemAddress, data, length, rakPeer, rakNetSocket, &isOfflineMessage, timeRead))
5418  {
5419  return;
5420  }
5421 
5422 // SLNet::Packet *packet;
5423  RakPeer::RemoteSystemStruct *remoteSystem;
5424 
5425  // See if this datagram came from a connected system
5426  remoteSystem = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
5427  if ( remoteSystem )
5428  {
5429  // Handle regular incoming data
5430  // HandleSocketReceiveFromConnectedPlayer is only safe to be called from the same thread as Update, which is this thread
5431  if ( isOfflineMessage==false)
5432  {
5434  data, length, systemAddress, rakPeer->pluginListNTS, remoteSystem->MTUSize,
5435  rakNetSocket, &rnr, timeRead, updateBitStream);
5436  }
5437  }
5438  else
5439  {
5440  // int a=5;
5441  // printf("--- Packet from unknown system %s\n", systemAddress.ToString());
5442  }
5443 }
5444 
5445 }
5446 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5448 {
5449  /*
5450  // Construct a random seed based on the initial guid value, and the last digits of the difference to each subsequent number
5451  // This assumes that only the last 3 bits of each guidId integer has a meaningful amount of randomness between it and the prior number
5452  unsigned int t = guid.g[0];
5453  unsigned int i;
5454  for (i=1; i < sizeof(guid.g) / sizeof(guid.g[0]); i++)
5455  {
5456  unsigned int diff = guid.g[i]-guid.g[i-1];
5457  unsigned int diff3Bits = diff & 0x0007;
5458  diff3Bits <<= 29;
5459  diff3Bits >>= (i-1)*3;
5460  t ^= diff3Bits;
5461  }
5462 
5463  return t;
5464  */
5465  return (unsigned int) ((myGuid.g >> 32) ^ myGuid.g);
5466 }
5467 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5469 {
5470  unsigned int i;
5471  for (i=0; i < socketList.Size(); i++)
5472  {
5474  }
5476 }
5477 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5478 unsigned int RakPeer::GetRakNetSocketFromUserConnectionSocketIndex(unsigned int userIndex) const
5479 {
5480  unsigned int i;
5481  for (i=0; i < socketList.Size(); i++)
5482  {
5483  if (socketList[i]->GetUserConnectionSocketIndex()==userIndex)
5484  return i;
5485  }
5486  RakAssert("GetRakNetSocketFromUserConnectionSocketIndex failed" && 0);
5487  return (unsigned int) -1;
5488 }
5489 
5490 /*
5491 // DS_APR
5492 void RakPeer::ProcessChromePacket(RakNetSocket2 *s, const char *buffer, int dataSize, const SystemAddress& recvFromAddress, SLNet::TimeUS timeRead)
5493 {
5494  RakAssert(buffer);
5495  RakAssert(dataSize > 0);
5496  RakAssert(recvFromAddress.GetPort());
5497 
5498  RNS2RecvStruct *recvFromStruct;
5499  recvFromStruct=bufferedPackets.Allocate( _FILE_AND_LINE_ );
5500  RakAssert(dataSize <= (int)sizeof(recvFromStruct->data));
5501  memcpy(recvFromStruct->data, buffer, dataSize);
5502  recvFromStruct->bytesRead=dataSize;
5503  recvFromStruct->systemAddress=recvFromAddress;
5504  recvFromStruct->timeRead=timeRead;
5505  bufferedPackets.Push(recvFromStruct);
5506 }
5507 */
5508 
5509 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5510 /*
5511 bool RakPeer::RunRecvFromOnce( RakNetSocket *s )
5512 {
5513  RakPeer::RecvFromStruct *recvFromStruct;
5514 
5515  recvFromStruct=bufferedPackets.Allocate( _FILE_AND_LINE_ );
5516  if (recvFromStruct != NULL)
5517  {
5518  recvFromStruct->s=s;
5519  SocketLayer::RecvFromBlocking(s, this, recvFromStruct->data, &recvFromStruct->bytesRead, &recvFromStruct->systemAddress, &recvFromStruct->timeRead);
5520 
5521  if (recvFromStruct->bytesRead>0)
5522  {
5523  RakAssert(recvFromStruct->systemAddress.GetPort());
5524  bufferedPackets.Push(recvFromStruct);
5525  quitAndDataEvents.SetEvent();
5526 
5527  // Got data
5528  return true;
5529  }
5530  else
5531  {
5532  bufferedPackets.Deallocate(recvFromStruct, _FILE_AND_LINE_);
5533  }
5534  }
5535  // No data
5536  return false;
5537 }
5538 */
5539 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5540 bool RakPeer::RunUpdateCycle(BitStream &updateBitStream )
5541 {
5542  RakPeer::RemoteSystemStruct * remoteSystem;
5543  unsigned int activeSystemListIndex;
5544  Packet *packet;
5545  // int currentSentBytes,currentReceivedBytes;
5546 // unsigned numberOfBytesUsed;
5547 // BitSize_t numberOfBitsUsed;
5548  //SystemAddress authoritativeClientSystemAddress;
5549  BitSize_t bitSize;
5550  unsigned int byteSize;
5551  unsigned char *data;
5552  SystemAddress systemAddress;
5553  BufferedCommandStruct *bcs;
5554  bool callerDataAllocationUsed;
5555  RakNetStatistics *rnss;
5556  SLNet::TimeUS timeNS=0;
5557  SLNet::Time timeMS=0;
5558 
5559  // This is here so RecvFromBlocking actually gets data from the same thread
5560 
5561  #if defined(WINDOWS_STORE_RT)
5562  #elif defined(_WIN32)
5563  if (socketList[0]->GetSocketType()==RNS2T_WINDOWS && ((RNS2_Windows*)socketList[0])->GetSocketLayerOverride())
5564  {
5565  int len;
5566  SystemAddress sender;
5567  char dataOut[ MAXIMUM_MTU_SIZE ];
5568  do {
5569  len = ((RNS2_Windows*)socketList[0])->GetSocketLayerOverride()->RakNetRecvFrom(dataOut,&sender,true);
5570  if (len>0)
5571  ProcessNetworkPacket( sender, dataOut, len, this, socketList[0], SLNet::GetTimeUS(), updateBitStream );
5572  } while (len>0);
5573  }
5574  #endif
5575 
5576 // unsigned int socketListIndex;
5577  RNS2RecvStruct *recvFromStruct;
5578  while ((recvFromStruct=PopBufferedPacket())!=0)
5579  {
5580  /*
5581  for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
5582  {
5583  if ((RakNetSocket*) socketList[socketListIndex]==recvFromStruct->s)
5584  break;
5585  }
5586  if (socketListIndex!=socketList.Size())
5587  */
5588  ProcessNetworkPacket(recvFromStruct->systemAddress, recvFromStruct->data, recvFromStruct->bytesRead, this, recvFromStruct->socket, recvFromStruct->timeRead, updateBitStream);
5589  DeallocRNS2RecvStruct(recvFromStruct, _FILE_AND_LINE_);
5590  }
5591 
5592  while ((bcs=bufferedCommands.PopInaccurate())!=0)
5593  {
5595  {
5596  // GetTime is a very slow call so do it once and as late as possible
5597  if (timeNS==0)
5598  {
5599  timeNS = SLNet::GetTimeUS();
5600  timeMS = (SLNet::TimeMS)(timeNS/(SLNet::TimeUS)1000);
5601  }
5602 
5603  callerDataAllocationUsed=SendImmediate((char*)bcs->data, bcs->numberOfBitsToSend, bcs->priority, bcs->reliability, bcs->orderingChannel, bcs->systemIdentifier, bcs->broadcast, true, timeNS, bcs->receipt);
5604  if ( callerDataAllocationUsed==false )
5606 
5607  // Set the new connection state AFTER we call sendImmediate in case we are setting it to a disconnection state, which does not allow further sends
5609  {
5610  remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
5611  if (remoteSystem)
5612  remoteSystem->connectMode=bcs->connectionMode;
5613  }
5614  }
5616  {
5617  CloseConnectionInternal(bcs->systemIdentifier, false, true, bcs->orderingChannel, bcs->priority);
5618  }
5620  {
5621  // Reroute
5623  if (rssFromGuid!=0)
5624  {
5625  unsigned int existingSystemIndex = GetRemoteSystemIndex(rssFromGuid->systemAddress);
5626  ReferenceRemoteSystem(bcs->systemIdentifier.systemAddress, existingSystemIndex);
5627  }
5628  }
5630  {
5631  SocketQueryOutput *sqo;
5632  if (bcs->systemIdentifier.IsUndefined())
5633  {
5635  sqo->sockets=socketList;
5636  socketQueryOutput.Push(sqo);
5637  }
5638  else
5639  {
5640  remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
5642 
5643  sqo->sockets.Clear(false, _FILE_AND_LINE_);
5644  if (remoteSystem)
5645  {
5646  sqo->sockets.Push(remoteSystem->rakNetSocket, _FILE_AND_LINE_ );
5647  }
5648  else
5649  {
5650  // Leave empty smart pointer
5651  }
5652  socketQueryOutput.Push(sqo);
5653  }
5654 
5655  }
5656 
5657 #ifdef _DEBUG
5658  bcs->data=0;
5659 #endif
5660 
5662  }
5663 
5664  if (requestedConnectionQueue.IsEmpty()==false)
5665  {
5666  if (timeNS==0)
5667  {
5668  timeNS = SLNet::GetTimeUS();
5669  timeMS = (SLNet::TimeMS)(timeNS/(SLNet::TimeUS)1000);
5670  }
5671 
5672  bool condition1, condition2;
5673  unsigned requestedConnectionQueueIndex=0;
5675  while (requestedConnectionQueueIndex < requestedConnectionQueue.Size())
5676  {
5678  rcs = requestedConnectionQueue[requestedConnectionQueueIndex];
5680  if (rcs->nextRequestTime < timeMS)
5681  {
5682  condition1=rcs->requestsMade==rcs->sendConnectionAttemptCount+1;
5683  condition2=(bool)((rcs->systemAddress==UNASSIGNED_SYSTEM_ADDRESS)==1);
5684  // If too many requests made or a hole then remove this if possible, otherwise invalidate it
5685  if (condition1 || condition2)
5686  {
5687  if (rcs->data)
5688  {
5690  rcs->data=0;
5691  }
5692 
5693  if (condition1 && !condition2 && rcs->actionToTake==RequestedConnectionStruct::CONNECT)
5694  {
5695  // Tell user of connection attempt failed
5696  packet=AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5697  packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
5698  packet->bitSize = ( sizeof( char ) * 8);
5699  packet->systemAddress = rcs->systemAddress;
5700  AddPacketToProducer(packet);
5701  }
5702 
5703 #if LIBCAT_SECURITY==1
5704  CAT_AUDIT_PRINTF("AUDIT: Connection attempt FAILED so deleting rcs->client_handshake object %x\n", rcs->client_handshake);
5705  SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
5706 #endif
5708 
5710  for (unsigned int k=0; k < requestedConnectionQueue.Size(); k++)
5711  {
5712  if (requestedConnectionQueue[k]==rcs)
5713  {
5715  break;
5716  }
5717  }
5719  }
5720  else
5721  {
5722 
5723  int MTUSizeIndex = rcs->requestsMade / (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES);
5724  if (MTUSizeIndex>=NUM_MTU_SIZES)
5725  MTUSizeIndex=NUM_MTU_SIZES-1;
5726  rcs->requestsMade++;
5728 
5729  SLNet::BitStream bitStream;
5730  //WriteOutOfBandHeader(&bitStream, ID_USER_PACKET_ENUM);
5732  bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5734  bitStream.PadWithZeroToByteLength(mtuSizes[MTUSizeIndex]-UDP_HEADER_SIZE);
5735 
5736  char str[256];
5737  rcs->systemAddress.ToString(true,str,static_cast<size_t>(256));
5738 
5739  //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
5740 
5741  unsigned i;
5742  for (i=0; i < pluginListNTS.Size(); i++)
5743  pluginListNTS[i]->OnDirectSocketSend((const char*) bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), rcs->systemAddress);
5744 
5745  RakNetSocket2 *socketToUse;
5746  if (rcs->socket == 0)
5747  socketToUse = socketList[rcs->socketIndex];
5748  else
5749  socketToUse = rcs->socket;
5750 
5751  rcs->systemAddress.FixForIPVersion(socketToUse->GetBoundAddress());
5752 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
5753  if (socketToUse->IsBerkleySocket())
5754  ((RNS2_Berkley*)socketToUse)->SetDoNotFragment(1);
5755 #endif
5756 
5757 // SocketLayer::SetDoNotFragment(socketToUse, 1);
5758  SLNet::Time sendToStart= SLNet::GetTime();
5759 
5760  RNS2_SendParameters bsp;
5761  bsp.data = (char*) bitStream.GetData();
5762  bsp.length = bitStream.GetNumberOfBytesUsed();
5763  bsp.systemAddress = rcs->systemAddress;
5764  if (socketToUse->Send(&bsp, _FILE_AND_LINE_) == 10040)
5765  // if (SocketLayer::SendTo( socketToUse, (const char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), rcs->systemAddress, _FILE_AND_LINE_ )==-10040)
5766  {
5767  // Don't use this MTU size again
5768  rcs->requestsMade = (unsigned char) ((MTUSizeIndex + 1) * (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES));
5769  rcs->nextRequestTime=timeMS;
5770  }
5771  else
5772  {
5773  SLNet::Time sendToEnd= SLNet::GetTime();
5774  if (sendToEnd-sendToStart>100)
5775  {
5776  // Drop to lowest MTU
5777  int lowestMtuIndex = rcs->sendConnectionAttemptCount/NUM_MTU_SIZES * (NUM_MTU_SIZES - 1);
5778  if (lowestMtuIndex > rcs->requestsMade)
5779  {
5780  rcs->requestsMade = (unsigned char) lowestMtuIndex;
5781  rcs->nextRequestTime=timeMS;
5782  }
5783  else
5784  rcs->requestsMade=(unsigned char)(rcs->sendConnectionAttemptCount+1);
5785  }
5786  }
5787  // SocketLayer::SetDoNotFragment(socketToUse, 0);
5788 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
5789  if (socketToUse->IsBerkleySocket())
5790  ((RNS2_Berkley*)socketToUse)->SetDoNotFragment(0);
5791 #endif
5792 
5793  requestedConnectionQueueIndex++;
5794  }
5795  }
5796  else
5797  requestedConnectionQueueIndex++;
5798 
5800  }
5802  }
5803 
5804  // remoteSystemList in network thread
5805  for ( activeSystemListIndex = 0; activeSystemListIndex < activeSystemListSize; ++activeSystemListIndex )
5806  //for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; ++remoteSystemIndex )
5807  {
5808  // I'm using systemAddress from remoteSystemList but am not locking it because this loop is called very frequently and it doesn't
5809  // matter if we miss or do an extra update. The reliability layers themselves never care which player they are associated with
5810  //systemAddress = remoteSystemList[ remoteSystemIndex ].systemAddress;
5811  // Allow the systemAddress for this remote system list to change. We don't care if it changes now.
5812  // remoteSystemList[ remoteSystemIndex ].allowSystemAddressAssigment=true;
5813 
5814 
5815  // Found an active remote system
5816  remoteSystem = activeSystemList[ activeSystemListIndex ];
5817  systemAddress = remoteSystem->systemAddress;
5818  RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
5819  // Update is only safe to call from the same thread that calls HandleSocketReceiveFromConnectedPlayer,
5820  // which is this thread
5821 
5822  if (timeNS==0)
5823  {
5824  timeNS = SLNet::GetTimeUS();
5825  timeMS = (SLNet::TimeMS)(timeNS/(SLNet::TimeUS)1000);
5826  //RAKNET_DEBUG_PRINTF("timeNS = %I64i timeMS=%i\n", timeNS, timeMS);
5827  }
5828 
5829 
5830  if (timeMS > remoteSystem->lastReliableSend && timeMS-remoteSystem->lastReliableSend > remoteSystem->reliabilityLayer.GetTimeoutTime()/2 && remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
5831  {
5832  // If no reliable packets are waiting for an ack, do a one byte reliable send so that disconnections are noticed
5833  RakNetStatistics rakNetStatistics;
5834  rnss=remoteSystem->reliabilityLayer.GetStatistics(&rakNetStatistics);
5835  if (rnss->messagesInResendBuffer==0)
5836  {
5837  PingInternal( systemAddress, true, RELIABLE );
5838 
5839  //remoteSystem->lastReliableSend=timeMS+remoteSystem->reliabilityLayer.GetTimeoutTime();
5840  remoteSystem->lastReliableSend=timeMS;
5841  }
5842  }
5843 
5844  remoteSystem->reliabilityLayer.Update( remoteSystem->rakNetSocket, systemAddress, remoteSystem->MTUSize, timeNS, maxOutgoingBPS, pluginListNTS, &rnr, updateBitStream ); // systemAddress only used for the internet simulator test
5845 
5846  // Check for failure conditions
5847  if ( remoteSystem->reliabilityLayer.IsDeadConnection() ||
5849  (remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK && (remoteSystem->reliabilityLayer.AreAcksWaiting()==false || remoteSystem->reliabilityLayer.AckTimeout(timeMS)==true)) ||
5850  ((
5854  && timeMS > remoteSystem->connectionTime && timeMS - remoteSystem->connectionTime > 10000))
5855  )
5856  {
5857  // RAKNET_DEBUG_PRINTF("timeMS=%i remoteSystem->connectionTime=%i\n", timeMS, remoteSystem->connectionTime );
5858 
5859  // Failed. Inform the user?
5860  // TODO - RakNet 4.0 - Return a different message identifier for DISCONNECT_ASAP_SILENTLY and DISCONNECT_ASAP than for DISCONNECT_ON_NO_ACK
5861  // The first two mean we called CloseConnection(), the last means the other system sent us ID_DISCONNECTION_NOTIFICATION
5864  {
5865 
5866 // SLNet::BitStream undeliveredMessages;
5867 // remoteSystem->reliabilityLayer.GetUndeliveredMessages(&undeliveredMessages,remoteSystem->MTUSize);
5868 
5869 // packet=AllocPacket(sizeof( char ) + undeliveredMessages.GetNumberOfBytesUsed());
5870  packet=AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5872  packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
5873  else if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
5874  packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
5875  else
5876  packet->data[ 0 ] = ID_DISCONNECTION_NOTIFICATION; // DeadConnection
5877 
5878 // memcpy(packet->data+1, undeliveredMessages.GetData(), undeliveredMessages.GetNumberOfBytesUsed());
5879 
5880  packet->guid = remoteSystem->guid;
5881  packet->systemAddress = systemAddress;
5882  packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
5883  packet->guid.systemIndex=packet->systemAddress.systemIndex;
5884 
5885  AddPacketToProducer(packet);
5886  }
5887  // else connection shutting down, don't bother telling the user
5888 
5889 #ifdef _DO_PRINTF
5890  RAKNET_DEBUG_PRINTF("Connection dropped for player %i:%i\n", systemAddress);
5891 #endif
5892  CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
5893  continue;
5894  }
5895 
5896  // Ping this guy if it is time to do so
5897  if ( remoteSystem->connectMode==RemoteSystemStruct::CONNECTED && timeMS > remoteSystem->nextPingTime && ( occasionalPing || remoteSystem->lowestPing == (unsigned short)-1 ) )
5898  {
5899  remoteSystem->nextPingTime = timeMS + 5000;
5900  PingInternal( systemAddress, true, UNRELIABLE );
5901 
5902  // Update again immediately after this tick so the ping goes out right away
5904  }
5905 
5906  // Find whoever has the lowest player ID
5907  //if (systemAddress < authoritativeClientSystemAddress)
5908  // authoritativeClientSystemAddress=systemAddress;
5909 
5910  // Does the reliability layer have any packets waiting for us?
5911  // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
5912  bitSize = remoteSystem->reliabilityLayer.Receive( &data );
5913 
5914  while ( bitSize > 0 )
5915  {
5916  // These types are for internal use and should never arrive from a network packet
5917  if (data[0]==ID_CONNECTION_ATTEMPT_FAILED)
5918  {
5919  RakAssert(0);
5920  bitSize=0;
5921  continue;
5922  }
5923 
5924  // Fast and easy - just use the data that was returned
5925  byteSize = (unsigned int) BITS_TO_BYTES( bitSize );
5926 
5927  // For unknown senders we only accept a few specific packets
5929  {
5930  if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
5931  {
5932  ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
5933  rakFree_Ex(data, _FILE_AND_LINE_ );
5934  }
5935  else
5936  {
5937  CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
5938 #ifdef _DO_PRINTF
5939  RAKNET_DEBUG_PRINTF("Temporarily banning %i:%i for sending nonsense data\n", systemAddress);
5940 #endif
5941 
5942  char str1[64];
5943  systemAddress.ToString(false, str1, static_cast<size_t>(64));
5944  AddToBanList(str1, remoteSystem->reliabilityLayer.GetTimeoutTime());
5945 
5946 
5947  rakFree_Ex(data, _FILE_AND_LINE_ );
5948  }
5949  }
5950  else
5951  {
5952  // However, if we are connected we still take a connection request in case both systems are trying to connect to each other
5953  // at the same time
5954  if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
5955  {
5956  // 04/27/06 This is wrong. With cross connections, we can both have initiated the connection are in state REQUESTED_CONNECTION
5957  // 04/28/06 Downgrading connections from connected will close the connection due to security at ((remoteSystem->connectMode!=RemoteSystemStruct::CONNECTED && time > remoteSystem->connectionTime && time - remoteSystem->connectionTime > 10000))
5959  {
5960  ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
5961  }
5962  else
5963  {
5964 
5965  SLNet::BitStream bs((unsigned char*) data,byteSize,false);
5966  bs.IgnoreBytes(sizeof(MessageID));
5969  SLNet::Time incomingTimestamp;
5970  bs.Read(incomingTimestamp);
5971 
5972  // Got a connection request message from someone we are already connected to. Just reply normally.
5973  // This can happen due to race conditions with the fully connected mesh
5974  OnConnectionRequest( remoteSystem, incomingTimestamp );
5975  }
5976  rakFree_Ex(data, _FILE_AND_LINE_ );
5977  }
5978  else if ( (unsigned char) data[ 0 ] == ID_NEW_INCOMING_CONNECTION && byteSize > sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(SLNet::Time)*2 )
5979  {
5981  {
5983  PingInternal( systemAddress, true, UNRELIABLE );
5984 
5985  // Update again immediately after this tick so the ping goes out right away
5987 
5988  SLNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
5989  SystemAddress bsSystemAddress;
5990 
5991  inBitStream.IgnoreBits(8);
5992  inBitStream.Read(bsSystemAddress);
5993  for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
5994  inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
5995 
5996  SLNet::Time sendPingTime, sendPongTime;
5997  inBitStream.Read(sendPingTime);
5998  inBitStream.Read(sendPongTime);
5999  OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
6000 
6001  // Overwrite the data in the packet
6002  // NewIncomingConnectionStruct newIncomingConnectionStruct;
6003  // SLNet::BitStream nICS_BS( data, NewIncomingConnectionStruct_Size, false );
6004  // newIncomingConnectionStruct.Deserialize( nICS_BS );
6005 
6006  remoteSystem->myExternalSystemAddress = bsSystemAddress;
6007 
6008  // Bug: If A connects to B through R, A's firstExternalID is set to R. If A tries to send to R, sends to loopback because R==firstExternalID
6009  // Correct fix is to specify in Connect() if target is through a proxy.
6010  // However, in practice you have to connect to something else first anyway to know about the proxy. So setting once only is good enough
6012  {
6013  firstExternalID=bsSystemAddress;
6014  firstExternalID.debugPort=ntohs(firstExternalID.address.addr4.sin_port);
6015  }
6016 
6017  // Send this info down to the game
6018  packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6019  packet->bitSize = bitSize;
6020  packet->systemAddress = systemAddress;
6021  packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
6022  packet->guid = remoteSystem->guid;
6023  packet->guid.systemIndex=packet->systemAddress.systemIndex;
6024  AddPacketToProducer(packet);
6025  }
6026  else
6027  {
6028  // Send to game even if already connected. This could happen when connecting to 127.0.0.1
6029  // Ignore, already connected
6030  // rakFree_Ex(data, _FILE_AND_LINE_ );
6031  }
6032  }
6033  else if ( (unsigned char) data[ 0 ] == ID_CONNECTED_PONG && byteSize == sizeof(unsigned char)+sizeof(SLNet::Time)*2 )
6034  {
6035  SLNet::Time sendPingTime, sendPongTime;
6036 
6037  // Copy into the ping times array the current time - the value returned
6038  // First extract the sent ping
6039  SLNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
6040  //PingStruct ps;
6041  //ps.Deserialize(psBS);
6042  inBitStream.IgnoreBits(8);
6043  inBitStream.Read(sendPingTime);
6044  inBitStream.Read(sendPongTime);
6045 
6046  OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
6047 
6048  rakFree_Ex(data, _FILE_AND_LINE_ );
6049  }
6050  else if ( (unsigned char)data[0] == ID_CONNECTED_PING && byteSize == sizeof(unsigned char)+sizeof(SLNet::Time) )
6051  {
6052  SLNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
6053  inBitStream.IgnoreBits(8);
6054  SLNet::Time sendPingTime;
6055  inBitStream.Read(sendPingTime);
6056 
6057  SLNet::BitStream outBitStream;
6058  outBitStream.Write((MessageID)ID_CONNECTED_PONG);
6059  outBitStream.Write(sendPingTime);
6060  outBitStream.Write(SLNet::GetTime());
6061  SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, UNRELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0 );
6062 
6063  // Update again immediately after this tick so the ping goes out right away
6065 
6066  rakFree_Ex(data, _FILE_AND_LINE_ );
6067  }
6068  else if ( (unsigned char) data[ 0 ] == ID_DISCONNECTION_NOTIFICATION )
6069  {
6070  // We shouldn't close the connection immediately because we need to ack the ID_DISCONNECTION_NOTIFICATION
6072  rakFree_Ex(data, _FILE_AND_LINE_ );
6073 
6074  // AddPacketToProducer(packet);
6075  }
6076  else if ( (unsigned char)(data)[0] == ID_DETECT_LOST_CONNECTIONS && byteSize == sizeof(unsigned char) )
6077  {
6078  // Do nothing
6079  rakFree_Ex(data, _FILE_AND_LINE_ );
6080  }
6081  else if ( (unsigned char)(data)[0] == ID_INVALID_PASSWORD )
6082  {
6084  {
6085  packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6086  packet->bitSize = bitSize;
6087  packet->systemAddress = systemAddress;
6088  packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
6089  packet->guid = remoteSystem->guid;
6090  packet->guid.systemIndex=packet->systemAddress.systemIndex;
6091  AddPacketToProducer(packet);
6092 
6094  }
6095  else
6096  {
6097  rakFree_Ex(data, _FILE_AND_LINE_ );
6098  }
6099  }
6100  else if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST_ACCEPTED )
6101  {
6102  if (byteSize > sizeof(MessageID)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(SystemIndex)+sizeof(SLNet::Time)*2)
6103  {
6104  // Make sure this connection accept is from someone we wanted to connect to
6105  bool allowConnection, alreadyConnected;
6106 
6110  allowConnection=true;
6111  else
6112  allowConnection=false;
6113 
6115  alreadyConnected=true;
6116  else
6117  alreadyConnected=false;
6118 
6119  if ( allowConnection )
6120  {
6121  SystemAddress externalID;
6122  SystemIndex systemIndex;
6123 // SystemAddress internalID;
6124 
6125  SLNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
6126  inBitStream.IgnoreBits(8);
6127  // inBitStream.Read(remotePort);
6128  inBitStream.Read(externalID);
6129  inBitStream.Read(systemIndex);
6130  for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
6131  inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
6132 
6133  SLNet::Time sendPingTime, sendPongTime;
6134  inBitStream.Read(sendPingTime);
6135  inBitStream.Read(sendPongTime);
6136  OnConnectedPong(sendPingTime, sendPongTime, remoteSystem);
6137 
6138  // Find a free remote system struct to use
6139  // SLNet::BitStream casBitS(data, byteSize, false);
6140  // ConnectionAcceptStruct cas;
6141  // cas.Deserialize(casBitS);
6142  // systemAddress.GetPort() = remotePort;
6143 
6144  // The remote system told us our external IP, so save it
6145  remoteSystem->myExternalSystemAddress = externalID;
6147 
6148  // Bug: If A connects to B through R, A's firstExternalID is set to R. If A tries to send to R, sends to loopback because R==firstExternalID
6149  // Correct fix is to specify in Connect() if target is through a proxy.
6150  // However, in practice you have to connect to something else first anyway to know about the proxy. So setting once only is good enough
6152  {
6153  firstExternalID=externalID;
6154  firstExternalID.debugPort=ntohs(firstExternalID.address.addr4.sin_port);
6155  }
6156 
6157  // Send the connection request complete to the game
6158  packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6159  packet->bitSize = byteSize * 8;
6160  packet->systemAddress = systemAddress;
6161  packet->systemAddress.systemIndex = ( SystemIndex ) GetIndexFromSystemAddress( systemAddress, true );
6162  packet->guid = remoteSystem->guid;
6163  packet->guid.systemIndex=packet->systemAddress.systemIndex;
6164  AddPacketToProducer(packet);
6165 
6166  SLNet::BitStream outBitStream;
6168  outBitStream.Write(systemAddress);
6169  for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
6170  outBitStream.Write(ipList[i]);
6171  outBitStream.Write(sendPongTime);
6172  outBitStream.Write(SLNet::GetTime());
6173 
6174  SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0 );
6175 
6176  if (alreadyConnected==false)
6177  {
6178  PingInternal( systemAddress, true, UNRELIABLE );
6179  }
6180  }
6181  else
6182  {
6183  // Ignore, already connected
6184  rakFree_Ex(data, _FILE_AND_LINE_ );
6185  }
6186  }
6187  else
6188  {
6189  // Version mismatch error?
6190  RakAssert(0);
6191  rakFree_Ex(data, _FILE_AND_LINE_ );
6192  }
6193  }
6194  else
6195  {
6196  // What do I do if I get a message from a system, before I am fully connected?
6197  // I can either ignore it or give it to the user
6198  // It seems like giving it to the user is a better option
6199  if ((data[0]>=(MessageID)ID_TIMESTAMP || data[0]==ID_SND_RECEIPT_ACKED || data[0]==ID_SND_RECEIPT_LOSS) &&
6200  remoteSystem->isActive
6201  )
6202  {
6203  packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6204  packet->bitSize = bitSize;
6205  packet->systemAddress = systemAddress;
6206  packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
6207  packet->guid = remoteSystem->guid;
6208  packet->guid.systemIndex=packet->systemAddress.systemIndex;
6209  AddPacketToProducer(packet);
6210  }
6211  else
6212  {
6213  rakFree_Ex(data, _FILE_AND_LINE_ );
6214  }
6215  }
6216  }
6217 
6218  // Does the reliability layer have any more packets waiting for us?
6219  // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
6220  bitSize = remoteSystem->reliabilityLayer.Receive( &data );
6221  }
6222 
6223  }
6224 
6225  return true;
6226 }
6227 
6228 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6229 
6231 {
6233  {
6234  if (incomingDatagramEventHandler(recvStruct)!=true)
6235  return;
6236  }
6237 
6238  PushBufferedPacket(recvStruct);
6240 }
6241 
6242 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6243 
6244 /*
6245 RAK_THREAD_DECLARATION(SLNet::RecvFromLoop)
6246 {
6247 #if defined(SN_TARGET_PSP2)
6248  RakPeerAndIndex *rpai = ( RakPeerAndIndex * ) RakThread::GetRealThreadArgument(callGetRealThreadArgument);
6249 #else
6250  RakPeerAndIndex *rpai = ( RakPeerAndIndex * ) arguments;
6251 #endif
6252  RakPeer * rakPeer = rpai->rakPeer;
6253  RakNetSocket *s = rpai->s;
6254  SLNet::OP_DELETE(rpai,_FILE_AND_LINE_);
6255 
6256  rakPeer->isRecvFromLoopThreadActive.Increment();
6257 
6258  while ( rakPeer->endThreads == false )
6259  {
6260  if (rakPeer->RunRecvFromOnce(s)==false &&
6261  s->GetBlockingSocket()==false)
6262  RakSleep(0);
6263  }
6264  rakPeer->isRecvFromLoopThreadActive.Decrement();
6265 
6266 #if defined(SN_TARGET_PSP2)
6267  return sceKernelExitDeleteThread(0);
6268 #else
6269  return 0;
6270 #endif
6271 }
6272 */
6273 
6274 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6275 RAK_THREAD_DECLARATION(SLNet::UpdateNetworkLoop)
6276 {
6277 
6278 
6279 
6280  RakPeer * rakPeer = ( RakPeer * ) arguments;
6281 
6282 
6283 /*
6284  // 11/15/05 - this is slower than Sleep()
6285 #ifdef _WIN32
6286 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
6287  // Lets see if these timers give better performance than Sleep
6288  HANDLE timerHandle;
6289  LARGE_INTEGER dueTime;
6290 
6291  if ( rakPeer->threadSleepTimer <= 0 )
6292  rakPeer->threadSleepTimer = 1;
6293 
6294  // 2nd parameter of false means synchronization timer instead of manual-reset timer
6295  timerHandle = CreateWaitableTimer( NULL, FALSE, 0 );
6296 
6297  RakAssert( timerHandle );
6298 
6299  dueTime.QuadPart = -10000 * rakPeer->threadSleepTimer; // 10000 is 1 ms?
6300 
6301  BOOL success = SetWaitableTimer( timerHandle, &dueTime, rakPeer->threadSleepTimer, NULL, NULL, FALSE );
6302  (void) success;
6303  RakAssert( success );
6304 
6305 #endif
6306 #endif
6307 */
6308 
6309  BitStream updateBitStream( MAXIMUM_MTU_SIZE
6310 #if LIBCAT_SECURITY==1
6311  + cat::AuthenticatedEncryption::OVERHEAD_BYTES
6312 #endif
6313  );
6314 //
6315  rakPeer->isMainLoopThreadActive = true;
6316 
6317  bool running = true;
6318  while ( running )
6319  {
6320  if (rakPeer->endThreads) {
6321  // allow just one more final update-run prior to shutting down this thread to make sure that outstanding acks are still sent and the peers don't unnecessary wait for already retrieved packets
6322  // note: this fixes part of SLNET-123
6323  running = false;
6324  }
6325 // #ifdef _DEBUG
6326 // // Sanity check, make sure RunUpdateCycle does not block or not otherwise get called for a long time
6327 // RakNetTime thisCall=SLNet::GetTime();
6328 // RakAssert(thisCall-lastCall<250);
6329 // lastCall=thisCall;
6330 // #endif
6331  if (rakPeer->userUpdateThreadPtr)
6332  rakPeer->userUpdateThreadPtr(rakPeer, rakPeer->userUpdateThreadData);
6333 
6334  rakPeer->RunUpdateCycle(updateBitStream);
6335 
6336  // Pending sends go out this often, unless quitAndDataEvents is set
6337  rakPeer->quitAndDataEvents.WaitOnEvent(10);
6338 
6339  /*
6340 
6341 // #if ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) &&
6342 #if defined(USE_WAIT_FOR_MULTIPLE_EVENTS) && defined(_WIN32)
6343 
6344  if (rakPeer->threadSleepTimer>0)
6345  {
6346  WSAEVENT eventArray[256];
6347  unsigned int i, eventArrayIndex;
6348  for (i=0,eventArrayIndex=0; i < rakPeer->socketList.Size(); i++)
6349  {
6350  if (rakPeer->socketList[i]->recvEvent!=INVALID_HANDLE_VALUE)
6351  {
6352  eventArray[eventArrayIndex]=rakPeer->socketList[i]->recvEvent;
6353  eventArrayIndex++;
6354  if (eventArrayIndex==256)
6355  break;
6356  }
6357  }
6358  WSAWaitForMultipleEvents(eventArrayIndex,(const HANDLE*) &eventArray,FALSE,rakPeer->threadSleepTimer,FALSE);
6359  }
6360  else
6361  {
6362  RakSleep(0);
6363  }
6364 
6365 #else // ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
6366  #pragma message("-- RakNet: Using Sleep(). Uncomment USE_WAIT_FOR_MULTIPLE_EVENTS in defines.h if you want to use WaitForSingleObject instead. --")
6367 
6368  RakSleep( rakPeer->threadSleepTimer );
6369 #endif
6370  */
6371  }
6372 
6373  rakPeer->isMainLoopThreadActive = false;
6374 
6375  /*
6376 #ifdef _WIN32
6377 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
6378  CloseHandle(timerHandle);
6379 #endif
6380 #endif
6381  */
6382 
6383 
6384 
6385 
6386  return 0;
6387 
6388 }
6389 
6391 {
6392  for (unsigned int i=0; i < pluginList.Size(); i++)
6393  {
6394  switch (packet->data[0])
6395  {
6397  pluginList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_DISCONNECTION_NOTIFICATION);
6398  break;
6399  case ID_CONNECTION_LOST:
6400  pluginList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_CONNECTION_LOST);
6401  break;
6403  pluginList[i]->OnNewConnection(packet->systemAddress, packet->guid, true);
6404  break;
6406  pluginList[i]->OnNewConnection(packet->systemAddress, packet->guid, false);
6407  break;
6409  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_ATTEMPT_FAILED);
6410  break;
6412  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY);
6413  break;
6415  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_OUR_SYSTEM_REQUIRES_SECURITY);
6416  break;
6418  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_PUBLIC_KEY_MISMATCH);
6419  break;
6420  case ID_ALREADY_CONNECTED:
6421  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_ALREADY_CONNECTED);
6422  break;
6424  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_NO_FREE_INCOMING_CONNECTIONS);
6425  break;
6426  case ID_CONNECTION_BANNED:
6427  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_BANNED);
6428  break;
6429  case ID_INVALID_PASSWORD:
6430  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_INVALID_PASSWORD);
6431  break;
6433  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_INCOMPATIBLE_PROTOCOL);
6434  break;
6436  pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_IP_RECENTLY_CONNECTED);
6437  break;
6438  }
6439  }
6440 }
6441 
6443 {
6445  return;
6446 
6447  // Fill out ipList structure
6448 #if !defined(WINDOWS_STORE_RT)
6450 #endif
6451 
6452  // Sort the addresses from lowest to highest
6453  int startingIdx = 0;
6454  while (startingIdx < MAXIMUM_NUMBER_OF_INTERNAL_IDS-1 && ipList[startingIdx] != UNASSIGNED_SYSTEM_ADDRESS)
6455  {
6456  int lowestIdx = startingIdx;
6457  for (int curIdx = startingIdx + 1; curIdx < MAXIMUM_NUMBER_OF_INTERNAL_IDS-1 && ipList[curIdx] != UNASSIGNED_SYSTEM_ADDRESS; curIdx++ )
6458  {
6459  if (ipList[curIdx] < ipList[startingIdx])
6460  {
6461  lowestIdx = curIdx;
6462  }
6463  }
6464  if (startingIdx != lowestIdx)
6465  {
6466  SystemAddress temp = ipList[startingIdx];
6467  ipList[startingIdx] = ipList[lowestIdx];
6468  ipList[lowestIdx] = temp;
6469  }
6470  ++startingIdx;
6471  }
6472 }
6473 
6474 
6475 // #if defined(RMO_NEW_UNDEF_ALLOCATING_QUEUE)
6476 // #pragma pop_macro("new")
6477 // #undef RMO_NEW_UNDEF_ALLOCATING_QUEUE
6478 // #endif
6479