1 // \file
2 //
3 // This file is part of RakNet Copyright 2003 Jenkins Software LLC
4 //
5 // Raknet is available under the terms of the GPLv3 license, see /usr/local/share/licenses/raknet-3.9.2_10,1/GPLv3.
6
7
8 #include "RakNetDefines.h"
9 #include "RakPeer.h"
10 #include "RakNetTypes.h"
11 #include "WSAStartupSingleton.h"
12
13 #ifdef _WIN32
14
15
16 #else
17 #define closesocket close
18 #include <unistd.h>
19 #endif
20
21 #if defined(new)
22 #pragma push_macro("new")
23 #undef new
24 #define RMO_NEW_UNDEF_ALLOCATING_QUEUE
25 #endif
26
27
28 #include <time.h>
29
30 #include <ctype.h> // toupper
31 #include <string.h>
32 #include "GetTime.h"
33 #include "MessageIdentifiers.h"
34 #include "DS_HuffmanEncodingTree.h"
35 #include "Rand.h"
36 #include "PluginInterface2.h"
37 #include "StringCompressor.h"
38 #include "StringTable.h"
39 #include "NetworkIDObject.h"
40 #include "RakNetTypes.h"
41 #include "SHA1.h"
42 #include "RakSleep.h"
43 #include "RouterInterface.h"
44 #include "RakAssert.h"
45 #include "RakNetVersion.h"
46 #include "NetworkIDManager.h"
47 #include "DataBlockEncryptor.h"
48 #include "gettimeofday.h"
49 #include "SignaledEvent.h"
50 #include "SuperFastHash.h"
51
52 RAK_THREAD_DECLARATION(UpdateNetworkLoop);
53 RAK_THREAD_DECLARATION(RecvFromLoop);
54 RAK_THREAD_DECLARATION(UDTConnect);
55
56 #define REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE 8
57
58 #if !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ )
59 #include <stdlib.h> // malloc
60 #endif
61
62
63
64 #if defined(_WIN32)
65 //
66 #else
67 /*
68 #include <alloca.h> // Console 2
69 #include <stdlib.h>
70 extern bool _extern_Console2LoadModules(void);
71 extern int _extern_Console2GetConnectionStatus(void);
72 extern int _extern_Console2GetLobbyStatus(void);
73 //extern bool Console2StartupFluff(unsigned int *);
74 extern void Console2ShutdownFluff(void);
75 //extern unsigned int Console2ActivateConnection(unsigned int, void *);
76 //extern bool Console2BlockOnEstablished(void);
77 extern void Console2GetIPAndPort(unsigned int, char *, unsigned short *, unsigned int );
78 //extern void Console2DeactivateConnection(unsigned int, unsigned int);
79 */
80 #endif
81
82
83 static const int NUM_MTU_SIZES=3;
84
85
86
87 static const int mtuSizes[NUM_MTU_SIZES]={MAXIMUM_MTU_SIZE, 1200, 576};
88
89
90
91 #include "RakAlloca.h"
92
93 // Note to self - if I change this it might affect RECIPIENT_OFFLINE_MESSAGE_INTERVAL in Natpunchthrough.cpp
94 //static const int MAX_OPEN_CONNECTION_REQUESTS=8;
95 //static const int TIME_BETWEEN_OPEN_CONNECTION_REQUESTS=500;
96
97 #ifdef _MSC_VER
98 #pragma warning( push )
99 #endif
100
101 using namespace RakNet;
102
103 static RakNetRandom rnr;
104
105 struct RakPeerAndIndex
106 {
107 SOCKET s;
108 unsigned short remotePortRakNetWasStartedOn_PS3;
109 RakPeer *rakPeer;
110 };
111
112 // On a Little-endian machine the RSA key and message are mangled, but we're
113 // trying to be friendly to the little endians, so we do byte order
114 // mangling on Big-Endian machines. Note that this mangling is independent
115 // of the byte order used on the network (which also defaults to little-end).
116 #ifdef HOST_ENDIAN_IS_BIG
BSWAPCPY(unsigned char * dest,unsigned char * source,int bytesize)117 void __inline BSWAPCPY(unsigned char *dest, unsigned char *source, int bytesize)
118 {
119 #ifdef _DEBUG
120 RakAssert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
121 #endif
122 int i;
123 for (i=0; i<bytesize; i+=4)
124 {
125 dest[i] = source[i+3];
126 dest[i+1] = source[i+2];
127 dest[i+2] = source[i+1];
128 dest[i+3] = source[i];
129 }
130 }
BSWAPSELF(unsigned char * source,int bytesize)131 void __inline BSWAPSELF(unsigned char *source, int bytesize)
132 {
133 #ifdef _DEBUG
134 RakAssert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
135 #endif
136 int i;
137 unsigned char a, b;
138 for (i=0; i<bytesize; i+=4)
139 {
140 a = source[i];
141 b = source[i+1];
142 source[i] = source[i+3];
143 source[i+1] = source[i+2];
144 source[i+2] = b;
145 source[i+3] = a;
146 }
147 }
148 #endif
149
150 static const unsigned int SYN_COOKIE_OLD_RANDOM_NUMBER_DURATION = 10000;
151 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.
152
153 // Used to distinguish between offline messages with data, and messages from the reliability layer
154 // Should be different than any message that could result from messages from the reliability layer
155 #pragma warning(disable:4309) // 'initializing' : truncation of constant value
156 // Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false
157 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};
158
159 //#define _DO_PRINTF
160
161 // UPDATE_THREAD_POLL_TIME is how often the update thread will poll to see
162 // if receive wasn't called within UPDATE_THREAD_UPDATE_TIME. If it wasn't called within that time,
163 // the updating thread will activate and take over network communication until Receive is called again.
164 //static const unsigned int UPDATE_THREAD_UPDATE_TIME=30;
165 //static const unsigned int UPDATE_THREAD_POLL_TIME=30;
166
167 //#define _TEST_AES
168
169 struct PacketFollowedByData
170 {
171 Packet p;
172 unsigned char data[1];
173 };
174
AllocPacket(unsigned dataSize,const char * file,unsigned int line)175 Packet *RakPeer::AllocPacket(unsigned dataSize, const char *file, unsigned int line)
176 {
177 // Crashes when dataSize is 4 bytes - not sure why
178 // unsigned char *data = (unsigned char *) rakMalloc_Ex(sizeof(PacketFollowedByData)+dataSize, file, line);
179 // Packet *p = &((PacketFollowedByData *)data)->p;
180 // p->data=((PacketFollowedByData *)data)->data;
181 // p->length=dataSize;
182 // p->bitSize=BYTES_TO_BITS(dataSize);
183 // p->deleteData=false;
184 // p->guid=UNASSIGNED_RAKNET_GUID;
185 // return p;
186
187 Packet *p;
188 packetAllocationPoolMutex.Lock();
189 p = packetAllocationPool.Allocate(file,line);
190 packetAllocationPoolMutex.Unlock();
191 p = new ((void*)p) Packet;
192 p->data=(unsigned char*) rakMalloc_Ex(dataSize,file,line);
193 p->length=dataSize;
194 p->bitSize=BYTES_TO_BITS(dataSize);
195 p->deleteData=true;
196 p->guid=UNASSIGNED_RAKNET_GUID;
197 p->bypassPlugins=false;
198 return p;
199 }
200
AllocPacket(unsigned dataSize,unsigned char * data,const char * file,unsigned int line)201 Packet *RakPeer::AllocPacket(unsigned dataSize, unsigned char *data, const char *file, unsigned int line)
202 {
203 // Packet *p = (Packet *)rakMalloc_Ex(sizeof(Packet), file, line);
204 Packet *p;
205 packetAllocationPoolMutex.Lock();
206 p = packetAllocationPool.Allocate(file,line);
207 packetAllocationPoolMutex.Unlock();
208 p = new ((void*)p) Packet;
209 p->data=data;
210 p->length=dataSize;
211 p->bitSize=BYTES_TO_BITS(dataSize);
212 p->deleteData=true;
213 p->guid=UNASSIGNED_RAKNET_GUID;
214 p->bypassPlugins=false;
215 return p;
216 }
217
218 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
219 // Constructor
220 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RakPeer()221 RakPeer::RakPeer()
222 {
223 StringCompressor::AddReference();
224 RakNet::StringTable::AddReference();
225 WSAStartupSingleton::AddRef();
226
227 #if !defined(_WIN32_WCE)
228 usingSecurity = false;
229 #endif
230 memset( frequencyTable, 0, sizeof( unsigned int ) * 256 );
231 rawBytesSent = rawBytesReceived = compressedBytesSent = compressedBytesReceived = 0;
232 outputTree = inputTree = 0;
233 defaultMTUSize = mtuSizes[NUM_MTU_SIZES-1];
234 trackFrequencyTable = false;
235 maximumIncomingConnections = 0;
236 maximumNumberOfPeers = 0;
237 //remoteSystemListSize=0;
238 remoteSystemList = 0;
239 remoteSystemLookup=0;
240 bytesSentPerSecond = bytesReceivedPerSecond = 0;
241 endThreads = true;
242 isMainLoopThreadActive = false;
243 isRecvFromLoopThreadActive = false;
244 // isRecvfromThreadActive=false;
245 #if defined(GET_TIME_SPIKE_LIMIT) && GET_TIME_SPIKE_LIMIT>0
246 occasionalPing = true;
247 #else
248 occasionalPing = false;
249 #endif
250 allowInternalRouting=false;
251 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
252 mySystemAddress[i]=UNASSIGNED_SYSTEM_ADDRESS;
253 allowConnectionResponseIPMigration = false;
254 blockOnRPCReply=false;
255 //incomingPasswordLength=outgoingPasswordLength=0;
256 incomingPasswordLength=0;
257 router=0;
258 splitMessageProgressInterval=0;
259 //unreliableTimeout=0;
260 unreliableTimeout=1000;
261 networkIDManager=0;
262 maxOutgoingBPS=0;
263 firstExternalID=UNASSIGNED_SYSTEM_ADDRESS;
264 myGuid=UNASSIGNED_RAKNET_GUID;
265 networkIDManager=0;
266 userUpdateThreadPtr=0;
267 userUpdateThreadData=0;
268
269 #ifdef _DEBUG
270 // Wait longer to disconnect in debug so I don't get disconnected while tracing
271 defaultTimeoutTime=30000;
272 #else
273 defaultTimeoutTime=10000;
274 #endif
275
276 #ifdef _DEBUG
277 _packetloss=0.0;
278 _minExtraPing=0;
279 _extraPingVariance=0;
280 #endif
281
282 #ifdef _RAKNET_THREADSAFE
283 bufferedCommands.SetPageSize(sizeof(BufferedCommandStruct)*32);
284 socketQueryOutput.SetPageSize(sizeof(SocketQueryOutput)*8);
285 bufferedPackets.SetPageSize(sizeof(RecvFromStruct)*32);
286 #endif
287
288 packetAllocationPoolMutex.Lock();
289 packetAllocationPool.SetPageSize(sizeof(DataStructures::MemoryPool<Packet>::MemoryWithPage)*32);
290 packetAllocationPoolMutex.Unlock();
291
292 remoteSystemIndexPool.SetPageSize(sizeof(DataStructures::MemoryPool<RemoteSystemIndex>::MemoryWithPage)*32);
293
294 GenerateGUID();
295
296 quitAndDataEvents.InitEvent();
297 limitConnectionFrequencyFromTheSameIP=false;
298 ResetSendReceipt();
299 }
300
301 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
302 // Destructor
303 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
~RakPeer()304 RakPeer::~RakPeer()
305 {
306 // unsigned i;
307
308
309 Shutdown( 0, 0 );
310
311 // Free the ban list.
312 ClearBanList();
313
314 StringCompressor::RemoveReference();
315 RakNet::StringTable::RemoveReference();
316 WSAStartupSingleton::Deref();
317
318 quitAndDataEvents.CloseEvent();
319 }
320
321 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
322 // \brief Starts the network threads, opens the listen port.
323 // You must call this before calling Connect().
324 // Multiple calls while already active are ignored. To call this function again with different settings, you must first call Shutdown().
325 // \note Call SetMaximumIncomingConnections if you want to accept incoming connections
326 // \note Set _RAKNET_THREADSAFE in RakNetDefines.h if you want to call RakNet functions from multiple threads (not recommended, as it is much slower and RakNet is already asynchronous).
327 // \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
328 // \param[in] localPort The port to listen for connections on.
329 // \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.
330 // \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();
331 // \param[in] socketDescriptorCount The size of the \a socketDescriptors array. Pass 1 if you are not sure what to pass.
332 // \return False on failure (can't create socket or thread), true on success.
333 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Startup(unsigned short maxConnections,int _threadSleepTimer,SocketDescriptor * socketDescriptors,unsigned socketDescriptorCount,int threadPriority)334 bool RakPeer::Startup( unsigned short maxConnections, int _threadSleepTimer, SocketDescriptor *socketDescriptors, unsigned socketDescriptorCount, int threadPriority )
335 {
336 if (IsActive())
337 return false;
338
339 if (threadPriority==-99999)
340 {
341
342
343 #if defined(_WIN32)
344 threadPriority=0;
345
346
347 #else
348 threadPriority=1000;
349 #endif
350 }
351
352 // Fill out ipList structure
353
354 memset( ipList, 0, sizeof( char ) * 16 * MAXIMUM_NUMBER_OF_INTERNAL_IDS );
355 SocketLayer::GetMyIP( ipList,binaryAddresses );
356
357
358 unsigned int i;
359 if (myGuid==UNASSIGNED_RAKNET_GUID)
360 {
361 seedMT( GenerateSeedFromGuid() );
362 }
363
364 rnr.SeedMT( GenerateSeedFromGuid() );
365
366 RakPeerAndIndex rpai[32];
367 RakAssert(socketDescriptorCount<32);
368
369 RakAssert(socketDescriptors && socketDescriptorCount>=1);
370
371 if (socketDescriptors==0 || socketDescriptorCount<1)
372 return false;
373
374 //unsigned short localPort;
375 //localPort=socketDescriptors[0].port;
376
377 RakAssert( maxConnections > 0 );
378
379 if ( maxConnections <= 0 )
380 return false;
381
382 DerefAllSockets();
383
384
385 // Go through all socket descriptors and precreate sockets on the specified addresses
386 for (i=0; i<socketDescriptorCount; i++)
387 {
388 if (socketDescriptors[i].port!=0 && SocketLayer::IsPortInUse(socketDescriptors[i].port, socketDescriptors[i].hostAddress)==true)
389 {
390 DerefAllSockets();
391 return false;
392 }
393
394 RakNetSmartPtr<RakNetSocket> rns(RakNet::OP_NEW<RakNetSocket>(__FILE__,__LINE__));
395 if (socketDescriptors[i].remotePortRakNetWasStartedOn_PS3==0)
396 rns->s = (unsigned int) SocketLayer::CreateBoundSocket( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress, 100 );
397 else // if (socketDescriptors[i].socketType==SocketDescriptor::PS3_LOBBY_UDP)
398 rns->s = (unsigned int) SocketLayer::CreateBoundSocket_PS3Lobby( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress );
399
400 if ((SOCKET)rns->s==(SOCKET)-1)
401 {
402 DerefAllSockets();
403 return false;
404 }
405
406
407 rns->boundAddress=SocketLayer::GetSystemAddress( rns->s );
408 rns->remotePortRakNetWasStartedOn_PS3=socketDescriptors[i].remotePortRakNetWasStartedOn_PS3;
409 rns->userConnectionSocketIndex=i;
410
411 // Test the socket
412 int zero=0;
413 if (SocketLayer::SendTo((SOCKET)rns->s, (const char*) &zero,4,"127.0.0.1", rns->boundAddress.port, rns->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ )!=0)
414 {
415 DerefAllSockets();
416 return false;
417 }
418
419 socketList.Push(rns, __FILE__, __LINE__ );
420
421 /*
422 #if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
423 if (_threadSleepTimer>0)
424 {
425 rns->recvEvent=CreateEvent(0,FALSE,FALSE,0);
426 WSAEventSelect(rns->s,rns->recvEvent,FD_READ);
427 }
428 #endif
429 */
430 }
431
432 // 05/05/09 - Updated to dynamically bind sockets on IP addresses, so we always reply on the same address we recieved from
433 /*
434
435 for (i=0; i<connectionSocketsLength; i++)
436 {
437 if (connectionSockets[i].haveRakNetCloseSocket && connectionSockets[i].s != (SOCKET) -1)
438 closesocket(connectionSockets[i].s);
439 }
440 if (connectionSockets)
441 {
442 RakNet::OP_DELETE_ARRAY(connectionSockets, __FILE__, __LINE__);
443 }
444 connectionSocketsLength=0;
445
446 connectionSockets=RakNet::OP_NEW_ARRAY<RakNetSocket>(socketDescriptorCount, __FILE__, __LINE__ );
447 for (i=0; i<socketDescriptorCount; i++)
448 {
449 if (socketDescriptors[i].socketType==SocketDescriptor::NONE)
450 connectionSockets[i].s = (SOCKET) -1;
451 else if (socketDescriptors[i].remotePortRakNetWasStartedOn_PS3==0)
452 connectionSockets[i].s = SocketLayer::CreateBoundSocket( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress );
453 else if (socketDescriptors[i].socketType==SocketDescriptor::PS3_LOBBY_UDP)
454 connectionSockets[i].s = SocketLayer::CreateBoundSocket_PS3Lobby( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress );
455 connectionSockets[i].haveRakNetCloseSocket=true;
456 connectionSockets[i].socketType=socketDescriptors[i].socketType;
457
458 if (connectionSockets[i].s==(SOCKET)-1 && socketDescriptors[i].socketType!=SocketDescriptor::NONE)
459 {
460 unsigned int j;
461 for (j=0; j < i; j++)
462 {
463 if (connectionSockets[j].haveRakNetCloseSocket)
464 closesocket(connectionSockets[j].s);
465 }
466 if (connectionSockets)
467 {
468 RakNet::OP_DELETE_ARRAY(connectionSockets, __FILE__, __LINE__);
469 }
470 connectionSocketsLength=0;
471 connectionSockets=0;
472 return false;
473 }
474 }
475
476 connectionSocketsLength=socketDescriptorCount;
477
478 #if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
479 if (_threadSleepTimer>0)
480 {
481 recvEvent=CreateEvent(0,FALSE,FALSE,0);
482 for (i=0; i<socketDescriptorCount; i++)
483 {
484 if (socketDescriptors[i].socketType!=SocketDescriptor::NONE)
485 WSAEventSelect(connectionSockets[i].s,recvEvent,FD_READ);
486 }
487 }
488 #endif
489 */
490
491 if ( maximumNumberOfPeers == 0 )
492 {
493 // Don't allow more incoming connections than we have peers.
494 if ( maximumIncomingConnections > maxConnections )
495 maximumIncomingConnections = maxConnections;
496
497 maximumNumberOfPeers = maxConnections;
498 // 04/19/2006 - Don't overallocate because I'm no longer allowing connected pings.
499 // The disconnects are not consistently processed and the process was sloppy and complicated.
500 // Allocate 10% extra to handle new connections from players trying to connect when the server is full
501 //remoteSystemListSize = maxConnections;// * 11 / 10 + 1;
502
503 // remoteSystemList in Single thread
504 //remoteSystemList = RakNet::OP_NEW<RemoteSystemStruct[ remoteSystemListSize ]>( __FILE__, __LINE__ );
505 remoteSystemList = RakNet::OP_NEW_ARRAY<RemoteSystemStruct>(maximumNumberOfPeers, __FILE__, __LINE__ );
506
507 remoteSystemLookup = RakNet::OP_NEW_ARRAY<RemoteSystemIndex*>((unsigned int) maximumNumberOfPeers * REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE, __FILE__, __LINE__ );
508
509 for ( i = 0; i < maximumNumberOfPeers; i++ )
510 //for ( i = 0; i < remoteSystemListSize; i++ )
511 {
512 // remoteSystemList in Single thread
513 remoteSystemList[ i ].isActive = false;
514 remoteSystemList[ i ].systemAddress = UNASSIGNED_SYSTEM_ADDRESS;
515 remoteSystemList[ i ].guid = UNASSIGNED_RAKNET_GUID;
516 remoteSystemList[ i ].myExternalSystemAddress = UNASSIGNED_SYSTEM_ADDRESS;
517 remoteSystemList[ i ].connectMode=RemoteSystemStruct::NO_ACTION;
518 remoteSystemList[ i ].MTUSize = defaultMTUSize;
519 #ifdef _DEBUG
520 remoteSystemList[ i ].reliabilityLayer.ApplyNetworkSimulator(_packetloss, _minExtraPing, _extraPingVariance);
521 #endif
522 }
523
524 for (unsigned int i=0; i < (unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE; i++)
525 {
526 remoteSystemLookup[i]=0;
527 }
528 }
529
530 // For histogram statistics
531 // nextReadBytesTime=0;
532 // lastSentBytes=lastReceivedBytes=0;
533
534 if ( endThreads )
535 {
536 // lastUserUpdateCycle = 0;
537
538 // Reset the frequency table that we use to save outgoing data
539 memset( frequencyTable, 0, sizeof( unsigned int ) * 256 );
540
541 // Reset the statistical data
542 rawBytesSent = rawBytesReceived = compressedBytesSent = compressedBytesReceived = 0;
543
544 updateCycleIsRunning = false;
545 endThreads = false;
546 // Create the threads
547 threadSleepTimer = _threadSleepTimer;
548
549 ClearBufferedCommands();
550 ClearBufferedPackets();
551 ClearSocketQueryOutput();
552
553
554 for (int ipIndex=0; ipIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipIndex++)
555 {
556
557 if (ipList[ipIndex][0])
558 {
559 mySystemAddress[ipIndex].port = SocketLayer::GetLocalPort(socketList[0]->s);
560 // if (socketDescriptors[0].hostAddress==0 || socketDescriptors[0].hostAddress[0]==0)
561 mySystemAddress[ipIndex].binaryAddress = inet_addr( ipList[ ipIndex ] );
562 // else
563 // mySystemAddress[ipIndex].binaryAddress = inet_addr( socketDescriptors[0].hostAddress );
564 }
565 else
566 mySystemAddress[ipIndex]=UNASSIGNED_SYSTEM_ADDRESS;
567
568
569
570 }
571
572 if ( isMainLoopThreadActive == false )
573 {
574
575 int errorCode = RakNet::RakThread::Create(UpdateNetworkLoop, this, threadPriority);
576
577 if ( errorCode != 0 )
578 {
579 Shutdown( 0, 0 );
580 return false;
581 }
582
583 for (i=0; i<socketDescriptorCount; i++)
584 {
585 rpai[i].remotePortRakNetWasStartedOn_PS3=socketDescriptors[i].remotePortRakNetWasStartedOn_PS3;
586 rpai[i].s=socketList[i]->s;
587 rpai[i].rakPeer=this;
588 isRecvFromLoopThreadActive=false;
589 errorCode = RakNet::RakThread::Create(RecvFromLoop, &rpai[i], threadPriority);
590
591 if ( errorCode != 0 )
592 {
593 Shutdown( 0, 0 );
594 return false;
595 }
596
597 while ( isRecvFromLoopThreadActive == false )
598 RakSleep(10);
599 }
600
601 }
602
603 // Wait for the threads to activate. When they are active they will set these variables to true
604
605 while ( isMainLoopThreadActive == false )
606 RakSleep(10);
607
608 }
609
610 for (i=0; i < messageHandlerList.Size(); i++)
611 {
612 messageHandlerList[i]->OnRakPeerStartup();
613 }
614
615 #ifdef USE_THREADED_SEND
616 SendToThread::AddRef();
617 #endif
618
619 return true;
620 }
621
622 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
623 // Description:
624 // Must be called while offline
625 // Secures connections though a combination of SHA1, AES128, SYN Cookies, and RSA to prevent
626 // connection spoofing, replay attacks, data eavesdropping, packet tampering, and MitM attacks.
627 // There is a significant amount of processing and a slight amount of bandwidth
628 // overhead for this feature.
629 //
630 // If you accept connections, you must call this or else secure connections will not be enabled
631 // for incoming connections.
632 // If you are connecting to another system, you can call this with values for the
633 // (e and p,q) public keys before connecting to prevent MitM
634 //
635 // Parameters:
636 // pubKeyE, pubKeyN - A pointer to the public keys from the RSACrypt class. See the Encryption sample
637 // privKeyP, privKeyQ - Private keys generated from the RSACrypt class. See the Encryption sample
638 // If the private keys are 0, then a new key will be generated when this function is called
639 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
InitializeSecurity(const char * pubKeyE,const char * pubKeyN,const char * privKeyP,const char * privKeyQ)640 void RakPeer::InitializeSecurity(const char *pubKeyE, const char *pubKeyN, const char *privKeyP, const char *privKeyQ )
641 {
642 #if !defined(_WIN32_WCE)
643 if ( endThreads == false )
644 return ;
645
646 // Setting the client key is e,n,
647 // Setting the server key is p,q
648 if ( //( privKeyP && privKeyQ && ( pubKeyE || pubKeyN ) ) ||
649 //( pubKeyE && pubKeyN && ( privKeyP || privKeyQ ) ) ||
650 ( privKeyP && privKeyQ == 0 ) ||
651 ( privKeyQ && privKeyP == 0 ) ||
652 ( pubKeyE && pubKeyN == 0 ) ||
653 ( pubKeyN && pubKeyE == 0 ) )
654 {
655 // Invalid parameters
656 RakAssert( 0 );
657 }
658
659 GenerateSYNCookieRandomNumber();
660
661 usingSecurity = true;
662
663 if ( privKeyP == 0 && privKeyQ == 0 && pubKeyE == 0 && pubKeyN == 0 )
664 {
665 keysLocallyGenerated = true;
666 //rsacrypt.generateKeys();
667 rsacrypt.generatePrivateKey(RAKNET_RSA_FACTOR_LIMBS);
668 }
669
670 else
671 {
672 if ( pubKeyE && pubKeyN )
673 {
674 // Save public keys
675 memcpy( ( char* ) & publicKeyE, pubKeyE, sizeof( publicKeyE ) );
676 memcpy( publicKeyN, pubKeyN, sizeof( publicKeyN ) );
677 }
678
679 if ( privKeyP && privKeyQ )
680 {
681 bool b = rsacrypt.setPrivateKey( (const uint32_t*) privKeyP, (const uint32_t*) privKeyQ, RAKNET_RSA_FACTOR_LIMBS/2);
682 (void) b;
683 RakAssert(b);
684 // BIGHALFSIZE( RSA_BIT_SIZE, p );
685 // BIGHALFSIZE( RSA_BIT_SIZE, q );
686
687 // memcpy( p, privKeyP, sizeof( p ) );
688 // memcpy( q, privKeyQ, sizeof( q ) );
689 // Save private keys
690 // rsacrypt.setPrivateKey( p, q );
691 }
692
693 keysLocallyGenerated = false;
694 }
695 #endif
696 }
697
698 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
699 // Description
700 // Must be called while offline
701 // Disables all security.
702 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DisableSecurity(void)703 void RakPeer::DisableSecurity( void )
704 {
705 #if !defined(_WIN32_WCE)
706 if ( endThreads == false )
707 return ;
708
709 usingSecurity = false;
710 #endif
711 }
712
713 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AddToSecurityExceptionList(const char * ip)714 void RakPeer::AddToSecurityExceptionList(const char *ip)
715 {
716 securityExceptionMutex.Lock();
717 securityExceptionList.Insert(RakString(ip), __FILE__, __LINE__);
718 securityExceptionMutex.Unlock();
719 }
720
721 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RemoveFromSecurityExceptionList(const char * ip)722 void RakPeer::RemoveFromSecurityExceptionList(const char *ip)
723 {
724 if (securityExceptionList.Size()==0)
725 return;
726
727 if (ip==0)
728 {
729 securityExceptionMutex.Lock();
730 securityExceptionList.Clear(false, __FILE__, __LINE__);
731 securityExceptionMutex.Unlock();
732 }
733 else
734 {
735 unsigned i=0;
736 securityExceptionMutex.Lock();
737 while (i < securityExceptionList.Size())
738 {
739 if (securityExceptionList[i].IPAddressMatch(ip))
740 {
741 securityExceptionList[i]=securityExceptionList[securityExceptionList.Size()-1];
742 securityExceptionList.RemoveAtIndex(securityExceptionList.Size()-1);
743 }
744 else
745 i++;
746 }
747 securityExceptionMutex.Unlock();
748 }
749 }
750 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsInSecurityExceptionList(const char * ip)751 bool RakPeer::IsInSecurityExceptionList(const char *ip)
752 {
753 if (securityExceptionList.Size()==0)
754 return false;
755
756 unsigned i=0;
757 securityExceptionMutex.Lock();
758 for (; i < securityExceptionList.Size(); i++)
759 {
760 if (securityExceptionList[i].IPAddressMatch(ip))
761 {
762 securityExceptionMutex.Unlock();
763 return true;
764 }
765 }
766 securityExceptionMutex.Unlock();
767 return false;
768 }
769
770 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
771 // Description:
772 // Sets how many incoming connections are allowed. If this is less than the number of players currently connected, no
773 // more players will be allowed to connect. If this is greater than the maximum number of peers allowed, it will be reduced
774 // to the maximum number of peers allowed. Defaults to 0.
775 //
776 // Parameters:
777 // numberAllowed - Maximum number of incoming connections allowed.
778 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetMaximumIncomingConnections(unsigned short numberAllowed)779 void RakPeer::SetMaximumIncomingConnections( unsigned short numberAllowed )
780 {
781 maximumIncomingConnections = numberAllowed;
782 }
783
784 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
785 // Description:
786 // Returns the maximum number of incoming connections, which is always <= maxConnections
787 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetMaximumIncomingConnections(void) const788 unsigned short RakPeer::GetMaximumIncomingConnections( void ) const
789 {
790 return maximumIncomingConnections;
791 }
792
793 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
794 // Returns how many open connections there are at this time
795 // \return the number of open connections
796 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NumberOfConnections(void) const797 unsigned short RakPeer::NumberOfConnections(void) const
798 {
799 unsigned short i, count=0;
800 for (i=0; i < maximumNumberOfPeers; i++)
801 if (remoteSystemList[i].isActive)
802 count++;
803 return count;
804 }
805
806 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
807 // Description:
808 // Sets the password incoming connections must match in the call to Connect (defaults to none)
809 // Pass 0 to passwordData to specify no password
810 //
811 // Parameters:
812 // passwordData: A data block that incoming connections must match. This can be just a password, or can be a stream of data.
813 // - Specify 0 for no password data
814 // passwordDataLength: The length in bytes of passwordData
815 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetIncomingPassword(const char * passwordData,int passwordDataLength)816 void RakPeer::SetIncomingPassword( const char* passwordData, int passwordDataLength )
817 {
818 //if (passwordDataLength > MAX_OFFLINE_DATA_LENGTH)
819 // passwordDataLength=MAX_OFFLINE_DATA_LENGTH;
820
821 if (passwordDataLength > 255)
822 passwordDataLength=255;
823
824 if (passwordData==0)
825 passwordDataLength=0;
826
827 // Not threadsafe but it's not important enough to lock. Who is going to change the password a lot during runtime?
828 // It won't overflow at least because incomingPasswordLength is an unsigned char
829 if (passwordDataLength>0)
830 memcpy(incomingPassword, passwordData, passwordDataLength);
831 incomingPasswordLength=(unsigned char)passwordDataLength;
832 }
833
834 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetIncomingPassword(char * passwordData,int * passwordDataLength)835 void RakPeer::GetIncomingPassword( char* passwordData, int *passwordDataLength )
836 {
837 if (passwordData==0)
838 {
839 *passwordDataLength=incomingPasswordLength;
840 return;
841 }
842
843 if (*passwordDataLength > incomingPasswordLength)
844 *passwordDataLength=incomingPasswordLength;
845
846 if (*passwordDataLength>0)
847 memcpy(passwordData, incomingPassword, *passwordDataLength);
848 }
849
850 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
851 // Description:
852 // Call this to connect to the specified host (ip or domain name) and server port.
853 // Calling Connect and not calling SetMaximumIncomingConnections acts as a dedicated client. Calling both acts as a true peer.
854 // This is a non-blocking connection. You know the connection is successful when IsConnected() returns true
855 // or receive gets a packet with the type identifier ID_CONNECTION_ACCEPTED. If the connection is not
856 // successful, such as rejected connection or no response then neither of these things will happen.
857 // Requires that you first call Initialize
858 //
859 // Parameters:
860 // host: Either a dotted IP address or a domain name
861 // remotePort: Which port to connect to on the remote machine.
862 // 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
863 // passwordDataLength: The length in bytes of passwordData
864 //
865 // Returns:
866 // True on successful initiation. False on incorrect parameters, internal error, or too many existing peers
867 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Connect(const char * host,unsigned short remotePort,const char * passwordData,int passwordDataLength,unsigned connectionSocketIndex,unsigned sendConnectionAttemptCount,unsigned timeBetweenSendConnectionAttemptsMS,RakNetTime timeoutTime)868 bool RakPeer::Connect( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, unsigned connectionSocketIndex, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime )
869 {
870 // If endThreads is true here you didn't call Startup() first.
871 if ( host == 0 || endThreads || connectionSocketIndex>=socketList.Size() )
872 return false;
873
874 connectionSocketIndex=GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
875
876 if (passwordDataLength>255)
877 passwordDataLength=255;
878
879 if (passwordData==0)
880 passwordDataLength=0;
881
882 // Not threadsafe but it's not important enough to lock. Who is going to change the password a lot during runtime?
883 // It won't overflow at least because outgoingPasswordLength is an unsigned char
884 // if (passwordDataLength>0)
885 // memcpy(outgoingPassword, passwordData, passwordDataLength);
886 // outgoingPasswordLength=(unsigned char) passwordDataLength;
887
888 if ( NonNumericHostString( host ) )
889 {
890 host = ( char* ) SocketLayer::DomainNameToIP( host );
891
892 if (host==0)
893 return false;
894 }
895
896 // 04/02/09 - Can't remember why I disabled connecting to self, but it seems to work
897 // Connecting to ourselves in the same instance of the program?
898 // if ( ( strcmp( host, "127.0.0.1" ) == 0 || strcmp( host, "0.0.0.0" ) == 0 ) && remotePort == mySystemAddress[0].port )
899 // return false;
900
901 return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, connectionSocketIndex, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime);
902 }
903
904 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
905
ConnectWithSocket(const char * host,unsigned short remotePort,const char * passwordData,int passwordDataLength,RakNetSmartPtr<RakNetSocket> socket,unsigned sendConnectionAttemptCount,unsigned timeBetweenSendConnectionAttemptsMS,RakNetTime timeoutTime)906 bool RakPeer::ConnectWithSocket(const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, RakNetSmartPtr<RakNetSocket> socket, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime)
907 {
908 if ( host == 0 || endThreads || socket.IsNull() )
909 return false;
910
911 if (passwordDataLength>255)
912 passwordDataLength=255;
913
914 if (passwordData==0)
915 passwordDataLength=0;
916
917 if ( NonNumericHostString( host ) )
918 {
919 host = ( char* ) SocketLayer::DomainNameToIP( host );
920
921 if (host==0)
922 return false;
923 }
924
925 return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, 0, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime, socket );
926
927 }
928
929 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
930 // Description:
931 // Stops the network threads and close all connections. Multiple calls are ok.
932 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Shutdown(unsigned int blockDuration,unsigned char orderingChannel,PacketPriority disconnectionNotificationPriority)933 void RakPeer::Shutdown( unsigned int blockDuration, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
934 {
935 unsigned i,j;
936 bool anyActive;
937 RakNetTime startWaitingTime;
938 // SystemAddress systemAddress;
939 RakNetTime time;
940 //unsigned short systemListSize = remoteSystemListSize; // This is done for threading reasons
941 unsigned short systemListSize = maximumNumberOfPeers;
942
943 if ( blockDuration > 0 )
944 {
945 for ( i = 0; i < systemListSize; i++ )
946 {
947 // remoteSystemList in user thread
948 if (remoteSystemList[i].isActive)
949 NotifyAndFlagForShutdown(remoteSystemList[i].systemAddress, false, orderingChannel, disconnectionNotificationPriority);
950 }
951
952 time = RakNet::GetTime();
953 startWaitingTime = time;
954 while ( time - startWaitingTime < blockDuration )
955 {
956 anyActive=false;
957 for (j=0; j < systemListSize; j++)
958 {
959 // remoteSystemList in user thread
960 if (remoteSystemList[j].isActive)
961 {
962 anyActive=true;
963 break;
964 }
965 }
966
967 // If this system is out of packets to send, then stop waiting
968 if ( anyActive==false )
969 break;
970
971 // This will probably cause the update thread to run which will probably
972 // send the disconnection notification
973
974 RakSleep(15);
975 time = RakNet::GetTime();
976 }
977 }
978
979 for (i=0; i < messageHandlerList.Size(); i++)
980 {
981 messageHandlerList[i]->OnRakPeerShutdown();
982 }
983
984 quitAndDataEvents.SetEvent();
985
986 endThreads = true;
987 // Get recvfrom to unblock
988 for (i=0; i < socketList.Size(); i++)
989 {
990 if (SocketLayer::SendTo(socketList[i]->s, (const char*) &i,1,"127.0.0.1", socketList[i]->boundAddress.port, socketList[i]->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ )!=0)
991 break;
992 }
993 while ( isMainLoopThreadActive )
994 {
995 endThreads = true;
996 RakSleep(15);
997 }
998
999 // char c=0;
1000 // unsigned int socketIndex;
1001 // remoteSystemList in Single thread
1002 for ( i = 0; i < systemListSize; i++ )
1003 {
1004 // Reserve this reliability layer for ourselves
1005 remoteSystemList[ i ].isActive = false;
1006
1007 // Remove any remaining packets
1008 remoteSystemList[ i ].reliabilityLayer.Reset(false, remoteSystemList[ i ].MTUSize);
1009
1010 remoteSystemList[ i ].rakNetSocket.SetNull();
1011 }
1012
1013
1014 // Setting maximumNumberOfPeers to 0 allows remoteSystemList to be reallocated in Initialize.
1015 // Setting remoteSystemListSize prevents threads from accessing the reliability layer
1016 maximumNumberOfPeers = 0;
1017 //remoteSystemListSize = 0;
1018
1019 // Free any packets the user didn't deallocate
1020 packetReturnMutex.Lock();
1021 for (unsigned int i=0; i < packetReturnQueue.Size(); i++)
1022 DeallocatePacket(packetReturnQueue[i]);
1023 packetReturnQueue.Clear(__FILE__,__LINE__);
1024 packetReturnMutex.Unlock();
1025 packetAllocationPoolMutex.Lock();
1026 packetAllocationPool.Clear(__FILE__,__LINE__);
1027 packetAllocationPoolMutex.Unlock();
1028
1029 blockOnRPCReply=false;
1030
1031 RakNetTimeMS timeout = RakNet::GetTimeMS()+1000;
1032 while ( isRecvFromLoopThreadActive && RakNet::GetTimeMS()<timeout )
1033 {
1034 // Get recvfrom to unblock
1035 for (i=0; i < socketList.Size(); i++)
1036 {
1037 SocketLayer::SendTo(socketList[i]->s, (const char*) &i,1,"127.0.0.1", socketList[i]->boundAddress.port, socketList[i]->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
1038 }
1039
1040 RakSleep(30);
1041 }
1042
1043 if (isRecvFromLoopThreadActive)
1044 {
1045 timeout = RakNet::GetTimeMS()+1000;
1046 while ( isRecvFromLoopThreadActive && RakNet::GetTimeMS()<timeout )
1047 {
1048 RakSleep(30);
1049 }
1050 }
1051
1052 DerefAllSockets();
1053
1054 ClearBufferedCommands();
1055 ClearBufferedPackets();
1056 ClearSocketQueryOutput();
1057 bytesSentPerSecond = bytesReceivedPerSecond = 0;
1058
1059 ClearRequestedConnectionList();
1060
1061
1062 // Clear out the reliability layer list in case we want to reallocate it in a successive call to Init.
1063 RemoteSystemStruct * temp = remoteSystemList;
1064 remoteSystemList = 0;
1065 RakNet::OP_DELETE_ARRAY(temp, __FILE__, __LINE__);
1066
1067 ClearRemoteSystemLookup();
1068
1069 #ifdef USE_THREADED_SEND
1070 SendToThread::Deref();
1071 #endif
1072
1073 ResetSendReceipt();
1074 }
1075
1076 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1077 // Description:
1078 // Returns true if the network threads are running
1079 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsActive(void) const1080 inline bool RakPeer::IsActive( void ) const
1081 {
1082 return endThreads == false;
1083 }
1084
1085 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1086 // Description:
1087 // Fills the array remoteSystems with the systemAddress of all the systems we are connected to
1088 //
1089 // Parameters:
1090 // remoteSystems (out): An array of SystemAddress structures to be filled with the SystemAddresss of the systems we are connected to
1091 // - pass 0 to remoteSystems to only get the number of systems we are connected to
1092 // numberOfSystems (int, out): As input, the size of remoteSystems array. As output, the number of elements put into the array
1093 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetConnectionList(SystemAddress * remoteSystems,unsigned short * numberOfSystems) const1094 bool RakPeer::GetConnectionList( SystemAddress *remoteSystems, unsigned short *numberOfSystems ) const
1095 {
1096 int count, index;
1097 count=0;
1098
1099 if ( remoteSystemList == 0 || endThreads == true )
1100 {
1101 *numberOfSystems = 0;
1102 return false;
1103 }
1104
1105 // This is called a lot so I unrolled the loop
1106 if ( remoteSystems )
1107 {
1108 // remoteSystemList in user thread
1109 //for ( count = 0, index = 0; index < remoteSystemListSize; ++index )
1110 for ( count = 0, index = 0; index < maximumNumberOfPeers; ++index )
1111 if ( remoteSystemList[ index ].isActive && remoteSystemList[ index ].connectMode==RemoteSystemStruct::CONNECTED)
1112 {
1113 if ( count < *numberOfSystems )
1114 remoteSystems[ count ] = remoteSystemList[ index ].systemAddress;
1115
1116 ++count;
1117 }
1118 }
1119 else
1120 {
1121 // remoteSystemList in user thread
1122 //for ( count = 0, index = 0; index < remoteSystemListSize; ++index )
1123 for ( count = 0, index = 0; index < maximumNumberOfPeers; ++index )
1124 if ( remoteSystemList[ index ].isActive && remoteSystemList[ index ].connectMode==RemoteSystemStruct::CONNECTED)
1125 ++count;
1126 }
1127
1128 *numberOfSystems = ( unsigned short ) count;
1129
1130 return true;
1131 }
1132
1133 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetNextSendReceipt(void)1134 uint32_t RakPeer::GetNextSendReceipt(void)
1135 {
1136 sendReceiptSerialMutex.Lock();
1137 uint32_t retVal = sendReceiptSerial;
1138 sendReceiptSerialMutex.Unlock();
1139 return retVal;
1140 }
1141 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IncrementNextSendReceipt(void)1142 uint32_t RakPeer::IncrementNextSendReceipt(void)
1143 {
1144 sendReceiptSerialMutex.Lock();
1145 uint32_t returned = sendReceiptSerial;
1146 if (++sendReceiptSerial==0)
1147 sendReceiptSerial=1;
1148 sendReceiptSerialMutex.Unlock();
1149 return returned;
1150 }
1151
1152 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1153 // Description:
1154 // Sends a block of data to the specified system that you are connected to.
1155 // This function only works while the client is connected (Use the Connect function).
1156 // The first byte should be a message identifier starting at ID_USER_PACKET_ENUM
1157 //
1158 // Parameters:
1159 // data: The block of data to send
1160 // length: The size in bytes of the data to send
1161 // bitStream: The bitstream to send
1162 // priority: What priority level to send on.
1163 // reliability: How reliability to send this data
1164 // orderingChannel: When using ordered or sequenced packets, what channel to order these on.
1165 // - Packets are only ordered relative to other packets on the same stream
1166 // 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
1167 // broadcast: True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to.
1168 // Returns:
1169 // \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
1170 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Send(const char * data,const int length,PacketPriority priority,PacketReliability reliability,char orderingChannel,const AddressOrGUID systemIdentifier,bool broadcast,uint32_t forceReceipt)1171 uint32_t RakPeer::Send( const char *data, const int length, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceipt )
1172 {
1173 #ifdef _DEBUG
1174 RakAssert( data && length > 0 );
1175 #endif
1176 RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
1177 RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
1178 RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
1179
1180 if ( data == 0 || length < 0 )
1181 return 0;
1182
1183 if ( remoteSystemList == 0 || endThreads == true )
1184 return 0;
1185
1186 if ( broadcast == false && systemIdentifier.IsUndefined())
1187 return 0;
1188
1189 uint32_t usedSendReceipt;
1190 if (forceReceipt!=0)
1191 usedSendReceipt=forceReceipt;
1192 else
1193 usedSendReceipt=IncrementNextSendReceipt();
1194
1195 if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
1196 {
1197 SendLoopback(data,length);
1198
1199 if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
1200 {
1201 char buff[5];
1202 buff[0]=ID_SND_RECEIPT_ACKED;
1203 sendReceiptSerialMutex.Lock();
1204 memcpy(buff+1, &sendReceiptSerial, 4);
1205 sendReceiptSerialMutex.Unlock();
1206 SendLoopback( buff, 5 );
1207 }
1208
1209 return usedSendReceipt;
1210 }
1211
1212 if (broadcast==false && router && IsConnected(systemIdentifier.systemAddress)==false)
1213 {
1214 router->Send(data, BYTES_TO_BITS(length), priority, reliability, orderingChannel, systemIdentifier.systemAddress);
1215 }
1216 else
1217 {
1218 SendBuffered(data, length*8, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1219 }
1220
1221 return usedSendReceipt;
1222 }
1223
SendLoopback(const char * data,const int length)1224 void RakPeer::SendLoopback( const char *data, const int length )
1225 {
1226 if ( data == 0 || length < 0 )
1227 return;
1228
1229 Packet *packet = AllocPacket(length, __FILE__, __LINE__);
1230 memcpy(packet->data, data, length);
1231 packet->systemAddress = GetLoopbackAddress();
1232 packet->guid=myGuid;
1233 PushBackPacket(packet, false);
1234 }
1235
Send(const RakNet::BitStream * bitStream,PacketPriority priority,PacketReliability reliability,char orderingChannel,const AddressOrGUID systemIdentifier,bool broadcast,uint32_t forceReceipt)1236 uint32_t RakPeer::Send( const RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceipt )
1237 {
1238 #ifdef _DEBUG
1239 RakAssert( bitStream->GetNumberOfBytesUsed() > 0 );
1240 #endif
1241
1242 RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
1243 RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
1244 RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
1245
1246 if ( bitStream->GetNumberOfBytesUsed() == 0 )
1247 return 0;
1248
1249 if ( remoteSystemList == 0 || endThreads == true )
1250 return 0;
1251
1252 if ( broadcast == false && systemIdentifier.IsUndefined() )
1253 return 0;
1254
1255 uint32_t usedSendReceipt;
1256 if (forceReceipt!=0)
1257 usedSendReceipt=forceReceipt;
1258 else
1259 usedSendReceipt=IncrementNextSendReceipt();
1260
1261 if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
1262 {
1263 SendLoopback((const char*) bitStream->GetData(),bitStream->GetNumberOfBytesUsed());
1264 if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
1265 {
1266 char buff[5];
1267 buff[0]=ID_SND_RECEIPT_ACKED;
1268 sendReceiptSerialMutex.Lock();
1269 memcpy(buff+1, &sendReceiptSerial,4);
1270 sendReceiptSerialMutex.Unlock();
1271 SendLoopback( buff, 5 );
1272 }
1273 return usedSendReceipt;
1274 }
1275
1276 if (broadcast==false && router && IsConnected(systemIdentifier.systemAddress)==false)
1277 {
1278 router->Send((const char*)bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier.systemAddress);
1279 }
1280 else
1281 {
1282 // Sends need to be buffered and processed in the update thread because the systemAddress associated with the reliability layer can change,
1283 // from that thread, resulting in a send to the wrong player! While I could mutex the systemAddress, that is much slower than doing this
1284 SendBuffered((const char*)bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1285 }
1286
1287 return usedSendReceipt;
1288 }
1289 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1290 // Sends multiple blocks of data, concatenating them automatically.
1291 //
1292 // This is equivalent to:
1293 // RakNet::BitStream bs;
1294 // bs.WriteAlignedBytes(block1, blockLength1);
1295 // bs.WriteAlignedBytes(block2, blockLength2);
1296 // bs.WriteAlignedBytes(block3, blockLength3);
1297 // Send(&bs, ...)
1298 //
1299 // This function only works while the connected
1300 // \param[in] data An array of pointers to blocks of data
1301 // \param[in] lengths An array of integers indicating the length of each block of data
1302 // \param[in] numParameters Length of the arrays data and lengths
1303 // \param[in] priority What priority level to send on. See PacketPriority.h
1304 // \param[in] reliability How reliability to send this data. See PacketPriority.h
1305 // \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
1306 // \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
1307 // \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to.
1308 // \return False if we are not connected to the specified recipient. True otherwise
1309 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendList(const char ** data,const int * lengths,const int numParameters,PacketPriority priority,PacketReliability reliability,char orderingChannel,const AddressOrGUID systemIdentifier,bool broadcast,uint32_t forceReceipt)1310 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 forceReceipt )
1311 {
1312 #ifdef _DEBUG
1313 RakAssert( data );
1314 #endif
1315
1316 if ( data == 0 || lengths == 0 )
1317 return 0;
1318
1319 if ( remoteSystemList == 0 || endThreads == true )
1320 return 0;
1321
1322 if (numParameters==0)
1323 return 0;
1324
1325 if (lengths==0)
1326 return 0;
1327
1328 if ( broadcast == false && systemIdentifier.IsUndefined() )
1329 return 0;
1330
1331 uint32_t usedSendReceipt;
1332 if (forceReceipt!=0)
1333 usedSendReceipt=forceReceipt;
1334 else
1335 usedSendReceipt=IncrementNextSendReceipt();
1336
1337 SendBufferedList(data, lengths, numParameters, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1338
1339 return usedSendReceipt;
1340 }
1341
1342 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1343 // Description:
1344 // Gets a packet from the incoming packet queue. Use DeallocatePacket to deallocate the packet after you are done with it. Packets must be deallocated in the same order they are received.
1345 // Check the Packet struct at the top of CoreNetworkStructures.h for the format of the struct
1346 //
1347 // Returns:
1348 // 0 if no packets are waiting to be handled, otherwise an allocated packet
1349 // If the client is not active this will also return 0, as all waiting packets are flushed when the client is Disconnected
1350 // This also updates all memory blocks associated with synchronized memory and distributed objects
1351 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Receive(void)1352 Packet* RakPeer::Receive( void )
1353 {
1354 Packet *packet = ReceiveIgnoreRPC();
1355 while (packet && (packet->data[ 0 ] == ID_RPC || (packet->length>sizeof(unsigned char)+sizeof(RakNetTime) && packet->data[0]==ID_TIMESTAMP && packet->data[sizeof(unsigned char)+sizeof(RakNetTime)]==ID_RPC)))
1356 {
1357 // Do RPC calls from the user thread, not the network update thread
1358 // If we are currently blocking on an RPC reply, send ID_RPC to the blocker to handle rather than handling RPCs automatically
1359 HandleRPCPacket( ( char* ) packet->data, packet->length, packet->systemAddress );
1360 DeallocatePacket( packet );
1361
1362 packet = ReceiveIgnoreRPC();
1363 }
1364
1365 return packet;
1366 }
1367
1368 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1369 // Internal - Gets a packet without checking for RPCs
1370 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1371 #ifdef _MSC_VER
1372 #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
1373 #endif
ReceiveIgnoreRPC(void)1374 Packet* RakPeer::ReceiveIgnoreRPC( void )
1375 {
1376 if ( !( IsActive() ) )
1377 return 0;
1378
1379 Packet *packet;
1380 // Packet **threadPacket;
1381 PluginReceiveResult pluginResult;
1382
1383 int offset;
1384 unsigned int i;
1385
1386 for (i=0; i < messageHandlerList.Size(); i++)
1387 {
1388 messageHandlerList[i]->Update();
1389 }
1390
1391 do
1392 {
1393 packetReturnMutex.Lock();
1394 if (packetReturnQueue.IsEmpty())
1395 packet=0;
1396 else
1397 packet = packetReturnQueue.Pop();
1398 packetReturnMutex.Unlock();
1399 if (packet==0)
1400 return 0;
1401
1402 unsigned char msgId;
1403 if ( ( packet->length >= sizeof(unsigned char) + sizeof( RakNetTime ) ) &&
1404 ( (unsigned char) packet->data[ 0 ] == ID_TIMESTAMP ) )
1405 {
1406 offset = sizeof(unsigned char);
1407 ShiftIncomingTimestamp( packet->data + offset, packet->systemAddress );
1408 msgId=packet->data[sizeof(unsigned char) + sizeof( RakNetTime )];
1409 }
1410 else
1411 msgId=packet->data[0];
1412
1413 if ( (unsigned char) packet->data[ 0 ] == ID_RPC_REPLY )
1414 {
1415 HandleRPCReplyPacket( ( char* ) packet->data, packet->length, packet->systemAddress );
1416 DeallocatePacket( packet );
1417 packet=0; // Will do the loop again and get another packet
1418 }
1419 else
1420 {
1421 for (i=0; i < messageHandlerList.Size(); i++)
1422 {
1423 switch (msgId)
1424 {
1425 case ID_DISCONNECTION_NOTIFICATION:
1426 messageHandlerList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_DISCONNECTION_NOTIFICATION);
1427 break;
1428 case ID_CONNECTION_LOST:
1429 messageHandlerList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_CONNECTION_LOST);
1430 break;
1431 case ID_NEW_INCOMING_CONNECTION:
1432 messageHandlerList[i]->OnNewConnection(packet->systemAddress, packet->guid, true);
1433 break;
1434 case ID_CONNECTION_REQUEST_ACCEPTED:
1435 messageHandlerList[i]->OnNewConnection(packet->systemAddress, packet->guid, false);
1436 break;
1437 case ID_CONNECTION_ATTEMPT_FAILED:
1438 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_ATTEMPT_FAILED);
1439 break;
1440 case ID_ALREADY_CONNECTED:
1441 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_ALREADY_CONNECTED);
1442 break;
1443 case ID_NO_FREE_INCOMING_CONNECTIONS:
1444 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_NO_FREE_INCOMING_CONNECTIONS);
1445 break;
1446 case ID_RSA_PUBLIC_KEY_MISMATCH:
1447 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_RSA_PUBLIC_KEY_MISMATCH);
1448 break;
1449 case ID_CONNECTION_BANNED:
1450 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_BANNED);
1451 break;
1452 case ID_INVALID_PASSWORD:
1453 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_INVALID_PASSWORD);
1454 break;
1455 case ID_INCOMPATIBLE_PROTOCOL_VERSION:
1456 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_INCOMPATIBLE_PROTOCOL);
1457 break;
1458 case ID_IP_RECENTLY_CONNECTED:
1459 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_IP_RECENTLY_CONNECTED);
1460 break;
1461 }
1462
1463
1464 pluginResult=messageHandlerList[i]->OnReceive(packet);
1465 if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
1466 {
1467 DeallocatePacket( packet );
1468 packet=0; // Will do the loop again and get another packet
1469 break; // break out of the enclosing for
1470 }
1471 else if (pluginResult==RR_STOP_PROCESSING)
1472 {
1473 packet=0;
1474 break;
1475 }
1476 }
1477 }
1478
1479 } while(packet==0);
1480
1481 #ifdef _DEBUG
1482 RakAssert( packet->data );
1483 #endif
1484
1485 return packet;
1486 }
1487
1488 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1489 // Description:
1490 // Call this to deallocate a packet returned by Receive
1491 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DeallocatePacket(Packet * packet)1492 void RakPeer::DeallocatePacket( Packet *packet )
1493 {
1494 if ( packet == 0 )
1495 return;
1496
1497 if (packet->deleteData)
1498 {
1499 rakFree_Ex(packet->data, __FILE__, __LINE__ );
1500 packet->~Packet();
1501 packetAllocationPoolMutex.Lock();
1502 packetAllocationPool.Release(packet,__FILE__,__LINE__);
1503 packetAllocationPoolMutex.Unlock();
1504 }
1505 else
1506 {
1507 rakFree_Ex(packet, __FILE__, __LINE__ );
1508 }
1509 }
1510
1511 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1512 // Description:
1513 // Return the total number of connections we are allowed
1514 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetMaximumNumberOfPeers(void) const1515 unsigned short RakPeer::GetMaximumNumberOfPeers( void ) const
1516 {
1517 return maximumNumberOfPeers;
1518 }
1519
1520 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1521 // Description:
1522 // Register a C function as available for calling as a remote procedure call
1523 //
1524 // Parameters:
1525 // uniqueID: A string of only letters to identify this procedure. Recommended you use the macro CLASS_MEMBER_ID for class member functions
1526 // functionName(...): The name of the C function or C++ singleton to be used as a function pointer
1527 // This can be called whether the client is active or not, and registered functions stay registered unless unregistered with
1528 // UnregisterAsRemoteProcedureCall
1529 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RegisterAsRemoteProcedureCall(const char * uniqueID,void (* functionPointer)(RPCParameters * rpcParms))1530 void RakPeer::RegisterAsRemoteProcedureCall( const char* uniqueID, void ( *functionPointer ) ( RPCParameters *rpcParms ) )
1531 {
1532 if ( uniqueID == 0 || uniqueID[ 0 ] == 0 || functionPointer == 0 )
1533 return;
1534
1535 rpcMap.AddIdentifierWithFunction(uniqueID, (void*)functionPointer, false);
1536
1537 /*
1538 char uppercaseUniqueID[ 256 ];
1539
1540 int counter = 0;
1541
1542 while ( uniqueID[ counter ] )
1543 {
1544 uppercaseUniqueID[ counter ] = ( char ) toupper( uniqueID[ counter ] );
1545 counter++;
1546 }
1547
1548 uppercaseUniqueID[ counter ] = 0;
1549
1550 // Each id must be unique
1551 //#ifdef _DEBUG
1552 // RakAssert( rpcTree.IsIn( RPCNode( uppercaseUniqueID, functionName ) ) == false );
1553 //#endif
1554
1555 if (rpcTree.IsIn( RPCNode( uppercaseUniqueID, functionName ) ))
1556 return;
1557
1558 rpcTree.Add( RPCNode( uppercaseUniqueID, functionName ) );
1559 */
1560 }
1561
RegisterClassMemberRPC(const char * uniqueID,void * functionPointer)1562 void RakPeer::RegisterClassMemberRPC( const char* uniqueID, void *functionPointer )
1563 {
1564 if ( uniqueID == 0 || uniqueID[ 0 ] == 0 || functionPointer == 0 )
1565 return;
1566
1567 rpcMap.AddIdentifierWithFunction(uniqueID, functionPointer, true);
1568 }
1569
1570 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1571 // Description:
1572 // Unregisters a C function as available for calling as a remote procedure call that was formerly registered
1573 // with RegisterAsRemoteProcedureCall
1574 //
1575 // Parameters:
1576 // uniqueID: A null terminated string to identify this procedure. Must match the parameter
1577 // passed to RegisterAsRemoteProcedureCall
1578 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UnregisterAsRemoteProcedureCall(const char * uniqueID)1579 void RakPeer::UnregisterAsRemoteProcedureCall( const char* uniqueID )
1580 {
1581 if ( uniqueID == 0 || uniqueID[ 0 ] == 0 )
1582 return;
1583
1584 // Don't call this while running because if you remove RPCs and add them they will not match the indices on the other systems anymore
1585 #ifdef _DEBUG
1586 RakAssert(IsActive()==false);
1587 //RakAssert( strlen( uniqueID ) < 256 );
1588 #endif
1589
1590 rpcMap.RemoveNode(uniqueID);
1591
1592 /*
1593 char uppercaseUniqueID[ 256 ];
1594
1595 strcpy( uppercaseUniqueID, uniqueID );
1596
1597 int counter = 0;
1598
1599 while ( uniqueID[ counter ] )
1600 {
1601 uppercaseUniqueID[ counter ] = ( char ) toupper( uniqueID[ counter ] );
1602 counter++;
1603 }
1604
1605 uppercaseUniqueID[ counter ] = 0;
1606
1607 // Unique ID must exist
1608 #ifdef _DEBUG
1609 RakAssert( rpcTree.IsIn( RPCNode( uppercaseUniqueID, 0 ) ) == true );
1610 #endif
1611
1612 rpcTree.Del( RPCNode( uppercaseUniqueID, 0 ) );
1613 */
1614 }
1615
1616 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetNetworkIDManager(NetworkIDManager * manager)1617 void RakPeer::SetNetworkIDManager( NetworkIDManager *manager )
1618 {
1619 networkIDManager=manager;
1620 if (manager)
1621 manager->SetGuid(myGuid);
1622 }
1623 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetNetworkIDManager(void) const1624 NetworkIDManager *RakPeer::GetNetworkIDManager(void) const
1625 {
1626 return networkIDManager;
1627 }
1628 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RPC(const char * uniqueID,const char * data,BitSize_t bitLength,PacketPriority priority,PacketReliability reliability,char orderingChannel,const AddressOrGUID systemIdentifier,bool broadcast,RakNetTime * includedTimestamp,NetworkID networkID,RakNet::BitStream * replyFromTarget)1629 bool RakPeer::RPC( const char* uniqueID, const char *data, BitSize_t bitLength, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RakNetTime *includedTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget )
1630 {
1631 #ifdef _DEBUG
1632 RakAssert( uniqueID && uniqueID[ 0 ] );
1633 RakAssert(orderingChannel >=0 && orderingChannel < 32);
1634 #endif
1635
1636 if ( uniqueID == 0 )
1637 return false;
1638
1639 if ( strlen( uniqueID ) > 256 )
1640 {
1641 #ifdef _DEBUG
1642 RakAssert( 0 );
1643 #endif
1644 return false; // Unique ID is too long
1645 }
1646 if (replyFromTarget && blockOnRPCReply==true)
1647 {
1648 // TODO - this should be fixed eventually
1649 // Prevent a bug where function A calls B (blocking) which calls C back on the sender, which calls D, and C is blocking.
1650 // blockOnRPCReply is a shared variable so making it unset would unset both blocks, rather than the lowest on the callstack
1651 // Fix by tracking which function the reply is for.
1652 return false;
1653 }
1654
1655 unsigned *sendList;
1656 // bool callerAllocationDataUsed;
1657 unsigned sendListSize;
1658
1659 // All this code modifies bcs->data and bcs->numberOfBitsToSend in order to transform an RPC request into an actual packet for SendImmediate
1660 RPCIndex rpcIndex; // Index into the list of RPC calls so we know what number to encode in the packet
1661 // char *userData; // RPC ID (the name of it) and a pointer to the data sent by the user
1662 // int extraBuffer; // How many data bytes were allocated to hold the RPC header
1663 unsigned remoteSystemIndex, sendListIndex; // Iterates into the list of remote systems
1664 // int dataBlockAllocationLength; // Total number of bytes to allocate for the packet
1665 // char *writeTarget; // Used to hold either a block of allocated data or the externally allocated data
1666
1667 sendListSize=0;
1668 bool routeSend;
1669 routeSend=false;
1670
1671 if (broadcast==false)
1672 {
1673
1674 sendList=(unsigned *)alloca(sizeof(unsigned));
1675
1676
1677
1678 remoteSystemIndex=GetIndexFromSystemAddress( systemIdentifier.systemAddress, false );
1679 if (remoteSystemIndex!=(unsigned)-1 &&
1680 remoteSystemList[remoteSystemIndex].isActive &&
1681 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP &&
1682 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY &&
1683 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
1684 {
1685 sendList[0]=remoteSystemIndex;
1686 sendListSize=1;
1687 }
1688 else if (router)
1689 routeSend=true;
1690 }
1691 else
1692 {
1693
1694 sendList=(unsigned *)alloca(sizeof(unsigned)*maximumNumberOfPeers);
1695
1696
1697
1698
1699 for ( remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; remoteSystemIndex++ )
1700 {
1701 if ( remoteSystemList[ remoteSystemIndex ].isActive && remoteSystemList[ remoteSystemIndex ].systemAddress != systemIdentifier.systemAddress )
1702 sendList[sendListSize++]=remoteSystemIndex;
1703 }
1704 }
1705
1706 if (sendListSize==0 && routeSend==false)
1707 {
1708
1709
1710
1711
1712 return false;
1713 }
1714 if (routeSend)
1715 sendListSize=1;
1716
1717 RakNet::BitStream outgoingBitStream;
1718 // remoteSystemList in network thread
1719 for (sendListIndex=0; sendListIndex < (unsigned)sendListSize; sendListIndex++)
1720 {
1721 outgoingBitStream.ResetWritePointer(); // Let us write at the start of the data block, rather than at the end
1722
1723 if (includedTimestamp)
1724 {
1725 outgoingBitStream.Write((MessageID)ID_TIMESTAMP);
1726 outgoingBitStream.Write(*includedTimestamp);
1727 }
1728 outgoingBitStream.Write((MessageID)ID_RPC);
1729 if (routeSend)
1730 rpcIndex=UNDEFINED_RPC_INDEX;
1731 else
1732 rpcIndex=remoteSystemList[sendList[sendListIndex]].rpcMap.GetIndexFromFunctionName(uniqueID); // Lots of trouble but we can only use remoteSystem->[whatever] in this thread so that is why this command was buffered
1733 if (rpcIndex!=UNDEFINED_RPC_INDEX)
1734 {
1735 // We have an RPC name to an index mapping, so write the index
1736 outgoingBitStream.Write(false);
1737 outgoingBitStream.WriteCompressed(rpcIndex);
1738 }
1739 else
1740 {
1741 // No mapping, so write the encoded RPC name
1742 outgoingBitStream.Write(true);
1743 stringCompressor->EncodeString(uniqueID, 256, &outgoingBitStream);
1744 }
1745 outgoingBitStream.Write((bool) ((replyFromTarget!=0)==true));
1746 outgoingBitStream.WriteCompressed( bitLength );
1747 if (networkID==UNASSIGNED_NETWORK_ID)
1748 {
1749 // No object ID
1750 outgoingBitStream.Write(false);
1751 }
1752 else
1753 {
1754 // Encode an object ID. This will use pointer to class member RPC
1755 outgoingBitStream.Write(true);
1756 outgoingBitStream.Write(networkID);
1757 }
1758
1759
1760 if ( bitLength > 0 )
1761 outgoingBitStream.WriteBits( (const unsigned char *) data, bitLength, false ); // Last param is false to write the raw data originally from another bitstream, rather than shifting from user data
1762 else
1763 outgoingBitStream.WriteCompressed( ( unsigned int ) 0 );
1764
1765 if (routeSend)
1766 router->Send((const char*)outgoingBitStream.GetData(), outgoingBitStream.GetNumberOfBitsUsed(), priority,reliability,orderingChannel,systemIdentifier.systemAddress);
1767 else
1768 Send(&outgoingBitStream, priority, reliability, orderingChannel, remoteSystemList[sendList[sendListIndex]].systemAddress, false);
1769 }
1770
1771
1772
1773
1774
1775 if (replyFromTarget)
1776 {
1777 blockOnRPCReply=true;
1778 // 04/20/06 Just do this transparently.
1779 // We have to be able to read blocking packets out of order. Otherwise, if two systems were to send blocking RPC calls to each other at the same time,
1780 // and they also had ordered packets waiting before the block, it would be impossible to unblock.
1781 // RakAssert(reliability==RELIABLE || reliability==UNRELIABLE);
1782 replyFromTargetBS=replyFromTarget;
1783 replyFromTargetPlayer=systemIdentifier.systemAddress;
1784 replyFromTargetBroadcast=broadcast;
1785 }
1786
1787 // Do not enter this loop on blockOnRPCReply because it is a global which could be set to true by an RPC higher on the callstack, where one RPC was called while waiting for another RPC
1788 if (replyFromTarget)
1789 // if (blockOnRPCReply)
1790 {
1791 // Packet *p;
1792 RakNetTime stopWaitingTime=RakNet::GetTime()+30000;
1793 // RPCIndex arrivedRPCIndex;
1794 // char uniqueIdentifier[256];
1795 if (reliability==UNRELIABLE)
1796 if (systemIdentifier.systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
1797 stopWaitingTime=RakNet::GetTime()+1500; // Lets guess the ave. ping is 500. Not important to be very accurate
1798 else
1799 stopWaitingTime=RakNet::GetTime()+GetAveragePing(systemIdentifier.systemAddress)*3;
1800
1801 // For reliable messages, block until we get a reply or the connection is lost
1802 // For unreliable messages, block until we get a reply, the connection is lost, or 3X the ping passes
1803 while (blockOnRPCReply &&
1804 ((
1805 reliability==RELIABLE ||
1806 reliability==RELIABLE_ORDERED ||
1807 reliability==RELIABLE_SEQUENCED ||
1808 reliability==RELIABLE_WITH_ACK_RECEIPT ||
1809 reliability==RELIABLE_ORDERED_WITH_ACK_RECEIPT
1810 // ||
1811 // reliability==RELIABLE_SEQUENCED_WITH_ACK_RECEIPT
1812 ) ||
1813 RakNet::GetTime() < stopWaitingTime))
1814 {
1815
1816 RakSleep(30);
1817
1818 if (routeSend==false && ValidSendTarget(systemIdentifier.systemAddress, broadcast)==false)
1819 return false;
1820
1821 unsigned i;
1822 i=0;
1823
1824
1825 packetReturnMutex.Lock();
1826 while (i < packetReturnQueue.Size())
1827 {
1828 if ((unsigned char) packetReturnQueue[i]->data[ 0 ] == ID_RPC_REPLY )
1829 {
1830 HandleRPCReplyPacket( ( char* ) packetReturnQueue[i]->data, packetReturnQueue[i]->length, packetReturnQueue[i]->systemAddress );
1831 DeallocatePacket( packetReturnQueue[i] );
1832 packetReturnQueue.RemoveAtIndex(i);
1833 }
1834 else
1835 i++;
1836 }
1837 packetReturnMutex.Unlock();
1838
1839 /*
1840 // Scan for RPC reply packets to break out of this loop
1841 while (i < packetPool.Size())
1842 {
1843 if ((unsigned char) packetPool[i]->data[ 0 ] == ID_RPC_REPLY )
1844 {
1845 HandleRPCReplyPacket( ( char* ) packetPool[i]->data, packetPool[i]->length, packetPool[i]->systemAddress );
1846 DeallocatePacket( packetPool[i] );
1847 packetPool.RemoveAtIndex(i);
1848 }
1849 else
1850 i++;
1851 }
1852 #ifdef _RAKNET_THREADSAFE
1853 rakPeerMutexes[packetPool_Mutex].Unlock();
1854 #endif
1855 */
1856
1857 PushBackPacket(ReceiveIgnoreRPC(), false);
1858
1859
1860 // I might not support processing other RPCs while blocking on one due to complexities I can't control
1861 // Problem is FuncA calls FuncB which calls back to the sender FuncC. Sometimes it is desirable to call FuncC before returning a return value
1862 // from FuncB - sometimes not. There is also a problem with recursion where FuncA calls FuncB which calls FuncA - sometimes valid if
1863 // a different control path is taken in FuncA. (This can take many different forms)
1864 /*
1865 // Same as Receive, but doesn't automatically do RPCs
1866 p = ReceiveIgnoreRPC();
1867 if (p)
1868 {
1869 // Process all RPC calls except for those calling the function we are currently blocking in (to prevent recursion).
1870 if ( p->data[ 0 ] == ID_RPC )
1871 {
1872 RakNet::BitStream temp((unsigned char *) p->data, p->length, false);
1873 RPCNode *rpcNode;
1874 temp.IgnoreBits(8);
1875 bool nameIsEncoded;
1876 temp.Read(nameIsEncoded);
1877 if (nameIsEncoded)
1878 {
1879 stringCompressor->DecodeString((char*)uniqueIdentifier, 256, &temp);
1880 }
1881 else
1882 {
1883 temp.ReadCompressed( arrivedRPCIndex );
1884 rpcNode=rpcMap.GetNodeFromIndex( arrivedRPCIndex );
1885 if (rpcNode==0)
1886 {
1887 // Invalid RPC format
1888 #ifdef _DEBUG
1889 RakAssert(0);
1890 #endif
1891 DeallocatePacket(p);
1892 continue;
1893 }
1894 else
1895 strcpy(uniqueIdentifier, rpcNode->uniqueIdentifier);
1896 }
1897
1898 if (strcmp(uniqueIdentifier, uniqueID)!=0)
1899 {
1900 HandleRPCPacket( ( char* ) p->data, p->length, p->systemAddress );
1901 DeallocatePacket(p);
1902 }
1903 else
1904 {
1905 PushBackPacket(p, false);
1906 }
1907 }
1908 else
1909 {
1910 PushBackPacket(p, false);
1911 }
1912 }
1913 */
1914 }
1915
1916 blockOnRPCReply=false;
1917 }
1918
1919 return true;
1920 }
1921
1922
1923 #ifdef _MSC_VER
1924 #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
1925 #endif
RPC(const char * uniqueID,const RakNet::BitStream * bitStream,PacketPriority priority,PacketReliability reliability,char orderingChannel,const AddressOrGUID systemIdentifier,bool broadcast,RakNetTime * includedTimestamp,NetworkID networkID,RakNet::BitStream * replyFromTarget)1926 bool RakPeer::RPC( const char* uniqueID, const RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RakNetTime *includedTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget )
1927 {
1928 if (bitStream)
1929 return RPC(uniqueID, (const char*) bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier.systemAddress, broadcast, includedTimestamp, networkID, replyFromTarget);
1930 else
1931 return RPC(uniqueID, 0,0, priority, reliability, orderingChannel, systemIdentifier.systemAddress, broadcast, includedTimestamp, networkID, replyFromTarget);
1932 }
1933
1934 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1935 // Description:
1936 // Close the connection to another host (if we initiated the connection it will disconnect, if they did it will kick them out).
1937 //
1938 // Parameters:
1939 // target: Which connection to close
1940 // sendDisconnectionNotification: True to send ID_DISCONNECTION_NOTIFICATION to the recipient. False to close it silently.
1941 // channel: If blockDuration > 0, the disconnect packet will be sent on this channel
1942 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloseConnection(const SystemAddress target,bool sendDisconnectionNotification,unsigned char orderingChannel,PacketPriority disconnectionNotificationPriority)1943 void RakPeer::CloseConnection( const SystemAddress target, bool sendDisconnectionNotification, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
1944 {
1945 // This only be called from the user thread, for the user shutting down.
1946 // From the network thread, this should occur because of ID_DISCONNECTION_NOTIFICATION and ID_CONNECTION_LOST
1947 unsigned j;
1948 for (j=0; j < messageHandlerList.Size(); j++)
1949 {
1950 messageHandlerList[j]->OnClosedConnection(target, GetGuidFromSystemAddress(target), LCR_CLOSED_BY_USER);
1951 }
1952
1953 CloseConnectionInternal(target, sendDisconnectionNotification, false, orderingChannel, disconnectionNotificationPriority);
1954
1955 // 12/14/09 Return ID_CONNECTION_LOST when calling CloseConnection with sendDisconnectionNotification==false, elsewise it is never returned
1956 if (sendDisconnectionNotification==false && IsConnected(target,false,false))
1957 {
1958 Packet *packet=AllocPacket(sizeof( char ), __FILE__, __LINE__);
1959 packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
1960 packet->guid = GetGuidFromSystemAddress(target);
1961 packet->systemAddress = target;
1962 packet->systemAddress.systemIndex = (SystemIndex) GetIndexFromSystemAddress(target,false);
1963 packet->guid.systemIndex=packet->systemAddress.systemIndex;
1964 AddPacketToProducer(packet);
1965 }
1966 }
1967
1968 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1969 // Cancel a pending connection attempt
1970 // If we are already connected, the connection stays open
1971 // \param[in] target Which system to cancel
1972 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CancelConnectionAttempt(const SystemAddress target)1973 void RakPeer::CancelConnectionAttempt( const SystemAddress target )
1974 {
1975 unsigned int i;
1976
1977 // Cancel pending connection attempt, if there is one
1978 i=0;
1979 requestedConnectionQueueMutex.Lock();
1980 while (i < requestedConnectionQueue.Size())
1981 {
1982 if (requestedConnectionQueue[i]->systemAddress==target)
1983 {
1984 RakNet::OP_DELETE(requestedConnectionQueue[i], __FILE__, __LINE__ );
1985 requestedConnectionQueue.RemoveAtIndex(i);
1986 break;
1987 }
1988 else
1989 i++;
1990 }
1991 requestedConnectionQueueMutex.Unlock();
1992
1993 }
1994 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsConnectionAttemptPending(const SystemAddress systemAddress)1995 bool RakPeer::IsConnectionAttemptPending( const SystemAddress systemAddress )
1996 {
1997 unsigned int i=0;
1998 requestedConnectionQueueMutex.Lock();
1999 for (; i < requestedConnectionQueue.Size(); i++)
2000 {
2001 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
2002 {
2003 requestedConnectionQueueMutex.Unlock();
2004 return true;
2005 }
2006 }
2007 requestedConnectionQueueMutex.Unlock();
2008
2009 int index = GetIndexFromSystemAddress(systemAddress, false);
2010 return index!=-1 && remoteSystemList[index].isActive &&
2011 (((remoteSystemList[index].connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
2012 remoteSystemList[index].connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
2013 remoteSystemList[index].connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
2014 remoteSystemList[index].connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET))
2015 )
2016 ;
2017 }
2018
2019 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2020 // Returns if a particular systemAddress is connected to us
2021 // \param[in] systemAddress The SystemAddress we are referring to
2022 // \return True if this system is connected and active, false otherwise.
2023 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsConnected(const AddressOrGUID systemIdentifier,bool includeInProgress,bool includeDisconnecting)2024 bool RakPeer::IsConnected( const AddressOrGUID systemIdentifier, bool includeInProgress, bool includeDisconnecting )
2025 {
2026 if (includeInProgress && systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
2027 {
2028 unsigned int i=0;
2029 requestedConnectionQueueMutex.Lock();
2030 for (; i < requestedConnectionQueue.Size(); i++)
2031 {
2032 if (requestedConnectionQueue[i]->systemAddress==systemIdentifier.systemAddress)
2033 {
2034 requestedConnectionQueueMutex.Unlock();
2035 return true;
2036 }
2037 }
2038 requestedConnectionQueueMutex.Unlock();
2039 }
2040
2041
2042 int index;
2043 if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
2044 {
2045 if (IsLoopbackAddress(systemIdentifier.systemAddress,true))
2046 return true;
2047 index = GetIndexFromSystemAddress(systemIdentifier.systemAddress, false);
2048 return index!=-1 && remoteSystemList[index].isActive &&
2049 (((includeInProgress && (remoteSystemList[index].connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
2050 remoteSystemList[index].connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
2051 remoteSystemList[index].connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
2052 remoteSystemList[index].connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET))
2053 ||
2054 (includeDisconnecting && (
2055 remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP ||
2056 remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY ||
2057 remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK))
2058 ||
2059 remoteSystemList[index].connectMode==RemoteSystemStruct::CONNECTED))
2060 ;
2061 }
2062 else
2063 {
2064 index = GetIndexFromGuid(systemIdentifier.rakNetGuid);
2065 return index!=-1 && remoteSystemList[index].isActive &&
2066 (((includeInProgress && (remoteSystemList[index].connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
2067 remoteSystemList[index].connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
2068 remoteSystemList[index].connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
2069 remoteSystemList[index].connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET))
2070 ||
2071 (includeDisconnecting && (
2072 remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP ||
2073 remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY ||
2074 remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK))
2075 ||
2076 remoteSystemList[index].connectMode==RemoteSystemStruct::CONNECTED))
2077 ;
2078 }
2079 }
2080
2081 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2082 // Description:
2083 // Given a systemAddress, returns an index from 0 to the maximum number of players allowed - 1.
2084 //
2085 // Parameters
2086 // systemAddress - The systemAddress to search for
2087 //
2088 // Returns
2089 // An integer from 0 to the maximum number of peers -1, or -1 if that player is not found
2090 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetIndexFromSystemAddress(const SystemAddress systemAddress) const2091 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress ) const
2092 {
2093 return GetIndexFromSystemAddress(systemAddress, false);
2094 }
2095
2096 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2097 // Description:
2098 // This function is only useful for looping through all players.
2099 //
2100 // Parameters
2101 // index - an integer between 0 and the maximum number of players allowed - 1.
2102 //
2103 // Returns
2104 // A valid systemAddress or UNASSIGNED_SYSTEM_ADDRESS if no such player at that index
2105 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetSystemAddressFromIndex(int index)2106 SystemAddress RakPeer::GetSystemAddressFromIndex( int index )
2107 {
2108 // remoteSystemList in user thread
2109 //if ( index >= 0 && index < remoteSystemListSize )
2110 if ( index >= 0 && index < maximumNumberOfPeers )
2111 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
2112 return remoteSystemList[ index ].systemAddress;
2113
2114 return UNASSIGNED_SYSTEM_ADDRESS;
2115 }
2116
2117 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2118 // Same as GetSystemAddressFromIndex but returns RakNetGUID
2119 // \param[in] index Index should range between 0 and the maximum number of players allowed - 1.
2120 // \return The RakNetGUID
2121 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetGUIDFromIndex(int index)2122 RakNetGUID RakPeer::GetGUIDFromIndex( int index )
2123 {
2124 // remoteSystemList in user thread
2125 //if ( index >= 0 && index < remoteSystemListSize )
2126 if ( index >= 0 && index < maximumNumberOfPeers )
2127 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
2128 return remoteSystemList[ index ].guid;
2129
2130 return UNASSIGNED_RAKNET_GUID;
2131 }
2132
2133 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2134 // Same as calling GetSystemAddressFromIndex and GetGUIDFromIndex for all systems, but more efficient
2135 // Indices match each other, so \a addresses[0] and \a guids[0] refer to the same system
2136 // \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.
2137 // \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.
2138 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetSystemList(DataStructures::List<SystemAddress> & addresses,DataStructures::List<RakNetGUID> & guids)2139 void RakPeer::GetSystemList(DataStructures::List<SystemAddress> &addresses, DataStructures::List<RakNetGUID> &guids)
2140 {
2141 addresses.Clear(false, __FILE__, __LINE__);
2142 guids.Clear(false, __FILE__, __LINE__);
2143 int index;
2144 for (index=0; index < maximumNumberOfPeers; index++)
2145 {
2146 // Don't give the user players that aren't fully connected, since sends will fail
2147 if (remoteSystemList[index].isActive && remoteSystemList[ index ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED)
2148 {
2149 addresses.Push(remoteSystemList[index].systemAddress, __FILE__, __LINE__ );
2150 guids.Push(remoteSystemList[index].guid, __FILE__, __LINE__ );
2151 }
2152 }
2153 }
2154
2155 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2156 // Description:
2157 // Bans an IP from connecting. Banned IPs persist between connections.
2158 //
2159 // Parameters
2160 // IP - Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will ban
2161 // All IP addresses starting with 128.0.0
2162 // milliseconds - how many ms for a temporary ban. Use 0 for a permanent ban
2163 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AddToBanList(const char * IP,RakNetTime milliseconds)2164 void RakPeer::AddToBanList( const char *IP, RakNetTime milliseconds )
2165 {
2166 unsigned index;
2167 RakNetTime time = RakNet::GetTime();
2168
2169 if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
2170 return ;
2171
2172 // If this guy is already in the ban list, do nothing
2173 index = 0;
2174
2175 banListMutex.Lock();
2176
2177 for ( ; index < banList.Size(); index++ )
2178 {
2179 if ( strcmp( IP, banList[ index ]->IP ) == 0 )
2180 {
2181 // Already in the ban list. Just update the time
2182 if (milliseconds==0)
2183 banList[ index ]->timeout=0; // Infinite
2184 else
2185 banList[ index ]->timeout=time+milliseconds;
2186 banListMutex.Unlock();
2187 return;
2188 }
2189 }
2190
2191 banListMutex.Unlock();
2192
2193 BanStruct *banStruct = RakNet::OP_NEW<BanStruct>( __FILE__, __LINE__ );
2194 banStruct->IP = (char*) rakMalloc_Ex( 16, __FILE__, __LINE__ );
2195 if (milliseconds==0)
2196 banStruct->timeout=0; // Infinite
2197 else
2198 banStruct->timeout=time+milliseconds;
2199 strcpy( banStruct->IP, IP );
2200 banListMutex.Lock();
2201 banList.Insert( banStruct, __FILE__, __LINE__ );
2202 banListMutex.Unlock();
2203 }
2204
2205 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2206 // Description:
2207 // Allows a previously banned IP to connect.
2208 //
2209 // Parameters
2210 // IP - Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will ban
2211 // All IP addresses starting with 128.0.0
2212 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RemoveFromBanList(const char * IP)2213 void RakPeer::RemoveFromBanList( const char *IP )
2214 {
2215 unsigned index;
2216 BanStruct *temp;
2217
2218 if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
2219 return ;
2220
2221 index = 0;
2222 temp=0;
2223
2224 banListMutex.Lock();
2225
2226 for ( ; index < banList.Size(); index++ )
2227 {
2228 if ( strcmp( IP, banList[ index ]->IP ) == 0 )
2229 {
2230 temp = banList[ index ];
2231 banList[ index ] = banList[ banList.Size() - 1 ];
2232 banList.RemoveAtIndex( banList.Size() - 1 );
2233 break;
2234 }
2235 }
2236
2237 banListMutex.Unlock();
2238
2239 if (temp)
2240 {
2241 rakFree_Ex(temp->IP, __FILE__, __LINE__ );
2242 RakNet::OP_DELETE(temp, __FILE__, __LINE__);
2243 }
2244
2245 }
2246
2247 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2248 // Description:
2249 // Allows all previously banned IPs to connect.
2250 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearBanList(void)2251 void RakPeer::ClearBanList( void )
2252 {
2253 unsigned index;
2254 index = 0;
2255 banListMutex.Lock();
2256
2257 for ( ; index < banList.Size(); index++ )
2258 {
2259 rakFree_Ex(banList[ index ]->IP, __FILE__, __LINE__ );
2260 RakNet::OP_DELETE(banList[ index ], __FILE__, __LINE__);
2261 }
2262
2263 banList.Clear(false, __FILE__, __LINE__);
2264
2265 banListMutex.Unlock();
2266 }
2267 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetLimitIPConnectionFrequency(bool b)2268 void RakPeer::SetLimitIPConnectionFrequency(bool b)
2269 {
2270 limitConnectionFrequencyFromTheSameIP=b;
2271 }
2272
2273 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2274 // Description:
2275 // Determines if a particular IP is banned.
2276 //
2277 // Parameters
2278 // IP - Complete dotted IP address
2279 //
2280 // Returns
2281 // True if IP matches any IPs in the ban list, accounting for any wildcards.
2282 // False otherwise.
2283 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsBanned(const char * IP)2284 bool RakPeer::IsBanned( const char *IP )
2285 {
2286 unsigned banListIndex, characterIndex;
2287 RakNetTime time;
2288 BanStruct *temp;
2289
2290 if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
2291 return false;
2292
2293 banListIndex = 0;
2294
2295 if ( banList.Size() == 0 )
2296 return false; // Skip the mutex if possible
2297
2298 time = RakNet::GetTime();
2299
2300 banListMutex.Lock();
2301
2302 while ( banListIndex < banList.Size() )
2303 {
2304 if (banList[ banListIndex ]->timeout>0 && banList[ banListIndex ]->timeout<time)
2305 {
2306 // Delete expired ban
2307 temp = banList[ banListIndex ];
2308 banList[ banListIndex ] = banList[ banList.Size() - 1 ];
2309 banList.RemoveAtIndex( banList.Size() - 1 );
2310 rakFree_Ex(temp->IP, __FILE__, __LINE__ );
2311 RakNet::OP_DELETE(temp, __FILE__, __LINE__);
2312 }
2313 else
2314 {
2315 characterIndex = 0;
2316
2317 #ifdef _MSC_VER
2318 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
2319 #endif
2320 while ( true )
2321 {
2322 if ( banList[ banListIndex ]->IP[ characterIndex ] == IP[ characterIndex ] )
2323 {
2324 // Equal characters
2325
2326 if ( IP[ characterIndex ] == 0 )
2327 {
2328 banListMutex.Unlock();
2329 // End of the string and the strings match
2330
2331 return true;
2332 }
2333
2334 characterIndex++;
2335 }
2336
2337 else
2338 {
2339 if ( banList[ banListIndex ]->IP[ characterIndex ] == 0 || IP[ characterIndex ] == 0 )
2340 {
2341 // End of one of the strings
2342 break;
2343 }
2344
2345 // Characters do not match
2346 if ( banList[ banListIndex ]->IP[ characterIndex ] == '*' )
2347 {
2348 banListMutex.Unlock();
2349
2350 // Domain is banned.
2351 return true;
2352 }
2353
2354 // Characters do not match and it is not a *
2355 break;
2356 }
2357 }
2358
2359 banListIndex++;
2360 }
2361 }
2362
2363 banListMutex.Unlock();
2364
2365 // No match found.
2366 return false;
2367 }
2368
2369 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2370 // Description:
2371 // Send a ping to the specified connected system.
2372 //
2373 // Parameters:
2374 // target - who to ping
2375 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ping(const SystemAddress target)2376 void RakPeer::Ping( const SystemAddress target )
2377 {
2378 PingInternal(target, false, UNRELIABLE);
2379 }
2380
2381 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2382 // Description:
2383 // Send a ping to the specified unconnected system.
2384 // The remote system, if it is Initialized, will respond with ID_PONG.
2385 // The final ping time will be encoded in the following sizeof(RakNetTime) bytes. (Default is 4 bytes - See __GET_TIME_64BIT in RakNetTypes.h
2386 //
2387 // Parameters:
2388 // host: Either a dotted IP address or a domain name. Can be 255.255.255.255 for LAN broadcast.
2389 // remotePort: Which port to connect to on the remote machine.
2390 // onlyReplyOnAcceptingConnections: Only request a reply if the remote system has open connections
2391 // connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on.
2392 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ping(const char * host,unsigned short remotePort,bool onlyReplyOnAcceptingConnections,unsigned connectionSocketIndex)2393 bool RakPeer::Ping( const char* host, unsigned short remotePort, bool onlyReplyOnAcceptingConnections, unsigned connectionSocketIndex )
2394 {
2395 if ( host == 0 )
2396 return false;
2397
2398 // If this assert hits then Startup wasn't called or the call failed.
2399 RakAssert(connectionSocketIndex < socketList.Size());
2400
2401 // if ( IsActive() == false )
2402 // return;
2403
2404 if ( NonNumericHostString( host ) )
2405 {
2406 host = ( char* ) SocketLayer::DomainNameToIP( host );
2407 if (host==0)
2408 return false;
2409 }
2410
2411 SystemAddress systemAddress;
2412 systemAddress.SetBinaryAddress(host);
2413 systemAddress.port=remotePort;
2414
2415 RakNet::BitStream bitStream( sizeof(unsigned char) + sizeof(RakNetTime) );
2416 if ( onlyReplyOnAcceptingConnections )
2417 bitStream.Write((MessageID)ID_PING_OPEN_CONNECTIONS);
2418 else
2419 bitStream.Write((MessageID)ID_PING);
2420
2421 bitStream.Write(RakNet::GetTime());
2422
2423 bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
2424
2425 unsigned i;
2426 for (i=0; i < messageHandlerList.Size(); i++)
2427 messageHandlerList[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
2428 // No timestamp for 255.255.255.255
2429 unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
2430 SocketLayer::SendTo( socketList[realIndex]->s, (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), ( char* ) host, remotePort, socketList[realIndex]->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
2431
2432 return true;
2433 }
2434
2435 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2436 // Description:
2437 // Returns the average of all ping times read for a specified target
2438 //
2439 // Parameters:
2440 // target - whose time to read
2441 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetAveragePing(const AddressOrGUID systemIdentifier)2442 int RakPeer::GetAveragePing( const AddressOrGUID systemIdentifier )
2443 {
2444 int sum, quantity;
2445 RemoteSystemStruct *remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2446
2447 if ( remoteSystem == 0 )
2448 return -1;
2449
2450 for ( sum = 0, quantity = 0; quantity < PING_TIMES_ARRAY_SIZE; quantity++ )
2451 {
2452 if ( remoteSystem->pingAndClockDifferential[ quantity ].pingTime == 65535 )
2453 break;
2454 else
2455 sum += remoteSystem->pingAndClockDifferential[ quantity ].pingTime;
2456 }
2457
2458 if ( quantity > 0 )
2459 return sum / quantity;
2460 else
2461 return -1;
2462 }
2463
2464 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2465 // Description:
2466 // Returns the last ping time read for the specific player or -1 if none read yet
2467 //
2468 // Parameters:
2469 // target - whose time to read
2470 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetLastPing(const AddressOrGUID systemIdentifier) const2471 int RakPeer::GetLastPing( const AddressOrGUID systemIdentifier ) const
2472 {
2473 RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2474
2475 if ( remoteSystem == 0 )
2476 return -1;
2477
2478 // return (int)(remoteSystem->reliabilityLayer.GetAckPing()/(RakNetTimeUS)1000);
2479
2480 if ( remoteSystem->pingAndClockDifferentialWriteIndex == 0 )
2481 return remoteSystem->pingAndClockDifferential[ PING_TIMES_ARRAY_SIZE - 1 ].pingTime;
2482 else
2483 return remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex - 1 ].pingTime;
2484 }
2485
2486 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2487 // Description:
2488 // Returns the lowest ping time read or -1 if none read yet
2489 //
2490 // Parameters:
2491 // target - whose time to read
2492 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetLowestPing(const AddressOrGUID systemIdentifier) const2493 int RakPeer::GetLowestPing( const AddressOrGUID systemIdentifier ) const
2494 {
2495 RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2496
2497 if ( remoteSystem == 0 )
2498 return -1;
2499
2500 return remoteSystem->lowestPing;
2501 }
2502
2503 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2504 // Description:
2505 // Ping the remote systems every so often. This is off by default
2506 // This will work anytime
2507 //
2508 // Parameters:
2509 // doPing - True to start occasional pings. False to stop them.
2510 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetOccasionalPing(bool doPing)2511 void RakPeer::SetOccasionalPing( bool doPing )
2512 {
2513 occasionalPing = doPing;
2514 }
2515 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2516 // Description:
2517 // Length should be under 400 bytes, as a security measure against flood attacks
2518 // Sets the data to send with an (LAN server discovery) /(offline ping) response
2519 // See the Ping sample project for how this is used.
2520 // data: a block of data to store, or 0 for none
2521 // length: The length of data in bytes, or 0 for none
2522 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetOfflinePingResponse(const char * data,const unsigned int length)2523 void RakPeer::SetOfflinePingResponse( const char *data, const unsigned int length )
2524 {
2525 RakAssert(length < 400);
2526
2527 rakPeerMutexes[ offlinePingResponse_Mutex ].Lock();
2528 offlinePingResponse.Reset();
2529
2530 if ( data && length > 0 )
2531 offlinePingResponse.Write( data, length );
2532
2533 rakPeerMutexes[ offlinePingResponse_Mutex ].Unlock();
2534 }
2535
2536 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2537 // Returns pointers to a copy of the data passed to SetOfflinePingResponse
2538 // \param[out] data A pointer to a copy of the data passed to \a SetOfflinePingResponse()
2539 // \param[out] length A pointer filled in with the length parameter passed to SetOfflinePingResponse()
2540 // \sa SetOfflinePingResponse
2541 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetOfflinePingResponse(char ** data,unsigned int * length)2542 void RakPeer::GetOfflinePingResponse( char **data, unsigned int *length )
2543 {
2544 rakPeerMutexes[ offlinePingResponse_Mutex ].Lock();
2545 *data = (char*) offlinePingResponse.GetData();
2546 *length = (int) offlinePingResponse.GetNumberOfBytesUsed();
2547 rakPeerMutexes[ offlinePingResponse_Mutex ].Unlock();
2548 }
2549
2550 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2551 // Description:
2552 // Return the unique SystemAddress that represents you on the the network
2553 // Note that unlike in previous versions, this is a struct and is not sequential
2554 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetInternalID(const SystemAddress systemAddress,const int index) const2555 SystemAddress RakPeer::GetInternalID( const SystemAddress systemAddress, const int index ) const
2556 {
2557 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
2558 {
2559 return mySystemAddress[index];
2560 }
2561 else
2562 {
2563
2564 // SystemAddress returnValue;
2565 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, false, true );
2566 if (remoteSystem==0)
2567 return UNASSIGNED_SYSTEM_ADDRESS;
2568
2569 return remoteSystem->theirInternalSystemAddress[index];
2570 /*
2571 sockaddr_in sa;
2572 socklen_t len = sizeof(sa);
2573 if (getsockname(connectionSockets[remoteSystem->connectionSocketIndex], (sockaddr*)&sa, &len)!=0)
2574 return UNASSIGNED_SYSTEM_ADDRESS;
2575 returnValue.port=ntohs(sa.sin_port);
2576 returnValue.binaryAddress=sa.sin_addr.s_addr;
2577 return returnValue;
2578 */
2579
2580
2581
2582 }
2583 }
2584
2585 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2586 // Description:
2587 // Return the unique address identifier that represents you on the the network and is based on your external
2588 // IP / port (the IP / port the specified player uses to communicate with you)
2589 // Note that unlike in previous versions, this is a struct and is not sequential
2590 //
2591 // Parameters:
2592 // target: Which remote system you are referring to for your external ID
2593 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetExternalID(const SystemAddress target) const2594 SystemAddress RakPeer::GetExternalID( const SystemAddress target ) const
2595 {
2596 unsigned i;
2597 SystemAddress inactiveExternalId;
2598
2599 inactiveExternalId=UNASSIGNED_SYSTEM_ADDRESS;
2600
2601 if (target==UNASSIGNED_SYSTEM_ADDRESS)
2602 return firstExternalID;
2603
2604 // First check for active connection with this systemAddress
2605 for ( i = 0; i < maximumNumberOfPeers; i++ )
2606 {
2607 if (remoteSystemList[ i ].systemAddress == target )
2608 {
2609 if ( remoteSystemList[ i ].isActive )
2610 return remoteSystemList[ i ].myExternalSystemAddress;
2611 else if (remoteSystemList[ i ].myExternalSystemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
2612 inactiveExternalId=remoteSystemList[ i ].myExternalSystemAddress;
2613 }
2614 }
2615
2616 return inactiveExternalId;
2617 }
2618
2619 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2620
GetGuidFromSystemAddress(const SystemAddress input) const2621 const RakNetGUID& RakPeer::GetGuidFromSystemAddress( const SystemAddress input ) const
2622 {
2623 if (input==UNASSIGNED_SYSTEM_ADDRESS)
2624 return myGuid;
2625
2626 if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].systemAddress == input)
2627 return remoteSystemList[ input.systemIndex ].guid;
2628
2629 unsigned int i;
2630 for ( i = 0; i < maximumNumberOfPeers; i++ )
2631 {
2632 if (remoteSystemList[ i ].systemAddress == input )
2633 {
2634 return remoteSystemList[ i ].guid;
2635 }
2636 }
2637
2638 return UNASSIGNED_RAKNET_GUID;
2639 }
2640
2641 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2642
GetSystemIndexFromGuid(const RakNetGUID input) const2643 unsigned int RakPeer::GetSystemIndexFromGuid( const RakNetGUID input ) const
2644 {
2645 if (input==UNASSIGNED_RAKNET_GUID)
2646 return (unsigned int) -1;
2647
2648 if (input==myGuid)
2649 return (unsigned int) -1;
2650
2651 if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
2652 return input.systemIndex;
2653
2654 unsigned int i;
2655 for ( i = 0; i < maximumNumberOfPeers; i++ )
2656 {
2657 if (remoteSystemList[ i ].guid == input )
2658 {
2659 return i;
2660 }
2661 }
2662
2663 return (unsigned int) -1;
2664 }
2665
2666 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2667
GetSystemAddressFromGuid(const RakNetGUID input) const2668 SystemAddress RakPeer::GetSystemAddressFromGuid( const RakNetGUID input ) const
2669 {
2670 if (input==UNASSIGNED_RAKNET_GUID)
2671 return UNASSIGNED_SYSTEM_ADDRESS;
2672
2673 if (input==myGuid)
2674 return GetInternalID(UNASSIGNED_SYSTEM_ADDRESS);
2675
2676 if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
2677 return remoteSystemList[ input.systemIndex ].systemAddress;
2678
2679 unsigned int i;
2680 for ( i = 0; i < maximumNumberOfPeers; i++ )
2681 {
2682 if (remoteSystemList[ i ].guid == input )
2683 {
2684 return remoteSystemList[ i ].systemAddress;
2685 }
2686 }
2687
2688 return UNASSIGNED_SYSTEM_ADDRESS;
2689 }
2690
2691 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2692 // Set the time, in MS, to use before considering ourselves disconnected after not being able to deliver a reliable packet
2693 // \param[in] time Time, in MS
2694 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetTimeoutTime(RakNetTime timeMS,const SystemAddress target)2695 void RakPeer::SetTimeoutTime( RakNetTime timeMS, const SystemAddress target )
2696 {
2697 if (target==UNASSIGNED_SYSTEM_ADDRESS)
2698 {
2699 defaultTimeoutTime=timeMS;
2700
2701 unsigned i;
2702 for ( i = 0; i < maximumNumberOfPeers; i++ )
2703 {
2704 if (remoteSystemList[ i ].isActive)
2705 {
2706 if ( remoteSystemList[ i ].isActive )
2707 remoteSystemList[ i ].reliabilityLayer.SetTimeoutTime(timeMS);
2708 }
2709 }
2710 }
2711 else
2712 {
2713 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
2714
2715 if ( remoteSystem != 0 )
2716 remoteSystem->reliabilityLayer.SetTimeoutTime(timeMS);
2717 }
2718 }
2719
2720 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2721
GetTimeoutTime(const SystemAddress target)2722 RakNetTime RakPeer::GetTimeoutTime( const SystemAddress target )
2723 {
2724 if (target==UNASSIGNED_SYSTEM_ADDRESS)
2725 {
2726 return defaultTimeoutTime;
2727 }
2728 else
2729 {
2730 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
2731
2732 if ( remoteSystem != 0 )
2733 remoteSystem->reliabilityLayer.GetTimeoutTime();
2734 }
2735 return defaultTimeoutTime;
2736 }
2737
2738 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2739 // Description:
2740 // Change the MTU size in order to improve performance when sending large packets
2741 // This can only be called when not connected.
2742 // A too high of value will cause packets not to arrive at worst and be fragmented at best.
2743 // A too low of value will split packets unnecessarily.
2744 //
2745 // Parameters:
2746 // size: Set according to the following table:
2747 // 1500. The largest Ethernet packet size
2748 // This is the typical setting for non-PPPoE, non-VPN connections. The default value for NETGEAR routers, adapters and switches.
2749 // 1492. The size PPPoE prefers.
2750 // 1472. Maximum size to use for pinging. (Bigger packets are fragmented.)
2751 // 1468. The size DHCP prefers.
2752 // 1460. Usable by AOL if you don't have large email attachments, etc.
2753 // 1430. The size VPN and PPTP prefer.
2754 // 1400. Maximum size for AOL DSL.
2755 // 576. Typical value to connect to dial-up ISPs. (Default)
2756 //
2757 // Returns:
2758 // False on failure (we are connected). True on success. Maximum allowed size is MAXIMUM_MTU_SIZE
2759 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2760 /*
2761 bool RakPeer::SetMTUSize( int size, const SystemAddress target )
2762 {
2763 if ( IsActive() )
2764 return false;
2765
2766 if ( size < 512 )
2767 size = 512;
2768 else if ( size > MAXIMUM_MTU_SIZE )
2769 size = MAXIMUM_MTU_SIZE;
2770
2771 if (target==UNASSIGNED_SYSTEM_ADDRESS)
2772 {
2773 defaultMTUSize = size;
2774
2775 int i;
2776 // Active connections take priority. But if there are no active connections, return the first systemAddress match found
2777 for ( i = 0; i < maximumNumberOfPeers; i++ )
2778 {
2779 remoteSystemList[i].MTUSize=size;
2780 }
2781 }
2782 else
2783 {
2784 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(target, false, true);
2785 if (rss)
2786 rss->MTUSize=size;
2787 }
2788
2789 return true;
2790 }
2791 */
2792
2793 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2794 // Description:
2795 // Returns the current MTU size
2796 //
2797 // Returns:
2798 // The MTU sized specified in SetMTUSize
2799 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetMTUSize(const SystemAddress target) const2800 int RakPeer::GetMTUSize( const SystemAddress target ) const
2801 {
2802 if (target!=UNASSIGNED_SYSTEM_ADDRESS)
2803 {
2804 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(target, false, true);
2805 if (rss)
2806 return rss->MTUSize;
2807 }
2808 return defaultMTUSize;
2809 }
2810 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2811 // Description:
2812 // Returns the number of IP addresses we have
2813 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetNumberOfAddresses(void)2814 unsigned int RakPeer::GetNumberOfAddresses( void )
2815 {
2816
2817 int i = 0;
2818
2819 while ( ipList[ i ][ 0 ] )
2820 i++;
2821
2822 return i;
2823
2824
2825
2826
2827 }
2828
2829 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2830 // Returns an IP address at index 0 to GetNumberOfAddresses-1
2831 // \param[in] index index into the list of IP addresses
2832 // \return The local IP address at this index
2833 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetLocalIP(unsigned int index)2834 const char* RakPeer::GetLocalIP( unsigned int index )
2835 {
2836 if (IsActive()==false)
2837 {
2838 // Fill out ipList structure
2839
2840 memset( ipList, 0, sizeof( char ) * 16 * MAXIMUM_NUMBER_OF_INTERNAL_IDS );
2841 SocketLayer::GetMyIP( ipList,binaryAddresses );
2842
2843 }
2844
2845
2846 return ipList[ index ];
2847
2848
2849
2850
2851 }
2852
2853 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2854 // Is this a local IP?
2855 // \param[in] An IP address to check
2856 // \return True if this is one of the IP addresses returned by GetLocalIP
2857 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsLocalIP(const char * ip)2858 bool RakPeer::IsLocalIP( const char *ip )
2859 {
2860 if (ip==0 || ip[0]==0)
2861 return false;
2862
2863
2864 if (strcmp(ip, "127.0.0.1")==0 || strcmp(ip, "localhost")==0)
2865 return true;
2866
2867 int num = GetNumberOfAddresses();
2868 int i;
2869 for (i=0; i < num; i++)
2870 {
2871 if (strcmp(ip, GetLocalIP(i))==0)
2872 return true;
2873 }
2874
2875
2876
2877
2878 return false;
2879 }
2880
2881 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2882 // Description:
2883 // Allow or disallow connection responses from any IP. Normally this should be false, but may be necessary
2884 // when connection to servers with multiple IP addresses
2885 //
2886 // Parameters:
2887 // allow - True to allow this behavior, false to not allow. Defaults to false. Value persists between connections
2888 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AllowConnectionResponseIPMigration(bool allow)2889 void RakPeer::AllowConnectionResponseIPMigration( bool allow )
2890 {
2891 allowConnectionResponseIPMigration = allow;
2892 }
2893
2894 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2895 // Description:
2896 // Sends a message ID_ADVERTISE_SYSTEM to the remote unconnected system.
2897 // This will tell the remote system our external IP outside the LAN, and can be used for NAT punch through
2898 //
2899 // Requires:
2900 // The sender and recipient must already be started via a successful call to Initialize
2901 //
2902 // host: Either a dotted IP address or a domain name
2903 // remotePort: Which port to connect to on the remote machine.
2904 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AdvertiseSystem(const char * host,unsigned short remotePort,const char * data,int dataLength,unsigned connectionSocketIndex)2905 bool RakPeer::AdvertiseSystem( const char *host, unsigned short remotePort, const char *data, int dataLength, unsigned connectionSocketIndex )
2906 {
2907 RakNet::BitStream bs;
2908 bs.Write((MessageID)ID_ADVERTISE_SYSTEM);
2909 bs.WriteAlignedBytes((const unsigned char*) data,dataLength);
2910 return SendOutOfBand(host, remotePort, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), connectionSocketIndex );
2911 }
2912
2913 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2914 // Controls how often to return ID_DOWNLOAD_PROGRESS for large message downloads.
2915 // ID_DOWNLOAD_PROGRESS is returned to indicate a new partial message chunk, roughly the MTU size, has arrived
2916 // As it can be slow or cumbersome to get this notification for every chunk, you can set the interval at which it is returned.
2917 // Defaults to 0 (never return this notification)
2918 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetSplitMessageProgressInterval(int interval)2919 void RakPeer::SetSplitMessageProgressInterval(int interval)
2920 {
2921 RakAssert(interval>=0);
2922 splitMessageProgressInterval=interval;
2923 for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
2924 remoteSystemList[ i ].reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval);
2925 }
2926
2927 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2928 // Returns what was passed to SetSplitMessageProgressInterval()
2929 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetSplitMessageProgressInterval(void) const2930 int RakPeer::GetSplitMessageProgressInterval(void) const
2931 {
2932 return splitMessageProgressInterval;
2933 }
2934
2935 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2936 // Set how long to wait before giving up on sending an unreliable message
2937 // Useful if the network is clogged up.
2938 // Set to 0 or less to never timeout. Defaults to 0.
2939 // timeoutMS How many ms to wait before simply not sending an unreliable message.
2940 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetUnreliableTimeout(RakNetTime timeoutMS)2941 void RakPeer::SetUnreliableTimeout(RakNetTime timeoutMS)
2942 {
2943 unreliableTimeout=timeoutMS;
2944 for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
2945 remoteSystemList[ i ].reliabilityLayer.SetUnreliableTimeout(unreliableTimeout);
2946 }
2947
2948 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2949 // Send a message to host, with the IP socket option TTL set to 3
2950 // This message will not reach the host, but will open the router.
2951 // Used for NAT-Punchthrough
2952 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendTTL(const char * host,unsigned short remotePort,int ttl,unsigned connectionSocketIndex)2953 void RakPeer::SendTTL( const char* host, unsigned short remotePort, int ttl, unsigned connectionSocketIndex )
2954 {
2955 char fakeData[2];
2956 fakeData[0]=0;
2957 fakeData[1]=1;
2958 unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
2959 SocketLayer::SendToTTL( socketList[realIndex]->s, (char*)fakeData, 2, (char*) host, remotePort, ttl );
2960 }
2961
2962 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2963 // Description:
2964 // Enables or disables our tracking of bytes input to and output from the network.
2965 // This is required to get a frequency table, which is used to generate a new compression layer.
2966 // You can call this at any time - however you SHOULD only call it when disconnected. Otherwise you will only track
2967 // part of the values sent over the network.
2968 // This value persists between connect calls and defaults to false (no frequency tracking)
2969 //
2970 // Parameters:
2971 // doCompile - true to track bytes. Defaults to false
2972 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetCompileFrequencyTable(bool doCompile)2973 void RakPeer::SetCompileFrequencyTable( bool doCompile )
2974 {
2975 trackFrequencyTable = doCompile;
2976 }
2977
2978 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2979 // Description:
2980 // Returns the frequency of outgoing bytes into outputFrequencyTable
2981 // The purpose is to save to file as either a master frequency table from a sample game session for passing to
2982 // GenerateCompressionLayer(false)
2983 // You should only call this when disconnected.
2984 // Requires that you first enable data frequency tracking by calling SetCompileFrequencyTable(true)
2985 //
2986 // Parameters:
2987 // outputFrequencyTable (out): The frequency of each corresponding byte
2988 //
2989 // Returns:
2990 // Ffalse (failure) if connected or if frequency table tracking is not enabled. Otherwise true (success)
2991 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetOutgoingFrequencyTable(unsigned int outputFrequencyTable[256])2992 bool RakPeer::GetOutgoingFrequencyTable( unsigned int outputFrequencyTable[ 256 ] )
2993 {
2994 if ( IsActive() )
2995 return false;
2996
2997 if ( trackFrequencyTable == false )
2998 return false;
2999
3000 memcpy( outputFrequencyTable, frequencyTable, sizeof( unsigned int ) * 256 );
3001
3002 return true;
3003 }
3004
3005 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3006 // Description:
3007 // Generates the compression layer from the input frequency table.
3008 // You should call this twice - once with inputLayer as true and once as false.
3009 // The frequency table passed here with inputLayer=true should match the frequency table on the recipient with inputLayer=false.
3010 // Likewise, the frequency table passed here with inputLayer=false should match the frequency table on the recipient with inputLayer=true
3011 // Calling this function when there is an existing layer will overwrite the old layer
3012 // You should only call this when disconnected
3013 //
3014 // Parameters:
3015 // inputFrequencyTable: The frequency table returned from GetSendFrequencyTable(...)
3016 // inputLayer - Whether inputFrequencyTable represents incoming data from other systems (true) or outgoing data from this system (false)
3017 //
3018 // Returns:
3019 // False on failure (we are connected). True otherwise
3020 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GenerateCompressionLayer(unsigned int inputFrequencyTable[256],bool inputLayer)3021 bool RakPeer::GenerateCompressionLayer( unsigned int inputFrequencyTable[ 256 ], bool inputLayer )
3022 {
3023 if ( IsActive() )
3024 return false;
3025
3026 DeleteCompressionLayer( inputLayer );
3027
3028 if ( inputLayer )
3029 {
3030 inputTree = RakNet::OP_NEW<HuffmanEncodingTree>( __FILE__, __LINE__ );
3031 inputTree->GenerateFromFrequencyTable( inputFrequencyTable );
3032 }
3033
3034 else
3035 {
3036 outputTree = RakNet::OP_NEW<HuffmanEncodingTree>( __FILE__, __LINE__ );
3037 outputTree->GenerateFromFrequencyTable( inputFrequencyTable );
3038 }
3039
3040 return true;
3041 }
3042
3043 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3044 // Description:
3045 // Deletes the output or input layer as specified. This is not necessary to call and is only valuable for freeing memory
3046 // You should only call this when disconnected
3047 //
3048 // Parameters:
3049 // inputLayer - Specifies the corresponding compression layer generated by GenerateCompressionLayer.
3050 //
3051 // Returns:
3052 // False on failure (we are connected). True otherwise
3053 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DeleteCompressionLayer(bool inputLayer)3054 bool RakPeer::DeleteCompressionLayer( bool inputLayer )
3055 {
3056 if ( IsActive() )
3057 return false;
3058
3059 if ( inputLayer )
3060 {
3061 if ( inputTree )
3062 {
3063 RakNet::OP_DELETE(inputTree, __FILE__, __LINE__);
3064 inputTree = 0;
3065 }
3066 }
3067
3068 else
3069 {
3070 if ( outputTree )
3071 {
3072 RakNet::OP_DELETE(outputTree, __FILE__, __LINE__);
3073 outputTree = 0;
3074 }
3075 }
3076
3077 return true;
3078 }
3079
3080 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3081 // Returns:
3082 // The compression ratio. A low compression ratio is good. Compression is for outgoing data
3083 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetCompressionRatio(void) const3084 float RakPeer::GetCompressionRatio( void ) const
3085 {
3086 if ( rawBytesSent > 0 )
3087 {
3088 return ( float ) compressedBytesSent / ( float ) rawBytesSent;
3089 }
3090
3091 else
3092 return 0.0f;
3093 }
3094
3095 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3096 // Returns:
3097 // The decompression ratio. A high decompression ratio is good. Decompression is for incoming data
3098 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetDecompressionRatio(void) const3099 float RakPeer::GetDecompressionRatio( void ) const
3100 {
3101 if ( rawBytesReceived > 0 )
3102 {
3103 return ( float ) compressedBytesReceived / ( float ) rawBytesReceived;
3104 }
3105
3106 else
3107 return 0.0f;
3108 }
3109
3110 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3111 // Attatches a Plugin interface to run code automatically on message receipt in the Receive call
3112 //
3113 // \param messageHandler Pointer to a plugin to attach
3114 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AttachPlugin(PluginInterface2 * plugin)3115 void RakPeer::AttachPlugin( PluginInterface2 *plugin )
3116 {
3117 if (messageHandlerList.GetIndexOf(plugin)==MAX_UNSIGNED_LONG)
3118 {
3119 plugin->SetRakPeerInterface(this);
3120 plugin->OnAttach();
3121 messageHandlerList.Insert(plugin, __FILE__, __LINE__);
3122 }
3123 }
3124
3125 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3126 // Detaches a Plugin interface to run code automatically on message receipt
3127 //
3128 // \param messageHandler Pointer to a plugin to detach
3129 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DetachPlugin(PluginInterface2 * plugin)3130 void RakPeer::DetachPlugin( PluginInterface2 *plugin )
3131 {
3132 if (plugin==0)
3133 return;
3134
3135 unsigned int index;
3136 index = messageHandlerList.GetIndexOf(plugin);
3137 if (index!=MAX_UNSIGNED_LONG)
3138 {
3139 // Unordered list so delete from end for speed
3140 messageHandlerList[index]=messageHandlerList[messageHandlerList.Size()-1];
3141 messageHandlerList.RemoveFromEnd();
3142 plugin->OnDetach();
3143 plugin->SetRakPeerInterface(0);
3144 }
3145 }
3146
3147 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3148 // Put a packet back at the end of the receive queue in case you don't want to deal with it immediately
3149 //
3150 // packet The packet you want to push back.
3151 // 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)
3152 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PushBackPacket(Packet * packet,bool pushAtHead)3153 void RakPeer::PushBackPacket( Packet *packet, bool pushAtHead)
3154 {
3155 if (packet==0)
3156 return;
3157
3158 unsigned i;
3159 for (i=0; i < messageHandlerList.Size(); i++)
3160 messageHandlerList[i]->OnPushBackPacket((const char*) packet->data, packet->bitSize, packet->systemAddress);
3161
3162 packetReturnMutex.Lock();
3163 if (pushAtHead)
3164 packetReturnQueue.PushAtHead(packet,0,__FILE__,__LINE__);
3165 else
3166 packetReturnQueue.Push(packet,__FILE__,__LINE__);
3167 packetReturnMutex.Unlock();
3168 }
3169
3170 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetRouterInterface(RouterInterface * routerInterface)3171 void RakPeer::SetRouterInterface( RouterInterface *routerInterface )
3172 {
3173 router=routerInterface;
3174 }
3175 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RemoveRouterInterface(RouterInterface * routerInterface)3176 void RakPeer::RemoveRouterInterface( RouterInterface *routerInterface )
3177 {
3178 if (router==routerInterface)
3179 router=0;
3180 }
3181 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ChangeSystemAddress(RakNetGUID guid,SystemAddress systemAddress)3182 void RakPeer::ChangeSystemAddress(RakNetGUID guid, SystemAddress systemAddress)
3183 {
3184 BufferedCommandStruct *bcs;
3185
3186 #ifdef _RAKNET_THREADSAFE
3187 bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
3188 #else
3189 bcs=bufferedCommands.WriteLock();
3190 #endif
3191 bcs->data = 0;
3192 bcs->systemIdentifier.systemAddress=systemAddress;
3193 bcs->systemIdentifier.rakNetGuid=guid;
3194 bcs->command=BufferedCommandStruct::BCS_CHANGE_SYSTEM_ADDRESS;
3195 #ifdef _RAKNET_THREADSAFE
3196 bufferedCommands.Push(bcs);
3197 #else
3198 bufferedCommands.WriteUnlock();
3199 #endif
3200 }
3201 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AllocatePacket(unsigned dataSize)3202 Packet* RakPeer::AllocatePacket(unsigned dataSize)
3203 {
3204 return AllocPacket(dataSize, __FILE__, __LINE__);
3205 }
3206 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetSocket(const SystemAddress target)3207 RakNetSmartPtr<RakNetSocket> RakPeer::GetSocket( const SystemAddress target )
3208 {
3209 // Send a query to the thread to get the socket, and return when we got it
3210 BufferedCommandStruct *bcs;
3211 #ifdef _RAKNET_THREADSAFE
3212 bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
3213 bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
3214 bcs->systemIdentifier=target;
3215 bcs->data=0;
3216 bufferedCommands.Push(bcs);
3217 #else
3218 bcs=bufferedCommands.WriteLock();
3219 bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
3220 bcs->systemIdentifier=target;
3221 bcs->data=0;
3222 bufferedCommands.WriteUnlock();
3223 #endif
3224
3225 // Block up to one second to get the socket, although it should actually take virtually no time
3226 SocketQueryOutput *sqo;
3227 RakNetTime stopWaiting = RakNet::GetTime()+1000;
3228 DataStructures::List<RakNetSmartPtr<RakNetSocket> > output;
3229 while (RakNet::GetTime() < stopWaiting)
3230 {
3231 if (isMainLoopThreadActive==false)
3232 return RakNetSmartPtr<RakNetSocket>();
3233
3234 RakSleep(0);
3235
3236 #ifdef _RAKNET_THREADSAFE
3237 sqo = socketQueryOutput.Pop();
3238 if (sqo)
3239 {
3240 output=sqo->sockets;
3241 sqo->sockets.Clear(false, __FILE__, __LINE__);
3242 socketQueryOutput.Deallocate(sqo, __FILE__,__LINE__);
3243 if (output.Size())
3244 return output[0];
3245 break;
3246 }
3247 #else
3248 sqo = socketQueryOutput.ReadLock();
3249 if (sqo)
3250 {
3251 output=sqo->sockets;
3252 sqo->sockets.Clear(false, __FILE__, __LINE__);
3253 socketQueryOutput.ReadUnlock();
3254 if (output.Size())
3255 return output[0];
3256 break;
3257 }
3258 #endif
3259 }
3260 return RakNetSmartPtr<RakNetSocket>();
3261 }
3262 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetSockets(DataStructures::List<RakNetSmartPtr<RakNetSocket>> & sockets)3263 void RakPeer::GetSockets( DataStructures::List<RakNetSmartPtr<RakNetSocket> > &sockets )
3264 {
3265 sockets.Clear(false, __FILE__, __LINE__);
3266
3267 // Send a query to the thread to get the socket, and return when we got it
3268 BufferedCommandStruct *bcs;
3269
3270 #ifdef _RAKNET_THREADSAFE
3271 bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
3272 bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
3273 bcs->systemIdentifier=UNASSIGNED_SYSTEM_ADDRESS;
3274 bcs->data=0;
3275 bufferedCommands.Push(bcs);
3276 #else
3277 bcs=bufferedCommands.WriteLock();
3278 bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
3279 bcs->systemIdentifier=UNASSIGNED_SYSTEM_ADDRESS;
3280 bcs->data=0;
3281 bufferedCommands.WriteUnlock();
3282 #endif
3283
3284 // Block up to one second to get the socket, although it should actually take virtually no time
3285 SocketQueryOutput *sqo;
3286 RakNetTime stopWaiting = RakNet::GetTime()+1000;
3287 RakNetSmartPtr<RakNetSocket> output;
3288 while (RakNet::GetTime() < stopWaiting)
3289 {
3290 if (isMainLoopThreadActive==false)
3291 return;
3292
3293 RakSleep(0);
3294
3295 #ifdef _RAKNET_THREADSAFE
3296 sqo = socketQueryOutput.Pop();
3297 if (sqo)
3298 {
3299 sockets=sqo->sockets;
3300 sqo->sockets.Clear(false, __FILE__, __LINE__);
3301 socketQueryOutput.Deallocate(sqo, __FILE__,__LINE__);
3302 return;
3303 }
3304 #else
3305 sqo = socketQueryOutput.ReadLock();
3306 if (sqo)
3307 {
3308 sockets=sqo->sockets;
3309 sqo->sockets.Clear(false, __FILE__, __LINE__);
3310 socketQueryOutput.ReadUnlock();
3311 return;
3312 }
3313 #endif
3314 }
3315 return;
3316 }
3317 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3318 // Adds simulated ping and packet loss to the outgoing data flow.
3319 // 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.
3320 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ApplyNetworkSimulator(float packetloss,unsigned short minExtraPing,unsigned short extraPingVariance)3321 void RakPeer::ApplyNetworkSimulator( float packetloss, unsigned short minExtraPing, unsigned short extraPingVariance)
3322 {
3323 #ifdef _DEBUG
3324 if (remoteSystemList)
3325 {
3326 unsigned short i;
3327 for (i=0; i < maximumNumberOfPeers; i++)
3328 //for (i=0; i < remoteSystemListSize; i++)
3329 remoteSystemList[i].reliabilityLayer.ApplyNetworkSimulator(packetloss, minExtraPing, extraPingVariance);
3330 }
3331
3332 _packetloss=packetloss;
3333 _minExtraPing=minExtraPing;
3334 _extraPingVariance=extraPingVariance;
3335 #endif
3336 }
3337
3338 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3339
SetPerConnectionOutgoingBandwidthLimit(unsigned maxBitsPerSecond)3340 void RakPeer::SetPerConnectionOutgoingBandwidthLimit( unsigned maxBitsPerSecond )
3341 {
3342 maxOutgoingBPS=maxBitsPerSecond;
3343 }
3344
3345 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3346 // Returns if you previously called ApplyNetworkSimulator
3347 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsNetworkSimulatorActive(void)3348 bool RakPeer::IsNetworkSimulatorActive( void )
3349 {
3350 #ifdef _DEBUG
3351 return _packetloss>0 || _minExtraPing>0 || _extraPingVariance>0;
3352 #else
3353 return false;
3354 #endif
3355 }
3356 /*
3357 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3358 // Have RakNet use a socket you created yourself
3359 // The socket should not be in use - it is up to you to either shutdown or close the connections using it. Otherwise existing connections on that socket will eventually disconnect
3360 // This socket will be forgotten after calling Shutdown(), so rebind again if you need to.
3361 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3362 void RakPeer::UseUserSocket( int socket, bool haveRakNetCloseSocket, unsigned connectionSocketIndex)
3363 {
3364 BufferedCommandStruct *bcs;
3365 #ifdef _RAKNET_THREADSAFE
3366 rakPeerMutexes[bufferedCommands_Mutex].Lock();
3367 #endif
3368 bcs=bufferedCommands.WriteLock();
3369 bcs->command=BufferedCommandStruct::BCS_USE_USER_SOCKET;
3370 bcs->data=0;
3371 bcs->socket=socket;
3372 bcs->haveRakNetCloseSocket=haveRakNetCloseSocket;
3373 bcs->connectionSocketIndex=connectionSocketIndex;
3374 bufferedCommands.WriteUnlock();
3375 #ifdef _RAKNET_THREADSAFE
3376 rakPeerMutexes[bufferedCommands_Mutex].Unlock();
3377 #endif
3378 }
3379
3380 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3381 // Have RakNet recreate a socket using a different port.
3382 // The socket should not be in use - it is up to you to either shutdown or close the connections using it. Otherwise existing connections on that socket will eventually disconnect
3383 // \param[in] connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on.
3384 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3385 void RakPeer::RebindSocketAddress(unsigned connectionSocketIndex, SocketDescriptor &sd)
3386 {
3387 BufferedCommandStruct *bcs;
3388 #ifdef _RAKNET_THREADSAFE
3389 rakPeerMutexes[bufferedCommands_Mutex].Lock();
3390 #endif
3391 bcs=bufferedCommands.WriteLock();
3392 bcs->command=BufferedCommandStruct::BCS_REBIND_SOCKET_ADDRESS;
3393 bcs->data=(char*) rakMalloc_Ex(sizeof(sd.hostAddress), __FILE__, __LINE__);
3394 memcpy(bcs->data, sd.hostAddress, sizeof(sd.hostAddress));
3395 bcs->port=sd.port;
3396 bcs->connectionSocketIndex=connectionSocketIndex;
3397 bcs->socketType=sd.socketType;
3398 bufferedCommands.WriteUnlock();
3399 #ifdef _RAKNET_THREADSAFE
3400 rakPeerMutexes[bufferedCommands_Mutex].Unlock();
3401 #endif
3402 }
3403 */
3404
3405
3406 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3407 // For internal use
3408 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRPCString(const char * data,const BitSize_t bitSize,const SystemAddress systemAddress)3409 char *RakPeer::GetRPCString( const char *data, const BitSize_t bitSize, const SystemAddress systemAddress)
3410 {
3411 bool nameIsEncoded=false;
3412 static char uniqueIdentifier[256];
3413 RPCIndex rpcIndex;
3414 RPCMap *_rpcMap;
3415 RakNet::BitStream rpcDecode((unsigned char*) data, BITS_TO_BYTES(bitSize), false);
3416 rpcDecode.IgnoreBits(8);
3417 if (data[0]==ID_TIMESTAMP)
3418 rpcDecode.IgnoreBits(sizeof(unsigned char)+sizeof(RakNetTime));
3419 rpcDecode.Read(nameIsEncoded);
3420 if (nameIsEncoded)
3421 {
3422 stringCompressor->DecodeString((char*)uniqueIdentifier, 256, &rpcDecode);
3423 }
3424 else
3425 {
3426 rpcDecode.ReadCompressed( rpcIndex );
3427 RPCNode *rpcNode;
3428
3429 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
3430 _rpcMap=&rpcMap;
3431 else
3432 {
3433 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(systemAddress, false, true);
3434 if (rss)
3435 _rpcMap=&(rss->rpcMap);
3436 else
3437 _rpcMap=0;
3438 }
3439
3440 if (_rpcMap)
3441 rpcNode = _rpcMap->GetNodeFromIndex(rpcIndex);
3442 else
3443 rpcNode=0;
3444
3445 if (_rpcMap && rpcNode)
3446 strcpy((char*)uniqueIdentifier, rpcNode->uniqueIdentifier);
3447 else
3448 strcpy((char*)uniqueIdentifier, "[UNKNOWN]");
3449 }
3450
3451 return uniqueIdentifier;
3452 }
3453
3454 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
WriteOutOfBandHeader(RakNet::BitStream * bitStream)3455 void RakPeer::WriteOutOfBandHeader(RakNet::BitStream *bitStream)
3456 {
3457 bitStream->Write((MessageID)ID_OUT_OF_BAND_INTERNAL);
3458 bitStream->Write(myGuid);
3459 bitStream->WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
3460 }
3461 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetUserUpdateThread(void (* _userUpdateThreadPtr)(RakPeerInterface *,void *),void * _userUpdateThreadData)3462 void RakPeer::SetUserUpdateThread(void (*_userUpdateThreadPtr)(RakPeerInterface *, void *), void *_userUpdateThreadData)
3463 {
3464 userUpdateThreadPtr=_userUpdateThreadPtr;
3465 userUpdateThreadData=_userUpdateThreadData;
3466 }
3467 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendOutOfBand(const char * host,unsigned short remotePort,const char * data,BitSize_t dataLength,unsigned connectionSocketIndex)3468 bool RakPeer::SendOutOfBand(const char *host, unsigned short remotePort, const char *data, BitSize_t dataLength, unsigned connectionSocketIndex )
3469 {
3470 if ( IsActive() == false )
3471 return false;
3472
3473 if (host==0 || host[0]==0)
3474 return false;
3475
3476 // If this assert hits then Startup wasn't called or the call failed.
3477 RakAssert(connectionSocketIndex < socketList.Size());
3478
3479 // This is a security measure. Don't send data longer than this value
3480 RakAssert(dataLength <= MAX_OFFLINE_DATA_LENGTH);
3481
3482 if ( NonNumericHostString( host ) )
3483 {
3484 host = ( char* ) SocketLayer::DomainNameToIP( host );
3485
3486 if (host==0)
3487 return false;
3488 }
3489
3490 if (host==0)
3491 return false;
3492
3493 SystemAddress systemAddress;
3494 systemAddress.SetBinaryAddress(host);
3495 systemAddress.port=remotePort;
3496
3497 // 34 bytes
3498 RakNet::BitStream bitStream;
3499 WriteOutOfBandHeader(&bitStream);
3500
3501 if (dataLength>0)
3502 {
3503 bitStream.Write(data, dataLength);
3504 }
3505
3506 if (IsActive())
3507 {
3508 BufferedCommandStruct *bcs;
3509 #ifdef _RAKNET_THREADSAFE
3510 bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
3511 bcs->command=BufferedCommandStruct::BCS_SEND_OUT_OF_BAND;
3512 bcs->connectionSocketIndex=connectionSocketIndex;
3513 bcs->data=(char*) rakMalloc_Ex(bitStream.GetNumberOfBytesUsed(), __FILE__, __LINE__);
3514 bcs->numberOfBitsToSend=bitStream.GetNumberOfBitsUsed();
3515 memcpy(bcs->data, bitStream.GetData(), bitStream.GetNumberOfBytesUsed());
3516 bcs->systemIdentifier.systemAddress.SetBinaryAddress(host);
3517 bcs->systemIdentifier.systemAddress.port=remotePort;
3518 bufferedCommands.Push(bcs);
3519 #else
3520 bcs=bufferedCommands.WriteLock();
3521 bcs->command=BufferedCommandStruct::BCS_SEND_OUT_OF_BAND;
3522 bcs->connectionSocketIndex=connectionSocketIndex;
3523 bcs->data=(char*) rakMalloc_Ex(bitStream.GetNumberOfBytesUsed(), __FILE__, __LINE__);
3524 bcs->numberOfBitsToSend=bitStream.GetNumberOfBitsUsed();
3525 memcpy(bcs->data, bitStream.GetData(), bitStream.GetNumberOfBytesUsed());
3526 bcs->systemIdentifier.systemAddress.SetBinaryAddress(host);
3527 bcs->systemIdentifier.systemAddress.port=remotePort;
3528 bufferedCommands.WriteUnlock();
3529 #endif
3530 }
3531 else
3532 {
3533 unsigned i;
3534 for (i=0; i < messageHandlerList.Size(); i++)
3535 messageHandlerList[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
3536 unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
3537 SocketLayer::SendTo( socketList[realIndex]->s, (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), ( char* ) host, remotePort, socketList[realIndex]->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
3538 }
3539
3540 return true;
3541 }
3542
3543 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetStatistics(const SystemAddress systemAddress,RakNetStatistics * rns)3544 RakNetStatistics * const RakPeer::GetStatistics( const SystemAddress systemAddress, RakNetStatistics *rns )
3545 {
3546 static RakNetStatistics staticStatistics;
3547 RakNetStatistics *systemStats;
3548 if (rns==0)
3549 systemStats=&staticStatistics;
3550 else
3551 systemStats=rns;
3552
3553 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
3554 {
3555 bool firstWrite=false;
3556 // Return a crude sum
3557 for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
3558 {
3559 if (remoteSystemList[ i ].isActive)
3560 {
3561 RakNetStatistics rnsTemp;
3562 remoteSystemList[ i ].reliabilityLayer.GetStatistics(&rnsTemp);
3563
3564 if (firstWrite==false)
3565 {
3566 memcpy(systemStats, &rnsTemp, sizeof(RakNetStatistics));
3567 firstWrite=true;
3568 }
3569 else
3570 (*systemStats)+=rnsTemp;
3571 }
3572 }
3573 return systemStats;
3574 }
3575 else
3576 {
3577 RemoteSystemStruct * rss;
3578 rss = GetRemoteSystemFromSystemAddress( systemAddress, false, false );
3579 if ( rss && endThreads==false )
3580 {
3581 rss->reliabilityLayer.GetStatistics(systemStats);
3582 return systemStats;
3583 }
3584 }
3585
3586 return 0;
3587 }
3588
3589 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetStatistics(const int index,RakNetStatistics * rns)3590 bool RakPeer::GetStatistics( const int index, RakNetStatistics *rns )
3591 {
3592 if (index < maximumNumberOfPeers && remoteSystemList[ index ].isActive)
3593 {
3594 remoteSystemList[ index ].reliabilityLayer.GetStatistics(rns);
3595 return true;
3596 }
3597 return false;
3598 }
3599 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetReceiveBufferSize(void)3600 unsigned int RakPeer::GetReceiveBufferSize(void)
3601 {
3602 unsigned int size;
3603 packetReturnMutex.Lock();
3604 size=packetReturnQueue.Size();
3605 packetReturnMutex.Unlock();
3606 return size;
3607 }
3608 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetIndexFromSystemAddress(const SystemAddress systemAddress,bool calledFromNetworkThread) const3609 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread ) const
3610 {
3611 unsigned i;
3612
3613 if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
3614 return -1;
3615
3616 if (systemAddress.systemIndex!=(SystemIndex)-1 && systemAddress.systemIndex < maximumNumberOfPeers && remoteSystemList[systemAddress.systemIndex].systemAddress==systemAddress && remoteSystemList[ systemAddress.systemIndex ].isActive)
3617 return systemAddress.systemIndex;
3618
3619 if (calledFromNetworkThread)
3620 {
3621 return GetRemoteSystemIndex(systemAddress);
3622 }
3623 else
3624 {
3625 // remoteSystemList in user and network thread
3626 for ( i = 0; i < maximumNumberOfPeers; i++ )
3627 if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].systemAddress == systemAddress )
3628 return i;
3629
3630 // If no active results found, try previously active results.
3631 for ( i = 0; i < maximumNumberOfPeers; i++ )
3632 if ( remoteSystemList[ i ].systemAddress == systemAddress )
3633 return i;
3634 }
3635
3636 return -1;
3637 }
3638 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetIndexFromGuid(const RakNetGUID guid)3639 int RakPeer::GetIndexFromGuid( const RakNetGUID guid )
3640 {
3641 unsigned i;
3642
3643 if ( guid == UNASSIGNED_RAKNET_GUID )
3644 return -1;
3645
3646 if (guid.systemIndex!=(SystemIndex)-1 && guid.systemIndex < maximumNumberOfPeers && remoteSystemList[guid.systemIndex].guid==guid && remoteSystemList[ guid.systemIndex ].isActive)
3647 return guid.systemIndex;
3648
3649 // remoteSystemList in user and network thread
3650 for ( i = 0; i < maximumNumberOfPeers; i++ )
3651 if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].guid == guid )
3652 return i;
3653
3654 // If no active results found, try previously active results.
3655 for ( i = 0; i < maximumNumberOfPeers; i++ )
3656 if ( remoteSystemList[ i ].guid == guid )
3657 return i;
3658
3659 return -1;
3660 }
3661 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendConnectionRequest(const char * host,unsigned short remotePort,const char * passwordData,int passwordDataLength,unsigned connectionSocketIndex,unsigned int extraData,unsigned sendConnectionAttemptCount,unsigned timeBetweenSendConnectionAttemptsMS,RakNetTime timeoutTime)3662 bool RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime )
3663 {
3664 RakAssert(passwordDataLength <= 256);
3665 RakAssert(remotePort!=0);
3666 SystemAddress systemAddress;
3667 systemAddress.SetBinaryAddress(host);
3668 systemAddress.port=remotePort;
3669
3670 // Already connected?
3671 if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
3672 return false;
3673
3674 //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), __FILE__, __LINE__);
3675 RequestedConnectionStruct *rcs = RakNet::OP_NEW<RequestedConnectionStruct>(__FILE__,__LINE__);
3676
3677 rcs->systemAddress=systemAddress;
3678 rcs->nextRequestTime=RakNet::GetTime();
3679 rcs->requestsMade=0;
3680 rcs->data=0;
3681 rcs->extraData=extraData;
3682 rcs->socketIndex=connectionSocketIndex;
3683 rcs->actionToTake=RequestedConnectionStruct::CONNECT;
3684 rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
3685 rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
3686 memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
3687 rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
3688 rcs->timeoutTime=timeoutTime;
3689
3690 // Return false if already pending, else push on queue
3691 unsigned int i=0;
3692 requestedConnectionQueueMutex.Lock();
3693 for (; i < requestedConnectionQueue.Size(); i++)
3694 {
3695 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
3696 {
3697 requestedConnectionQueueMutex.Unlock();
3698 RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
3699 return false;
3700 }
3701 }
3702 requestedConnectionQueue.Push(rcs, __FILE__, __LINE__ );
3703 requestedConnectionQueueMutex.Unlock();
3704
3705 return true;
3706 }
SendConnectionRequest(const char * host,unsigned short remotePort,const char * passwordData,int passwordDataLength,unsigned connectionSocketIndex,unsigned int extraData,unsigned sendConnectionAttemptCount,unsigned timeBetweenSendConnectionAttemptsMS,RakNetTime timeoutTime,RakNetSmartPtr<RakNetSocket> socket)3707 bool RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime, RakNetSmartPtr<RakNetSocket> socket )
3708 {
3709 RakAssert(passwordDataLength <= 256);
3710 SystemAddress systemAddress;
3711 systemAddress.SetBinaryAddress(host);
3712 systemAddress.port=remotePort;
3713
3714 // Already connected?
3715 if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
3716 return false;
3717
3718 //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), __FILE__, __LINE__);
3719 RequestedConnectionStruct *rcs = RakNet::OP_NEW<RequestedConnectionStruct>(__FILE__,__LINE__);
3720
3721 rcs->systemAddress=systemAddress;
3722 rcs->nextRequestTime=RakNet::GetTime();
3723 rcs->requestsMade=0;
3724 rcs->data=0;
3725 rcs->extraData=extraData;
3726 rcs->socketIndex=connectionSocketIndex;
3727 rcs->actionToTake=RequestedConnectionStruct::CONNECT;
3728 rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
3729 rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
3730 memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
3731 rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
3732 rcs->timeoutTime=timeoutTime;
3733 rcs->socket=socket;
3734
3735 // Return false if already pending, else push on queue
3736 unsigned int i=0;
3737 requestedConnectionQueueMutex.Lock();
3738 for (; i < requestedConnectionQueue.Size(); i++)
3739 {
3740 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
3741 {
3742 requestedConnectionQueueMutex.Unlock();
3743 RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
3744 return false;
3745 }
3746 }
3747 requestedConnectionQueue.Push(rcs, __FILE__, __LINE__ );
3748 requestedConnectionQueueMutex.Unlock();
3749
3750 return true;
3751 }
3752 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ValidateRemoteSystemLookup(void) const3753 void RakPeer::ValidateRemoteSystemLookup(void) const
3754 {
3755 }
3756 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRemoteSystem(const AddressOrGUID systemIdentifier,bool calledFromNetworkThread,bool onlyActive) const3757 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystem( const AddressOrGUID systemIdentifier, bool calledFromNetworkThread, bool onlyActive ) const
3758 {
3759 if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
3760 return GetRemoteSystemFromGUID(systemIdentifier.rakNetGuid, onlyActive);
3761 else
3762 return GetRemoteSystemFromSystemAddress(systemIdentifier.systemAddress, calledFromNetworkThread, onlyActive);
3763 }
3764 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRemoteSystemFromSystemAddress(const SystemAddress systemAddress,bool calledFromNetworkThread,bool onlyActive) const3765 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread, bool onlyActive ) const
3766 {
3767 unsigned i;
3768
3769 if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
3770 return 0;
3771
3772 if (calledFromNetworkThread)
3773 {
3774 unsigned int index = GetRemoteSystemIndex(systemAddress);
3775 if (index!=(unsigned int) -1)
3776 {
3777 if (onlyActive==false || remoteSystemList[ index ].isActive==true )
3778 {
3779 RakAssert(remoteSystemList[index].systemAddress==systemAddress);
3780 return remoteSystemList + index;
3781 }
3782 }
3783 }
3784 else
3785 {
3786 int deadConnectionIndex=-1;
3787
3788 // Active connections take priority. But if there are no active connections, return the first systemAddress match found
3789 for ( i = 0; i < maximumNumberOfPeers; i++ )
3790 {
3791 if (remoteSystemList[ i ].systemAddress == systemAddress)
3792 {
3793 if ( remoteSystemList[ i ].isActive )
3794 return remoteSystemList + i;
3795 else if (deadConnectionIndex==-1)
3796 deadConnectionIndex=i;
3797 }
3798 }
3799
3800 if (deadConnectionIndex!=-1 && onlyActive==false)
3801 return remoteSystemList + deadConnectionIndex;
3802 }
3803
3804 return 0;
3805 }
3806 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRemoteSystemFromGUID(const RakNetGUID guid,bool onlyActive) const3807 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromGUID( const RakNetGUID guid, bool onlyActive ) const
3808 {
3809 if (guid==UNASSIGNED_RAKNET_GUID)
3810 return 0;
3811
3812 unsigned i;
3813 for ( i = 0; i < maximumNumberOfPeers; i++ )
3814 {
3815 if (remoteSystemList[ i ].guid == guid && (onlyActive==false || remoteSystemList[ i ].isActive))
3816 {
3817 return remoteSystemList + i;
3818 }
3819 }
3820 return 0;
3821 }
3822 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ParseConnectionRequestPacket(RakPeer::RemoteSystemStruct * remoteSystem,SystemAddress systemAddress,const char * data,int byteSize)3823 void RakPeer::ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, SystemAddress systemAddress, const char *data, int byteSize )
3824 {
3825 RakNet::BitStream bs((unsigned char*) data,byteSize,false);
3826 bs.IgnoreBytes(sizeof(MessageID));
3827 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
3828 RakNetGUID guid;
3829 bs.Read(guid);
3830 RakNetTime incomingTimestamp;
3831 bs.Read(incomingTimestamp);
3832
3833 // If we are full tell the sender.
3834 // Not needed
3835 if ( 0 ) //!AllowIncomingConnections() )
3836 {
3837 RakNet::BitStream bs;
3838 bs.Write((MessageID)ID_NO_FREE_INCOMING_CONNECTIONS);
3839 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
3840 bs.Write(GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
3841 SendImmediate((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0);
3842 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
3843 }
3844 else
3845 {
3846 const char *password = data + sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID) + sizeof(RakNetTime);
3847 int passwordLength = byteSize - (int) (sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID) + sizeof(RakNetTime));
3848
3849 if ( incomingPasswordLength == passwordLength &&
3850 memcmp( password, incomingPassword, incomingPasswordLength ) == 0 )
3851 {
3852 remoteSystem->connectMode=RemoteSystemStruct::HANDLING_CONNECTION_REQUEST;
3853
3854
3855 char str1[64];
3856 systemAddress.ToString(false, str1);
3857 if ( usingSecurity == false ||
3858 IsInSecurityExceptionList(str1))
3859
3860 {
3861 #ifdef _TEST_AES
3862 unsigned char AESKey[ 16 ];
3863 // Save the AES key
3864 for ( i = 0; i < 16; i++ )
3865 AESKey[ i ] = i;
3866
3867 OnConnectionRequest( remoteSystem, AESKey, true );
3868 #else
3869 // Connect this player assuming we have open slots
3870 OnConnectionRequest( remoteSystem, 0, false, incomingTimestamp );
3871 #endif
3872 }
3873
3874 else
3875 SecuredConnectionResponse( systemAddress );
3876
3877 }
3878 else
3879 {
3880 // This one we only send once since we don't care if it arrives.
3881 RakNet::BitStream bitStream;
3882 bitStream.Write((MessageID)ID_INVALID_PASSWORD);
3883 bitStream.Write(GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
3884 SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0);
3885 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
3886 }
3887 }
3888 }
3889 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OnConnectionRequest(RakPeer::RemoteSystemStruct * remoteSystem,unsigned char * AESKey,bool setAESKey,RakNetTime incomingTimestamp)3890 void RakPeer::OnConnectionRequest( RakPeer::RemoteSystemStruct *remoteSystem, unsigned char *AESKey, bool setAESKey, RakNetTime incomingTimestamp )
3891 {
3892 // Already handled by caller
3893 //if ( AllowIncomingConnections() )
3894 {
3895 SendConnectionRequestAccepted(remoteSystem, incomingTimestamp);
3896
3897 // Don't set secure connections immediately because we need the ack from the remote system to know ID_CONNECTION_REQUEST_ACCEPTED
3898 // As soon as a 16 byte packet arrives, we will turn on AES. This works because all encrypted packets are multiples of 16 and the
3899 // packets I happen to be sending are less than 16 bytes
3900 remoteSystem->setAESKey=setAESKey;
3901 if ( setAESKey )
3902 {
3903 memcpy(remoteSystem->AESKey, AESKey, 16);
3904 remoteSystem->connectMode=RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET;
3905 }
3906 }
3907 /*
3908 else
3909 {
3910 unsigned char c = ID_NO_FREE_INCOMING_CONNECTIONS;
3911 //SocketLayer::SendTo( connectionSocket, ( char* ) & c, sizeof( char ), systemAddress.binaryAddress, systemAddress.port );
3912
3913 SendImmediate((char*)&c, sizeof(c)*8, IMMEDIATE_PRIORITY, RELIABLE, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS());
3914 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
3915 }
3916 */
3917 }
3918 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendConnectionRequestAccepted(RakPeer::RemoteSystemStruct * remoteSystem,RakNetTime incomingTimestamp)3919 void RakPeer::SendConnectionRequestAccepted(RakPeer::RemoteSystemStruct *remoteSystem, RakNetTime incomingTimestamp)
3920 {
3921 RakNet::BitStream bitStream;
3922 bitStream.Write((MessageID)ID_CONNECTION_REQUEST_ACCEPTED);
3923 bitStream.Write(remoteSystem->systemAddress);
3924 SystemIndex systemIndex = (SystemIndex) GetIndexFromSystemAddress( remoteSystem->systemAddress, true );
3925 RakAssert(systemIndex!=65535);
3926 bitStream.Write(systemIndex);
3927 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
3928 bitStream.Write(mySystemAddress[i]);
3929 bitStream.Write(incomingTimestamp);
3930 bitStream.Write(RakNet::GetTime());
3931
3932 SendImmediate((char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS(), 0);
3933 }
3934
3935 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NotifyAndFlagForShutdown(const SystemAddress systemAddress,bool performImmediate,unsigned char orderingChannel,PacketPriority disconnectionNotificationPriority)3936 void RakPeer::NotifyAndFlagForShutdown( const SystemAddress systemAddress, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
3937 {
3938 RakNet::BitStream temp( sizeof(unsigned char) );
3939 temp.Write( (MessageID)ID_DISCONNECTION_NOTIFICATION );
3940 if (performImmediate)
3941 {
3942 SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, false, RakNet::GetTimeNS(), 0);
3943 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(systemAddress, true, true);
3944 rss->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
3945 }
3946 else
3947 {
3948 SendBuffered((const char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, RemoteSystemStruct::DISCONNECT_ASAP, 0);
3949 }
3950 }
3951 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetNumberOfRemoteInitiatedConnections(void) const3952 unsigned short RakPeer::GetNumberOfRemoteInitiatedConnections( void ) const
3953 {
3954 unsigned short i, numberOfIncomingConnections;
3955
3956 if ( remoteSystemList == 0 || endThreads == true )
3957 return 0;
3958
3959 numberOfIncomingConnections = 0;
3960
3961 // remoteSystemList in network thread
3962 for ( i = 0; i < maximumNumberOfPeers; i++ )
3963 //for ( i = 0; i < remoteSystemListSize; i++ )
3964 {
3965 if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].weInitiatedTheConnection == false && remoteSystemList[i].connectMode==RemoteSystemStruct::CONNECTED)
3966 numberOfIncomingConnections++;
3967 }
3968
3969 return numberOfIncomingConnections;
3970 }
3971
3972 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AssignSystemAddressToRemoteSystemList(const SystemAddress systemAddress,RemoteSystemStruct::ConnectMode connectionMode,RakNetSmartPtr<RakNetSocket> incomingRakNetSocket,bool * thisIPConnectedRecently,SystemAddress bindingAddress,int incomingMTU,RakNetGUID guid)3973 RakPeer::RemoteSystemStruct * RakPeer::AssignSystemAddressToRemoteSystemList( const SystemAddress systemAddress, RemoteSystemStruct::ConnectMode connectionMode, RakNetSmartPtr<RakNetSocket> incomingRakNetSocket, bool *thisIPConnectedRecently, SystemAddress bindingAddress, int incomingMTU, RakNetGUID guid )
3974 {
3975 RemoteSystemStruct * remoteSystem;
3976 unsigned i,j,assignedIndex;
3977 RakNetTime time = RakNet::GetTime();
3978 #ifdef _DEBUG
3979 RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
3980 #endif
3981
3982 if (limitConnectionFrequencyFromTheSameIP)
3983 {
3984 if (IsLoopbackAddress(systemAddress,false)==false)
3985 {
3986 for ( i = 0; i < maximumNumberOfPeers; i++ )
3987 {
3988 if ( remoteSystemList[ i ].isActive==true &&
3989 remoteSystemList[ i ].systemAddress.binaryAddress==systemAddress.binaryAddress &&
3990 time >= remoteSystemList[ i ].connectionTime &&
3991 time - remoteSystemList[ i ].connectionTime < 100
3992 )
3993 {
3994 // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
3995 // Ignore connection attempts if this IP address connected within the last 100 milliseconds
3996 *thisIPConnectedRecently=true;
3997 ValidateRemoteSystemLookup();
3998 return 0;
3999 }
4000 }
4001 }
4002 }
4003
4004 // Don't use a different port than what we received on
4005 bindingAddress.port=incomingRakNetSocket->boundAddress.port;
4006
4007 *thisIPConnectedRecently=false;
4008 for ( assignedIndex = 0; assignedIndex < maximumNumberOfPeers; assignedIndex++ )
4009 {
4010 if ( remoteSystemList[ assignedIndex ].isActive==false )
4011 {
4012 remoteSystem=remoteSystemList+assignedIndex;
4013 remoteSystem->rpcMap.Clear();
4014 ReferenceRemoteSystem(systemAddress, assignedIndex);
4015 remoteSystem->MTUSize=defaultMTUSize;
4016 remoteSystem->guid=guid;
4017 remoteSystem->isActive = true; // This one line causes future incoming packets to go through the reliability layer
4018 // Reserve this reliability layer for ourselves.
4019 if (incomingMTU > remoteSystem->MTUSize)
4020 remoteSystem->MTUSize=incomingMTU;
4021 remoteSystem->reliabilityLayer.Reset(true, remoteSystem->MTUSize);
4022 remoteSystem->reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval);
4023 remoteSystem->reliabilityLayer.SetUnreliableTimeout(unreliableTimeout);
4024 remoteSystem->reliabilityLayer.SetTimeoutTime(defaultTimeoutTime);
4025 remoteSystem->reliabilityLayer.SetEncryptionKey( 0 );
4026 if (incomingRakNetSocket->boundAddress==bindingAddress)
4027 {
4028 remoteSystem->rakNetSocket=incomingRakNetSocket;
4029 }
4030 else
4031 {
4032 char str[256];
4033 bindingAddress.ToString(true,str);
4034 // See if this is an internal IP address.
4035 // If so, force binding on it so we reply on the same IP address as they sent to.
4036 unsigned int ipListIndex, foundIndex=(unsigned int)-1;
4037
4038 for (ipListIndex=0; ipListIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipListIndex++)
4039 {
4040 if (ipList[ipListIndex][0]==0)
4041 break;
4042 if (bindingAddress.binaryAddress==binaryAddresses[ipListIndex])
4043 {
4044 foundIndex=ipListIndex;
4045 break;
4046 }
4047 }
4048
4049 // 06/26/09 Unconfirmed report that Vista firewall blocks the reply if we force a binding
4050 // For now use the incoming socket only
4051 // Originally this code was to force a machine with multiple IP addresses to reply back on the IP
4052 // that the datagram came in on
4053 if (1 || foundIndex==(unsigned int)-1)
4054 {
4055 // Must not be an internal LAN address. Just use whatever socket it came in on
4056 remoteSystem->rakNetSocket=incomingRakNetSocket;
4057 }
4058 else
4059 {
4060 // Force binding
4061 unsigned int socketListIndex;
4062 for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
4063 {
4064 if (socketList[socketListIndex]->boundAddress==bindingAddress)
4065 {
4066 // Force binding with existing socket
4067 remoteSystem->rakNetSocket=socketList[socketListIndex];
4068 break;
4069 }
4070 }
4071
4072 if (socketListIndex==socketList.Size())
4073 {
4074 // Force binding with new socket
4075 RakNetSmartPtr<RakNetSocket> rns(RakNet::OP_NEW<RakNetSocket>(__FILE__,__LINE__));
4076 if (incomingRakNetSocket->remotePortRakNetWasStartedOn_PS3==0)
4077 rns->s = (unsigned int) SocketLayer::CreateBoundSocket( bindingAddress.port, true, ipList[foundIndex], 0 );
4078 else
4079 rns->s = (unsigned int) SocketLayer::CreateBoundSocket_PS3Lobby( bindingAddress.port, true, ipList[foundIndex] );
4080 if ((SOCKET)rns->s==(SOCKET)-1)
4081 {
4082 // Can't bind. Just use whatever socket it came in on
4083 remoteSystem->rakNetSocket=incomingRakNetSocket;
4084 }
4085 else
4086 {
4087 rns->boundAddress=bindingAddress;
4088 rns->remotePortRakNetWasStartedOn_PS3=incomingRakNetSocket->remotePortRakNetWasStartedOn_PS3;
4089 rns->userConnectionSocketIndex=(unsigned int)-1;
4090 socketList.Push(rns, __FILE__, __LINE__ );
4091 remoteSystem->rakNetSocket=rns;
4092
4093 RakPeerAndIndex rpai;
4094 rpai.remotePortRakNetWasStartedOn_PS3=rns->remotePortRakNetWasStartedOn_PS3;
4095 rpai.s=rns->s;
4096 rpai.rakPeer=this;
4097 #ifdef _WIN32
4098 int highPriority=THREAD_PRIORITY_ABOVE_NORMAL;
4099 #else
4100 int highPriority=-10;
4101 #endif
4102
4103 //#if !defined(_XBOX) && !defined(X360)
4104 highPriority=0;
4105 //#endif
4106 isRecvFromLoopThreadActive=false;
4107 int errorCode = RakNet::RakThread::Create(RecvFromLoop, &rpai, highPriority);
4108 RakAssert(errorCode!=0);
4109 while ( isRecvFromLoopThreadActive == false )
4110 RakSleep(10);
4111
4112
4113 /*
4114 #if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
4115 if (threadSleepTimer>0)
4116 {
4117 rns->recvEvent=CreateEvent(0,FALSE,FALSE,0);
4118 WSAEventSelect(rns->s,rns->recvEvent,FD_READ);
4119 }
4120 #endif
4121 */
4122 }
4123 }
4124 }
4125 }
4126
4127 for ( j = 0; j < (unsigned) PING_TIMES_ARRAY_SIZE; j++ )
4128 {
4129 remoteSystem->pingAndClockDifferential[ j ].pingTime = 65535;
4130 remoteSystem->pingAndClockDifferential[ j ].clockDifferential = 0;
4131 }
4132
4133 remoteSystem->connectMode=connectionMode;
4134 remoteSystem->pingAndClockDifferentialWriteIndex = 0;
4135 remoteSystem->lowestPing = 65535;
4136 remoteSystem->nextPingTime = 0; // Ping immediately
4137 remoteSystem->weInitiatedTheConnection = false;
4138 remoteSystem->connectionTime = time;
4139 remoteSystem->myExternalSystemAddress = UNASSIGNED_SYSTEM_ADDRESS;
4140 remoteSystem->setAESKey=false;
4141 remoteSystem->lastReliableSend=time;
4142
4143 #ifdef _DEBUG
4144 int indexLoopupCheck=GetIndexFromSystemAddress( systemAddress, true );
4145 if (indexLoopupCheck!=assignedIndex)
4146 {
4147 RakAssert(indexLoopupCheck==assignedIndex);
4148 }
4149 #endif
4150
4151 return remoteSystem;
4152 }
4153 }
4154
4155 return 0;
4156 }
4157
4158 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4159 // Adjust the first four bytes (treated as unsigned int) of the pointer
4160 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ShiftIncomingTimestamp(unsigned char * data,SystemAddress systemAddress) const4161 void RakPeer::ShiftIncomingTimestamp( unsigned char *data, SystemAddress systemAddress ) const
4162 {
4163 #ifdef _DEBUG
4164 RakAssert( IsActive() );
4165 RakAssert( data );
4166 #endif
4167
4168 RakNet::BitStream timeBS( data, sizeof(RakNetTime), false);
4169 RakNetTime encodedTimestamp;
4170 timeBS.Read(encodedTimestamp);
4171
4172 encodedTimestamp = encodedTimestamp - GetBestClockDifferential( systemAddress );
4173 timeBS.SetWriteOffset(0);
4174 timeBS.Write(encodedTimestamp);
4175 }
4176
4177 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4178 // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
GetBestClockDifferential(const SystemAddress systemAddress) const4179 RakNetTime RakPeer::GetBestClockDifferential( const SystemAddress systemAddress ) const
4180 {
4181 int counter, lowestPingSoFar;
4182 RakNetTime clockDifferential;
4183 RemoteSystemStruct *remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, true, true );
4184
4185 if ( remoteSystem == 0 )
4186 return 0;
4187
4188 lowestPingSoFar = 65535;
4189
4190 clockDifferential = 0;
4191
4192 for ( counter = 0; counter < PING_TIMES_ARRAY_SIZE; counter++ )
4193 {
4194 if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime == 65535 )
4195 break;
4196
4197 if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime < lowestPingSoFar )
4198 {
4199 clockDifferential = remoteSystem->pingAndClockDifferential[ counter ].clockDifferential;
4200 lowestPingSoFar = remoteSystem->pingAndClockDifferential[ counter ].pingTime;
4201 }
4202 }
4203
4204 return clockDifferential;
4205 }
4206 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RemoteSystemLookupHashIndex(SystemAddress sa) const4207 unsigned int RakPeer::RemoteSystemLookupHashIndex(SystemAddress sa) const
4208 {
4209 unsigned int lastHash = SuperFastHashIncremental ((const char*) & sa.binaryAddress, 4, 4 );
4210 lastHash = SuperFastHashIncremental ((const char*) & sa.port, 2, lastHash );
4211 return lastHash % ((unsigned int) maximumNumberOfPeers * REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE);
4212 }
4213 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ReferenceRemoteSystem(SystemAddress sa,unsigned int remoteSystemListIndex)4214 void RakPeer::ReferenceRemoteSystem(SystemAddress sa, unsigned int remoteSystemListIndex)
4215 {
4216 // #ifdef _DEBUG
4217 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
4218 // {
4219 // if (remoteSystemList[remoteSystemIndex].isActive )
4220 // {
4221 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
4222 // RakAssert(hashIndex==remoteSystemIndex);
4223 // }
4224 // }
4225 // #endif
4226
4227
4228 SystemAddress oldAddress = remoteSystemList[remoteSystemListIndex].systemAddress;
4229 if (oldAddress!=UNASSIGNED_SYSTEM_ADDRESS)
4230 {
4231 // The system might be active if rerouting
4232 // RakAssert(remoteSystemList[remoteSystemListIndex].isActive==false);
4233
4234 // Remove the reference if the reference is pointing to this inactive system
4235 if (GetRemoteSystem(oldAddress)==&remoteSystemList[remoteSystemListIndex])
4236 DereferenceRemoteSystem(oldAddress);
4237 }
4238 DereferenceRemoteSystem(sa);
4239
4240 // #ifdef _DEBUG
4241 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
4242 // {
4243 // if (remoteSystemList[remoteSystemIndex].isActive )
4244 // {
4245 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
4246 // if (hashIndex!=remoteSystemIndex)
4247 // {
4248 // RakAssert(hashIndex==remoteSystemIndex);
4249 // }
4250 // }
4251 // }
4252 // #endif
4253
4254
4255 remoteSystemList[remoteSystemListIndex].systemAddress=sa;
4256
4257 unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
4258 RemoteSystemIndex *rsi;
4259 rsi = remoteSystemIndexPool.Allocate(__FILE__,__LINE__);
4260 if (remoteSystemLookup[hashIndex]==0)
4261 {
4262 rsi->next=0;
4263 rsi->index=remoteSystemListIndex;
4264 remoteSystemLookup[hashIndex]=rsi;
4265 }
4266 else
4267 {
4268 RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
4269 while (cur->next!=0)
4270 {
4271 cur=cur->next;
4272 }
4273
4274 rsi = remoteSystemIndexPool.Allocate(__FILE__,__LINE__);
4275 rsi->next=0;
4276 rsi->index=remoteSystemListIndex;
4277 cur->next=rsi;
4278 }
4279
4280 // #ifdef _DEBUG
4281 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
4282 // {
4283 // if (remoteSystemList[remoteSystemIndex].isActive )
4284 // {
4285 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
4286 // RakAssert(hashIndex==remoteSystemIndex);
4287 // }
4288 // }
4289 // #endif
4290
4291
4292 RakAssert(GetRemoteSystemIndex(sa)==remoteSystemListIndex);
4293 }
4294 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DereferenceRemoteSystem(SystemAddress sa)4295 void RakPeer::DereferenceRemoteSystem(SystemAddress sa)
4296 {
4297 unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
4298 RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
4299 RemoteSystemIndex *last = 0;
4300 while (cur!=0)
4301 {
4302 if (remoteSystemList[cur->index].systemAddress==sa)
4303 {
4304 if (last==0)
4305 {
4306 remoteSystemLookup[hashIndex]=cur->next;
4307 }
4308 else
4309 {
4310 last->next=cur->next;
4311 }
4312 remoteSystemIndexPool.Release(cur,__FILE__,__LINE__);
4313 break;
4314 }
4315 last=cur;
4316 cur=cur->next;
4317 }
4318 }
4319 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRemoteSystemIndex(SystemAddress sa) const4320 unsigned int RakPeer::GetRemoteSystemIndex(SystemAddress sa) const
4321 {
4322 unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
4323 RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
4324 while (cur!=0)
4325 {
4326 if (remoteSystemList[cur->index].systemAddress==sa)
4327 return cur->index;
4328 cur=cur->next;
4329 }
4330 return (unsigned int) -1;
4331 }
4332 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRemoteSystem(SystemAddress sa) const4333 RakPeer::RemoteSystemStruct* RakPeer::GetRemoteSystem(SystemAddress sa) const
4334 {
4335 unsigned int remoteSystemIndex = GetRemoteSystemIndex(sa);
4336 if (remoteSystemIndex==(unsigned int)-1)
4337 return 0;
4338 return remoteSystemList + remoteSystemIndex;
4339 }
4340 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearRemoteSystemLookup(void)4341 void RakPeer::ClearRemoteSystemLookup(void)
4342 {
4343 remoteSystemIndexPool.Clear(__FILE__,__LINE__);
4344 RakNet::OP_DELETE_ARRAY(remoteSystemLookup,__FILE__,__LINE__);
4345 remoteSystemLookup=0;
4346 }
4347 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4348 /*
4349 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4350 unsigned int RakPeer::LookupIndexUsingHashIndex(SystemAddress sa) const
4351 {
4352 unsigned int scanCount=0;
4353 unsigned int index = RemoteSystemLookupHashIndex(sa);
4354 if (remoteSystemLookup[index].index==(unsigned int)-1)
4355 return (unsigned int) -1;
4356 while (remoteSystemList[remoteSystemLookup[index].index].systemAddress!=sa)
4357 {
4358 if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
4359 index=0;
4360 if (++scanCount>(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
4361 return (unsigned int) -1;
4362 if (remoteSystemLookup[index].index==-1)
4363 return (unsigned int) -1;
4364 }
4365 return index;
4366 }
4367 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4368 unsigned int RakPeer::RemoteSystemListIndexUsingHashIndex(SystemAddress sa) const
4369 {
4370 unsigned int index = LookupIndexUsingHashIndex(sa);
4371 if (index!=(unsigned int) -1)
4372 {
4373 return remoteSystemLookup[index].index;
4374 }
4375 return (unsigned int) -1;
4376 }
4377 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4378 unsigned int RakPeer::FirstFreeRemoteSystemLookupIndex(SystemAddress sa) const
4379 {
4380 // unsigned int collisionCount=0;
4381 unsigned int index = RemoteSystemLookupHashIndex(sa);
4382 while (remoteSystemLookup[index].index!=(unsigned int)-1)
4383 {
4384 if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
4385 index=0;
4386 // collisionCount++;
4387 }
4388 // printf("%i collisions. Using index %i\n", collisionCount, index);
4389 return index;
4390 }
4391 */
4392 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4393 // Description:
4394 // Handles an RPC packet. If you get a packet with the ID ID_RPC you should pass it to this function
4395 //
4396 // Parameters:
4397 // packet - A packet returned from Receive with the ID ID_RPC
4398 //
4399 // Returns:
4400 // true on success, false on a bad packet or an unregistered function
4401 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4402 #ifdef _MSC_VER
4403 #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
4404 #endif
HandleRPCPacket(const char * data,int length,SystemAddress systemAddress)4405 bool RakPeer::HandleRPCPacket( const char *data, int length, SystemAddress systemAddress )
4406 {
4407 // RPC BitStream format is
4408 // ID_RPC - unsigned char
4409 // Unique identifier string length - unsigned char
4410 // The unique ID - string with each letter in upper case, subtracted by 'A' and written in 5 bits.
4411 // Number of bits of the data (int)
4412 // The data
4413
4414 RakNet::BitStream incomingBitStream( (unsigned char *) data, length, false );
4415 char uniqueIdentifier[ 256 ];
4416 // BitSize_t bitLength;
4417 unsigned char *userData;
4418 //bool hasTimestamp;
4419 bool nameIsEncoded, networkIDIsEncoded;
4420 RPCIndex rpcIndex;
4421 RPCNode *node;
4422 RPCParameters rpcParms;
4423 NetworkID networkID;
4424 bool blockingCommand;
4425 RakNet::BitStream replyToSender;
4426 rpcParms.replyToSender=&replyToSender;
4427
4428 rpcParms.recipient=this;
4429 rpcParms.sender=systemAddress;
4430
4431 // Note to self - if I change this format then I have to change the PacketLogger class too
4432 incomingBitStream.IgnoreBits(8);
4433 if (data[0]==ID_TIMESTAMP)
4434 {
4435 // 11/1/2010 timestamp fix for RPC
4436 // incomingBitStream.IgnoreBits(8*(sizeof(RakNetTime)+sizeof(MessageID)));
4437 // memcpy(&rpcParms.remoteTimestamp, data+sizeof(MessageID), sizeof(RakNetTime));
4438 incomingBitStream.Read(rpcParms.remoteTimestamp);
4439 incomingBitStream.IgnoreBits(8);
4440 }
4441 else
4442 rpcParms.remoteTimestamp=0;
4443 if ( incomingBitStream.Read( nameIsEncoded ) == false )
4444 {
4445 #ifdef _DEBUG
4446 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4447 #endif
4448 return false;
4449 }
4450
4451 if (nameIsEncoded)
4452 {
4453 if ( stringCompressor->DecodeString(uniqueIdentifier, 256, &incomingBitStream) == false )
4454 {
4455 #ifdef _DEBUG
4456 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4457 #endif
4458 return false;
4459 }
4460
4461 rpcIndex = rpcMap.GetIndexFromFunctionName(uniqueIdentifier);
4462 }
4463 else
4464 {
4465 if ( incomingBitStream.ReadCompressed( rpcIndex ) == false )
4466 {
4467 #ifdef _DEBUG
4468 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4469 #endif
4470 return false;
4471 }
4472 }
4473 if ( incomingBitStream.Read( blockingCommand ) == false )
4474 {
4475 #ifdef _DEBUG
4476 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4477 #endif
4478 return false;
4479 }
4480
4481 /*
4482 if ( incomingBitStream.Read( rpcParms.hasTimestamp ) == false )
4483 {
4484 #ifdef _DEBUG
4485 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4486 #endif
4487 return false;
4488 }
4489 */
4490
4491 if ( incomingBitStream.ReadCompressed( rpcParms.numberOfBitsOfData ) == false )
4492 {
4493 #ifdef _DEBUG
4494 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4495 #endif
4496 return false;
4497 }
4498
4499 if ( incomingBitStream.Read( networkIDIsEncoded ) == false )
4500 {
4501 #ifdef _DEBUG
4502 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4503 #endif
4504 return false;
4505 }
4506
4507 if (networkIDIsEncoded)
4508 {
4509 if ( incomingBitStream.Read( networkID ) == false )
4510 {
4511 #ifdef _DEBUG
4512 RakAssert( 0 ); // bitstream was not long enough. Some kind of internal error
4513 #endif
4514 return false;
4515 }
4516 }
4517
4518 if (rpcIndex==UNDEFINED_RPC_INDEX)
4519 {
4520 // Unregistered function
4521 RakAssert(0);
4522 return false;
4523 }
4524
4525 node = rpcMap.GetNodeFromIndex(rpcIndex);
4526 if (node==0)
4527 {
4528 #ifdef _DEBUG
4529 RakAssert( 0 ); // Should never happen except perhaps from threading errors? No harm in checking anyway
4530 #endif
4531 return false;
4532 }
4533
4534 // Make sure the call type matches - if this is a pointer to a class member then networkID must be defined. Otherwise it must not be defined
4535 if (node->isPointerToMember==true && networkIDIsEncoded==false)
4536 {
4537 // If this hits then this pointer was registered as a class member function but the packet does not have an NetworkID.
4538 // Most likely this means this system registered a function with REGISTER_CLASS_MEMBER_RPC and the remote system called it
4539 // using the unique ID for a function registered with REGISTER_STATIC_RPC.
4540 RakAssert(0);
4541 return false;
4542 }
4543
4544 if (node->isPointerToMember==false && networkIDIsEncoded==true)
4545 {
4546 // If this hits then this pointer was not registered as a class member function but the packet does have an NetworkID.
4547 // Most likely this means this system registered a function with REGISTER_STATIC_RPC and the remote system called it
4548 // using the unique ID for a function registered with REGISTER_CLASS_MEMBER_RPC.
4549 RakAssert(0);
4550 return false;
4551 }
4552
4553 if (nameIsEncoded && GetRemoteSystemFromSystemAddress(systemAddress, false, true))
4554 {
4555 // Send ID_RPC_MAPPING to the sender so they know what index to use next time
4556 RakNet::BitStream rpcMapBitStream;
4557 rpcMapBitStream.Write((MessageID)ID_RPC_MAPPING);
4558 stringCompressor->EncodeString(node->uniqueIdentifier, 256, &rpcMapBitStream);
4559 rpcMapBitStream.WriteCompressed(rpcIndex);
4560 SendBuffered( (const char*)rpcMapBitStream.GetData(), rpcMapBitStream.GetNumberOfBitsUsed(), HIGH_PRIORITY, UNRELIABLE, 0, systemAddress, false, RemoteSystemStruct::NO_ACTION, 0 );
4561 }
4562
4563 rpcParms.functionName=node->uniqueIdentifier;
4564
4565 // Call the function
4566 if ( rpcParms.numberOfBitsOfData == 0 )
4567 {
4568 rpcParms.input=0;
4569 if (networkIDIsEncoded)
4570 {
4571 // If this assert hits, you tried to use object member RPC but didn't call RakPeer::SetNetworkIDManager first as required.
4572 RakAssert(networkIDManager);
4573 if (networkIDManager)
4574 {
4575 void *object = networkIDManager->GET_OBJECT_FROM_ID(networkID);
4576 if (object)
4577 (node->memberFunctionPointer(object, &rpcParms));
4578 }
4579 }
4580 else
4581 {
4582 node->staticFunctionPointer( &rpcParms );
4583 }
4584 }
4585 else
4586 {
4587 if ( incomingBitStream.GetNumberOfUnreadBits() == 0 )
4588 {
4589 #ifdef _DEBUG
4590 RakAssert( 0 );
4591 #endif
4592 return false; // No data was appended!
4593 }
4594
4595 // We have to copy into a new data chunk because the user data might not be byte aligned.
4596 bool usedAlloca=false;
4597
4598 if (BITS_TO_BYTES( incomingBitStream.GetNumberOfUnreadBits() ) < MAX_ALLOCA_STACK_ALLOCATION)
4599 {
4600 userData = ( unsigned char* ) alloca( (size_t) BITS_TO_BYTES( incomingBitStream.GetNumberOfUnreadBits() ) );
4601 usedAlloca=true;
4602 }
4603 else
4604
4605 userData = (unsigned char*) rakMalloc_Ex((size_t) BITS_TO_BYTES(incomingBitStream.GetNumberOfUnreadBits()), __FILE__, __LINE__);
4606
4607
4608 // The false means read out the internal representation of the bitstream data rather than
4609 // aligning it as we normally would with user data. This is so the end user can cast the data received
4610 // into a bitstream for reading
4611 if ( incomingBitStream.ReadBits( ( unsigned char* ) userData, rpcParms.numberOfBitsOfData, false ) == false )
4612 {
4613 #ifdef _DEBUG
4614 RakAssert( 0 );
4615 #endif
4616
4617
4618
4619
4620 return false; // Not enough data to read
4621 }
4622
4623 // if ( rpcParms.hasTimestamp )
4624 // ShiftIncomingTimestamp( userData, systemAddress );
4625
4626 // Call the function callback
4627 rpcParms.input=userData;
4628 if (networkIDIsEncoded)
4629 {
4630 // If this assert hits, you tried to use object member RPC but didn't call RakPeer::SetNetworkIDManager first as required.
4631 RakAssert(networkIDManager);
4632 if (networkIDManager)
4633 {
4634 void *object = networkIDManager->GET_OBJECT_FROM_ID(networkID);
4635 if (object)
4636 (node->memberFunctionPointer(object, &rpcParms));
4637 }
4638 }
4639 else
4640 {
4641 node->staticFunctionPointer( &rpcParms );
4642 }
4643
4644
4645 if (usedAlloca==false)
4646 rakFree_Ex(userData, __FILE__, __LINE__ );
4647 }
4648
4649 if (blockingCommand)
4650 {
4651 RakNet::BitStream reply;
4652 reply.Write((MessageID)ID_RPC_REPLY);
4653 reply.Write((char*)replyToSender.GetData(), replyToSender.GetNumberOfBytesUsed());
4654 Send(&reply, HIGH_PRIORITY, RELIABLE, 0, systemAddress, false);
4655 }
4656
4657 return true;
4658 }
4659
4660 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4661 /**
4662 * Handles an RPC reply packet. This is data returned from an RPC call
4663 *
4664 * \param data A packet returned from Receive with the ID ID_RPC
4665 * \param length The size of the packet data
4666 * \param systemAddress The sender of the packet
4667 *
4668 * \return true on success, false on a bad packet or an unregistered function
4669 */
4670 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HandleRPCReplyPacket(const char * data,int length,SystemAddress systemAddress)4671 void RakPeer::HandleRPCReplyPacket( const char *data, int length, SystemAddress systemAddress )
4672 {
4673 if (blockOnRPCReply)
4674 {
4675 if ((systemAddress==replyFromTargetPlayer && replyFromTargetBroadcast==false) ||
4676 (systemAddress!=replyFromTargetPlayer && replyFromTargetBroadcast==true))
4677 {
4678 replyFromTargetBS->Write(data+1, length-1);
4679 blockOnRPCReply=false;
4680 }
4681 }
4682 }
4683 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsLoopbackAddress(const AddressOrGUID & systemIdentifier,bool matchPort) const4684 bool RakPeer::IsLoopbackAddress(const AddressOrGUID &systemIdentifier, bool matchPort) const
4685 {
4686 if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
4687 return systemIdentifier.rakNetGuid==myGuid;
4688
4689 const SystemAddress sa = systemIdentifier.systemAddress;
4690
4691 // Used to see if we are sending to ourselves
4692 char str[64];
4693 sa.ToString(false,str);
4694
4695 bool isLoopback=strcmp(str,"127.0.0.1")==0;
4696 if (matchPort==false && isLoopback)
4697 return true;
4698 if (matchPort==false)
4699 {
4700 for (int ipIndex=0; ipIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipIndex++)
4701 if (mySystemAddress[ipIndex].binaryAddress==sa.binaryAddress)
4702 return true;
4703 }
4704 else
4705 {
4706 for (int ipIndex=0; ipIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipIndex++)
4707 if (mySystemAddress[ipIndex]==sa ||
4708 (isLoopback && sa.port==mySystemAddress[ipIndex].port))
4709 return true;
4710 }
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728 return sa==firstExternalID;
4729 }
4730 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetLoopbackAddress(void) const4731 SystemAddress RakPeer::GetLoopbackAddress(void) const
4732 {
4733
4734 return mySystemAddress[0];
4735
4736
4737
4738 }
4739 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GenerateSYNCookieRandomNumber(void)4740 void RakPeer::GenerateSYNCookieRandomNumber( void )
4741 {
4742 #if !defined(_WIN32_WCE)
4743 unsigned int number;
4744 int i;
4745 memcpy( oldRandomNumber, newRandomNumber, sizeof( newRandomNumber ) );
4746
4747 for ( i = 0; i < (int) sizeof( newRandomNumber ); i += (int) sizeof( number ) )
4748 {
4749 number = randomMT();
4750 memcpy( newRandomNumber + i, ( char* ) & number, sizeof( number ) );
4751 }
4752
4753 randomNumberExpirationTime = RakNet::GetTime() + SYN_COOKIE_OLD_RANDOM_NUMBER_DURATION;
4754 #endif
4755 }
4756
4757 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SecuredConnectionResponse(const SystemAddress systemAddress)4758 void RakPeer::SecuredConnectionResponse( const SystemAddress systemAddress )
4759 {
4760 #if !defined(_WIN32_WCE)
4761 CSHA1 sha1;
4762 // RSA_BIT_SIZE n;
4763 // big::uint32_t e;
4764 // unsigned char connectionRequestResponse[ 1 + sizeof( big::uint32_t ) + sizeof( RSA_BIT_SIZE ) + 20 ];
4765 uint32_t modulus[RAKNET_RSA_FACTOR_LIMBS];
4766 uint32_t e;
4767 unsigned char connectionRequestResponse[ 1 + sizeof( e ) + sizeof( modulus ) + 20 ];
4768 connectionRequestResponse[ 0 ] = ID_SECURED_CONNECTION_RESPONSE;
4769
4770 if ( randomNumberExpirationTime < RakNet::GetTime() )
4771 GenerateSYNCookieRandomNumber();
4772
4773 // Hash the SYN-Cookie
4774 // s2c syn-cookie = SHA1_HASH(source ip address + source port + random number)
4775 sha1.Reset();
4776 sha1.Update( ( unsigned char* ) & systemAddress.binaryAddress, sizeof( systemAddress.binaryAddress ) );
4777 sha1.Update( ( unsigned char* ) & systemAddress.port, sizeof( systemAddress.port ) );
4778 sha1.Update( ( unsigned char* ) & ( newRandomNumber ), sizeof(newRandomNumber) );
4779 sha1.Final();
4780
4781 // Write the cookie (not endian swapped)
4782 memcpy( connectionRequestResponse + 1, sha1.GetHash(), 20 );
4783
4784 // Write the public keys
4785 e = rsacrypt.getPublicExponent();
4786 //rsacrypt.getPublicModulus(n);
4787 rsacrypt.getPublicModulus(modulus);
4788 //rsacrypt.getPublicKey( e, n );
4789
4790 if (RakNet::BitStream::DoEndianSwap())
4791 {
4792 RakNet::BitStream::ReverseBytesInPlace(( unsigned char* ) & e, sizeof(e));
4793 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
4794 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &modulus[i], sizeof(modulus[i]));
4795 }
4796
4797 memcpy( connectionRequestResponse + 1 + 20, ( char* ) & e, sizeof( e ) );
4798 memcpy( connectionRequestResponse + 1 + 20 + sizeof( e ), modulus, sizeof( modulus ) );
4799
4800 /*
4801 #ifdef HOST_ENDIAN_IS_BIG
4802 // Mangle the keys on a Big-endian machine before sending
4803 BSWAPCPY( (unsigned char *)(connectionRequestResponse + 1 + 20),
4804 (unsigned char *)&e, sizeof( big::uint32_t ) );
4805 BSWAPCPY( (unsigned char *)(connectionRequestResponse + 1 + 20 + sizeof( big::uint32_t ) ),
4806 (unsigned char *)n, sizeof( RSA_BIT_SIZE ) );
4807 #else
4808 memcpy( connectionRequestResponse + 1 + 20, ( char* ) & e, sizeof( big::uint32_t ) );
4809 memcpy( connectionRequestResponse + 1 + 20 + sizeof( big::uint32_t ), n, sizeof( RSA_BIT_SIZE ) );
4810 #endif
4811 */
4812
4813 // s2c public key, syn-cookie
4814 //SocketLayer::SendTo( connectionSocket, ( char* ) connectionRequestResponse, 1 + sizeof( big::uint32_t ) + sizeof( RSA_BIT_SIZE ) + 20, systemAddress.binaryAddress, systemAddress.port );
4815 // All secure connection requests are unreliable because the entire process needs to be restarted if any part fails.
4816 // Connection requests are resent periodically
4817 SendImmediate(( char* ) connectionRequestResponse, (1 + sizeof( e ) + sizeof( modulus ) + 20) * 8, IMMEDIATE_PRIORITY, UNRELIABLE, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0);
4818 #endif
4819 }
4820
SecuredConnectionConfirmation(RakPeer::RemoteSystemStruct * remoteSystem,char * data)4821 void RakPeer::SecuredConnectionConfirmation( RakPeer::RemoteSystemStruct * remoteSystem, char* data )
4822 {
4823 #if !defined(_WIN32_WCE)
4824 int i, j;
4825 unsigned char randomNumber[ 20 ];
4826 unsigned int number;
4827 //bool doSend;
4828 Packet *packet;
4829 // big::uint32_t e;
4830 // RSA_BIT_SIZE n, message, encryptedMessage;
4831 // big::RSACrypt<RSA_BIT_SIZE> privKeyPncrypt;
4832 uint32_t e;
4833 uint32_t n[RAKNET_RSA_FACTOR_LIMBS], message[RAKNET_RSA_FACTOR_LIMBS], encryptedMessage[RAKNET_RSA_FACTOR_LIMBS];
4834 RSACrypt privKeyPncrypt;
4835
4836 // Make sure that we still want to connect
4837 if (remoteSystem->connectMode!=RemoteSystemStruct::REQUESTED_CONNECTION)
4838 return;
4839
4840 // Copy out e and n
4841 /*
4842 #ifdef HOST_ENDIAN_IS_BIG
4843 BSWAPCPY( (unsigned char *)&e, (unsigned char *)(data + 1 + 20), sizeof( big::uint32_t ) );
4844 BSWAPCPY( (unsigned char *)n, (unsigned char *)(data + 1 + 20 + sizeof( big::uint32_t )), sizeof( RSA_BIT_SIZE ) );
4845 #else
4846 memcpy( ( char* ) & e, data + 1 + 20, sizeof( big::uint32_t ) );
4847 memcpy( n, data + 1 + 20 + sizeof( big::uint32_t ), sizeof( RSA_BIT_SIZE ) );
4848 #endif
4849 */
4850
4851 memcpy( ( char* ) & e, data + 1 + 20, sizeof( e ) );
4852 memcpy( n, data + 1 + 20 + sizeof( e ), sizeof( n ) );
4853
4854 if (RakNet::BitStream::DoEndianSwap())
4855 {
4856 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &e, sizeof(e));
4857 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
4858 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &n[i], sizeof(n[i]));
4859 }
4860
4861
4862 // If we preset a size and it doesn't match, or the keys do not match, then tell the user
4863 if ( usingSecurity == true && keysLocallyGenerated == false )
4864 {
4865 if ( memcmp( ( char* ) & e, ( char* ) & publicKeyE, sizeof( e ) ) != 0 ||
4866 memcmp( n, publicKeyN, sizeof( n ) ) != 0 )
4867 {
4868 packet=AllocPacket(1, __FILE__, __LINE__);
4869 packet->data[ 0 ] = ID_RSA_PUBLIC_KEY_MISMATCH;
4870 packet->bitSize = sizeof( char ) * 8;
4871 packet->systemAddress = remoteSystem->systemAddress;
4872 packet->systemAddress.systemIndex = ( SystemIndex ) GetIndexFromSystemAddress( packet->systemAddress, true );
4873 packet->guid.systemIndex=packet->systemAddress.systemIndex;
4874 AddPacketToProducer(packet);
4875 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
4876 return;
4877 }
4878 }
4879
4880 // Create a random number
4881 for ( i = 0; i < (int) sizeof( randomNumber ); i += (int) sizeof( number ) )
4882 {
4883 number = randomMT();
4884 memcpy( randomNumber + i, ( char* ) & number, sizeof( number ) );
4885 }
4886
4887 memset( message, 0, sizeof( message ) );
4888 RakAssert( sizeof( message ) >= sizeof( randomNumber ) );
4889
4890 // if (RakNet::BitStream::DoEndianSwap())
4891 // {
4892 // for (int i=0; i < 20; i++)
4893 // RakNet::BitStream::ReverseBytesInPlace((unsigned char*) randomNumber[i], sizeof(randomNumber[i]));
4894 // }
4895
4896 memcpy( message, randomNumber, sizeof( randomNumber ) );
4897
4898 /*
4899
4900
4901 #ifdef HOST_ENDIAN_IS_BIG
4902 // Scramble the plaintext message (the random number)
4903 BSWAPCPY( (unsigned char *)message, randomNumber, sizeof(randomNumber) );
4904 #else
4905 memcpy( message, randomNumber, sizeof( randomNumber ) );
4906 #endif
4907 */
4908 privKeyPncrypt.setPublicKey( n, RAKNET_RSA_FACTOR_LIMBS, e );
4909 // privKeyPncrypt.encrypt( message, encryptedMessage );
4910
4911 // printf("message[0]=%i,%i\n", message[0], message[19]);
4912
4913 privKeyPncrypt.encrypt( encryptedMessage, message );
4914
4915 // printf("enc1[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
4916
4917 // A big-endian machine needs to scramble the byte order of an outgoing (encrypted) message
4918 if (RakNet::BitStream::DoEndianSwap())
4919 {
4920 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
4921 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &encryptedMessage[i], sizeof(encryptedMessage[i]));
4922 }
4923
4924 // printf("enc2[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
4925
4926
4927 /*
4928 #ifdef HOST_ENDIAN_IS_BIG
4929 // A big-endian machine needs to scramble the byte order of an outgoing (encrypted) message
4930 BSWAPSELF( (unsigned char *)encryptedMessage, sizeof( RSA_BIT_SIZE ) );
4931 #endif
4932 */
4933
4934 /*
4935 rakPeerMutexes[ RakPeer::requestedConnections_MUTEX ].Lock();
4936 for ( i = 0; i < ( int ) requestedConnectionsList.Size(); i++ )
4937 {
4938 if ( requestedConnectionsList[ i ]->systemAddress == systemAddress )
4939 {
4940 doSend = true;
4941 // Generate the AES key
4942
4943 for ( j = 0; j < 16; j++ )
4944 requestedConnectionsList[ i ]->AESKey[ j ] = data[ 1 + j ] ^ randomNumber[ j ];
4945
4946 requestedConnectionsList[ i ]->setAESKey = true;
4947
4948 break;
4949 }
4950 }
4951 rakPeerMutexes[ RakPeer::requestedConnections_MUTEX ].Unlock();
4952 */
4953
4954 // Take the remote system's AESKey (SynCookie) and XOR with our random number.
4955 for ( j = 0; j < 16; j++ )
4956 remoteSystem->AESKey[ j ] = data[ 1 + j ] ^ randomNumber[ j ];
4957 remoteSystem->setAESKey = true;
4958
4959 /*
4960 // if ( doSend )
4961 // {
4962 char reply[ 1 + 20 + sizeof( RSA_BIT_SIZE ) ];
4963 // c2s RSA(random number), same syn-cookie
4964 reply[ 0 ] = ID_SECURED_CONNECTION_CONFIRMATION;
4965 memcpy( reply + 1, data + 1, 20 ); // Copy the syn-cookie
4966 memcpy( reply + 1 + 20, encryptedMessage, sizeof( RSA_BIT_SIZE ) ); // Copy the encoded random number
4967
4968 //SocketLayer::SendTo( connectionSocket, reply, 1 + 20 + sizeof( RSA_BIT_SIZE ), systemAddress.binaryAddress, systemAddress.port );
4969 // All secure connection requests are unreliable because the entire process needs to be restarted if any part fails.
4970 // Connection requests are resent periodically
4971 SendImmediate((char*)reply, (1 + 20 + sizeof( RSA_BIT_SIZE )) * 8, IMMEDIATE_PRIORITY, UNRELIABLE, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS());
4972 // }
4973 */
4974
4975 char reply[ 1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS + sizeof(RakNetTime) ];
4976 // c2s RSA(random number), same syn-cookie
4977 reply[ 0 ] = ID_SECURED_CONNECTION_CONFIRMATION;
4978 memcpy( reply + 1, data + 1, 20 ); // Copy the syn-cookie
4979 memcpy( reply + 1 + 20, encryptedMessage, sizeof( encryptedMessage ) ); // Copy the encoded random number
4980 RakNet::BitStream bsTimestamp;
4981 bsTimestamp.Write(RakNet::GetTime());
4982 memcpy( reply + 1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS, bsTimestamp.GetData(), bsTimestamp.GetNumberOfBytesUsed() );
4983
4984 // All secure connection requests are unreliable because the entire process needs to be restarted if any part fails.
4985 // Connection requests are resent periodically
4986 SendImmediate((char*)reply, (1 + 20 + sizeof(uint32_t) * RAKNET_RSA_FACTOR_LIMBS + sizeof(RakNetTime) ) * 8 , IMMEDIATE_PRIORITY, UNRELIABLE, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS(), 0);
4987
4988 #endif
4989 }
4990 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AllowIncomingConnections(void) const4991 bool RakPeer::AllowIncomingConnections(void) const
4992 {
4993 return GetNumberOfRemoteInitiatedConnections() < GetMaximumIncomingConnections();
4994 }
4995 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PingInternal(const SystemAddress target,bool performImmediate,PacketReliability reliability)4996 void RakPeer::PingInternal( const SystemAddress target, bool performImmediate, PacketReliability reliability )
4997 {
4998 if ( IsActive() == false )
4999 return ;
5000
5001 RakNet::BitStream bitStream(sizeof(unsigned char)+sizeof(RakNetTime));
5002 bitStream.Write((MessageID)ID_INTERNAL_PING);
5003 RakNetTimeUS currentTimeNS = RakNet::GetTimeNS();
5004 RakNetTime currentTime = RakNet::GetTime();
5005 bitStream.Write(currentTime);
5006 if (performImmediate)
5007 SendImmediate( (char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, reliability, 0, target, false, false, currentTimeNS, 0 );
5008 else
5009 Send( &bitStream, IMMEDIATE_PRIORITY, reliability, 0, target, false );
5010 }
5011 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloseConnectionInternal(const AddressOrGUID & systemIdentifier,bool sendDisconnectionNotification,bool performImmediate,unsigned char orderingChannel,PacketPriority disconnectionNotificationPriority)5012 void RakPeer::CloseConnectionInternal( const AddressOrGUID& systemIdentifier, bool sendDisconnectionNotification, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
5013 {
5014 #ifdef _DEBUG
5015 RakAssert(orderingChannel < 32);
5016 #endif
5017
5018 if (systemIdentifier.IsUndefined())
5019 return;
5020
5021 if ( remoteSystemList == 0 || endThreads == true )
5022 return;
5023
5024 SystemAddress target;
5025 if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
5026 {
5027 target=systemIdentifier.systemAddress;
5028 }
5029 else
5030 {
5031 target=GetSystemAddressFromGuid(systemIdentifier.rakNetGuid);
5032 }
5033
5034 if (sendDisconnectionNotification)
5035 {
5036 NotifyAndFlagForShutdown(target, performImmediate, orderingChannel, disconnectionNotificationPriority);
5037 }
5038 else
5039 {
5040 if (performImmediate)
5041 {
5042 unsigned int index = GetRemoteSystemIndex(target);
5043 if (index!=(unsigned int) -1)
5044 {
5045 if ( remoteSystemList[index].isActive )
5046 {
5047 // Found the index to stop
5048 remoteSystemList[index].isActive = false;
5049
5050 remoteSystemList[index].guid=UNASSIGNED_RAKNET_GUID;
5051
5052 // Reserve this reliability layer for ourselves
5053 //remoteSystemList[ remoteSystemLookup[index].index ].systemAddress = UNASSIGNED_SYSTEM_ADDRESS;
5054
5055 // Clear any remaining messages
5056 remoteSystemList[index].reliabilityLayer.Reset(false, remoteSystemList[index].MTUSize);
5057
5058 // Not using this socket
5059 remoteSystemList[index].rakNetSocket.SetNull();
5060 }
5061 }
5062 }
5063 else
5064 {
5065 BufferedCommandStruct *bcs;
5066 #ifdef _RAKNET_THREADSAFE
5067 bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
5068 bcs->command=BufferedCommandStruct::BCS_CLOSE_CONNECTION;
5069 bcs->systemIdentifier=target;
5070 bcs->data=0;
5071 bcs->orderingChannel=orderingChannel;
5072 bcs->priority=disconnectionNotificationPriority;
5073 bufferedCommands.Push(bcs);
5074 #else
5075 bcs=bufferedCommands.WriteLock();
5076 bcs->command=BufferedCommandStruct::BCS_CLOSE_CONNECTION;
5077 bcs->systemIdentifier=target;
5078 bcs->data=0;
5079 bcs->orderingChannel=orderingChannel;
5080 bcs->priority=disconnectionNotificationPriority;
5081 bufferedCommands.WriteUnlock();
5082 #endif
5083 }
5084 }
5085 }
5086 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ValidSendTarget(SystemAddress systemAddress,bool broadcast)5087 bool RakPeer::ValidSendTarget(SystemAddress systemAddress, bool broadcast)
5088 {
5089 unsigned remoteSystemIndex;
5090
5091 // remoteSystemList in user thread. This is slow so only do it in debug
5092 for ( remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; remoteSystemIndex++ )
5093 //for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; remoteSystemIndex++ )
5094 {
5095 if ( remoteSystemList[ remoteSystemIndex ].isActive &&
5096 remoteSystemList[ remoteSystemIndex ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED && // Not fully connected players are not valid user-send targets because the reliability layer wasn't reset yet
5097 ( ( broadcast == false && remoteSystemList[ remoteSystemIndex ].systemAddress == systemAddress ) ||
5098 ( broadcast == true && remoteSystemList[ remoteSystemIndex ].systemAddress != systemAddress ) )
5099 )
5100 return true;
5101 }
5102
5103 return false;
5104 }
5105 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendBuffered(const char * data,BitSize_t numberOfBitsToSend,PacketPriority priority,PacketReliability reliability,char orderingChannel,const AddressOrGUID systemIdentifier,bool broadcast,RemoteSystemStruct::ConnectMode connectionMode,uint32_t receipt)5106 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 )
5107 {
5108 BufferedCommandStruct *bcs;
5109
5110 #ifdef _RAKNET_THREADSAFE
5111 bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
5112 #else
5113 bcs=bufferedCommands.WriteLock();
5114 #endif
5115 bcs->data = (char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES(numberOfBitsToSend), __FILE__, __LINE__ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
5116 if (bcs->data==0)
5117 {
5118 notifyOutOfMemory(__FILE__, __LINE__);
5119 #ifdef _RAKNET_THREADSAFE
5120 bufferedCommands.Deallocate(bcs, __FILE__,__LINE__);
5121 #else
5122 bufferedCommands.WriteUnlock();
5123 #endif
5124 return;
5125 }
5126 memcpy(bcs->data, data, (size_t) BITS_TO_BYTES(numberOfBitsToSend));
5127 bcs->numberOfBitsToSend=numberOfBitsToSend;
5128 bcs->priority=priority;
5129 bcs->reliability=reliability;
5130 bcs->orderingChannel=orderingChannel;
5131 bcs->systemIdentifier=systemIdentifier;
5132 bcs->broadcast=broadcast;
5133 bcs->connectionMode=connectionMode;
5134 bcs->receipt=receipt;
5135 bcs->command=BufferedCommandStruct::BCS_SEND;
5136 #ifdef _RAKNET_THREADSAFE
5137 bufferedCommands.Push(bcs);
5138 #else
5139 bufferedCommands.WriteUnlock();
5140 #endif
5141
5142 if (priority==IMMEDIATE_PRIORITY)
5143 {
5144 // Forces pending sends to go out now, rather than waiting to the next update interval
5145 quitAndDataEvents.SetEvent();
5146 }
5147 }
5148 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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)5149 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 )
5150 {
5151 BufferedCommandStruct *bcs;
5152 unsigned int totalLength=0;
5153 unsigned int lengthOffset;
5154 int i;
5155 for (i=0; i < numParameters; i++)
5156 {
5157 if (lengths[i]>0)
5158 totalLength+=lengths[i];
5159 }
5160 if (totalLength==0)
5161 return;
5162
5163 char *dataAggregate;
5164 dataAggregate = (char*) rakMalloc_Ex( (size_t) totalLength, __FILE__, __LINE__ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
5165 if (dataAggregate==0)
5166 {
5167 notifyOutOfMemory(__FILE__, __LINE__);
5168 return;
5169 }
5170 for (i=0, lengthOffset=0; i < numParameters; i++)
5171 {
5172 if (lengths[i]>0)
5173 {
5174 memcpy(dataAggregate+lengthOffset, data[i], lengths[i]);
5175 lengthOffset+=lengths[i];
5176 }
5177 }
5178
5179 if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
5180 {
5181 SendLoopback(dataAggregate,totalLength);
5182 rakFree_Ex(dataAggregate,__FILE__,__LINE__);
5183 return;
5184 }
5185
5186 #ifdef _RAKNET_THREADSAFE
5187 bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
5188 #else
5189 bcs=bufferedCommands.WriteLock();
5190 #endif
5191 bcs->data = dataAggregate;
5192 bcs->numberOfBitsToSend=BYTES_TO_BITS(totalLength);
5193 bcs->priority=priority;
5194 bcs->reliability=reliability;
5195 bcs->orderingChannel=orderingChannel;
5196 bcs->systemIdentifier=systemIdentifier;
5197 bcs->broadcast=broadcast;
5198 bcs->connectionMode=connectionMode;
5199 bcs->receipt=receipt;
5200 bcs->command=BufferedCommandStruct::BCS_SEND;
5201 #ifdef _RAKNET_THREADSAFE
5202 bufferedCommands.Push(bcs);
5203 #else
5204 bufferedCommands.WriteUnlock();
5205 #endif
5206
5207 if (priority==IMMEDIATE_PRIORITY)
5208 {
5209 // Forces pending sends to go out now, rather than waiting to the next update interval
5210 quitAndDataEvents.SetEvent();
5211 }
5212 }
5213 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendImmediate(char * data,BitSize_t numberOfBitsToSend,PacketPriority priority,PacketReliability reliability,char orderingChannel,const AddressOrGUID systemIdentifier,bool broadcast,bool useCallerDataAllocation,RakNetTimeUS currentTime,uint32_t receipt)5214 bool RakPeer::SendImmediate( char *data, BitSize_t numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, bool useCallerDataAllocation, RakNetTimeUS currentTime, uint32_t receipt )
5215 {
5216 unsigned *sendList;
5217 unsigned sendListSize;
5218 bool callerDataAllocationUsed;
5219 unsigned int remoteSystemIndex, sendListIndex; // Iterates into the list of remote systems
5220 unsigned numberOfBytesUsed = (unsigned) BITS_TO_BYTES(numberOfBitsToSend);
5221 callerDataAllocationUsed=false;
5222
5223 sendListSize=0;
5224
5225 if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
5226 remoteSystemIndex=GetIndexFromSystemAddress( systemIdentifier.systemAddress, true );
5227 else if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
5228 remoteSystemIndex=GetSystemIndexFromGuid(systemIdentifier.rakNetGuid);
5229 else
5230 remoteSystemIndex=(unsigned int) -1;
5231
5232 // 03/06/06 - If broadcast is false, use the optimized version of GetIndexFromSystemAddress
5233 if (broadcast==false)
5234 {
5235 if (remoteSystemIndex==(unsigned int) -1)
5236 {
5237 #ifdef _DEBUG
5238 // int debugIndex = GetRemoteSystemIndex(systemIdentifier.systemAddress);
5239 #endif
5240 return false;
5241 }
5242
5243
5244 sendList=(unsigned *)alloca(sizeof(unsigned));
5245
5246
5247
5248
5249 if (remoteSystemList[remoteSystemIndex].isActive &&
5250 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP &&
5251 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY &&
5252 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
5253 {
5254 sendList[0]=remoteSystemIndex;
5255 sendListSize=1;
5256 }
5257 }
5258 else
5259 {
5260
5261 //sendList=(unsigned *)alloca(sizeof(unsigned)*remoteSystemListSize);
5262 sendList=(unsigned *)alloca(sizeof(unsigned)*maximumNumberOfPeers);
5263
5264
5265
5266
5267
5268 // remoteSystemList in network thread
5269 unsigned int idx;
5270 for ( idx = 0; idx < maximumNumberOfPeers; idx++ )
5271 {
5272 if (remoteSystemIndex!=(unsigned int) -1 && idx==remoteSystemIndex)
5273 continue;
5274
5275 if ( remoteSystemList[ idx ].isActive && remoteSystemList[ idx ].systemAddress != UNASSIGNED_SYSTEM_ADDRESS )
5276 sendList[sendListSize++]=idx;
5277 }
5278 }
5279
5280 if (sendListSize==0)
5281 {
5282
5283
5284
5285 return false;
5286 }
5287
5288 for (sendListIndex=0; sendListIndex < sendListSize; sendListIndex++)
5289 {
5290 if ( trackFrequencyTable )
5291 {
5292 unsigned i;
5293 // Store output frequency
5294 for (i=0 ; i < numberOfBytesUsed; i++ )
5295 frequencyTable[ (unsigned char)(data[i]) ]++;
5296 }
5297
5298 if ( outputTree )
5299 {
5300 RakNet::BitStream bitStreamCopy( numberOfBytesUsed );
5301 outputTree->EncodeArray( (unsigned char*) data, numberOfBytesUsed, &bitStreamCopy );
5302 rawBytesSent += numberOfBytesUsed;
5303 compressedBytesSent += (unsigned int) bitStreamCopy.GetNumberOfBytesUsed();
5304 remoteSystemList[sendList[sendListIndex]].reliabilityLayer.Send( (char*) bitStreamCopy.GetData(), bitStreamCopy.GetNumberOfBitsUsed(), priority, reliability, orderingChannel, true, remoteSystemList[sendList[sendListIndex]].MTUSize, currentTime, receipt );
5305 }
5306 else
5307 {
5308 // Send may split the packet and thus deallocate data. Don't assume data is valid if we use the callerAllocationData
5309 bool useData = useCallerDataAllocation && callerDataAllocationUsed==false && sendListIndex+1==sendListSize;
5310 remoteSystemList[sendList[sendListIndex]].reliabilityLayer.Send( data, numberOfBitsToSend, priority, reliability, orderingChannel, useData==false, remoteSystemList[sendList[sendListIndex]].MTUSize, currentTime, receipt );
5311 if (useData)
5312 callerDataAllocationUsed=true;
5313 }
5314
5315 if (reliability==RELIABLE ||
5316 reliability==RELIABLE_ORDERED ||
5317 reliability==RELIABLE_SEQUENCED ||
5318 reliability==RELIABLE_WITH_ACK_RECEIPT ||
5319 reliability==RELIABLE_ORDERED_WITH_ACK_RECEIPT
5320 // ||
5321 // reliability==RELIABLE_SEQUENCED_WITH_ACK_RECEIPT
5322 )
5323 remoteSystemList[sendList[sendListIndex]].lastReliableSend=(RakNetTime)(currentTime/(RakNetTimeUS)1000);
5324 }
5325
5326
5327
5328
5329
5330 // 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
5331 return callerDataAllocationUsed;
5332 }
5333 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResetSendReceipt(void)5334 void RakPeer::ResetSendReceipt(void)
5335 {
5336 sendReceiptSerialMutex.Lock();
5337 sendReceiptSerial=1;
5338 sendReceiptSerialMutex.Unlock();
5339 }
5340 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OnConnectedPong(RakNetTime sendPingTime,RakNetTime sendPongTime,RemoteSystemStruct * remoteSystem)5341 void RakPeer::OnConnectedPong(RakNetTime sendPingTime, RakNetTime sendPongTime, RemoteSystemStruct *remoteSystem)
5342 {
5343 RakNetTime ping, lastPing;
5344 RakNetTimeUS timeNS = RakNet::GetTimeNS(); // Update the time value to be accurate
5345 RakNetTimeMS timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
5346 if (timeMS > sendPingTime)
5347 ping = timeMS - sendPingTime;
5348 else
5349 ping=0;
5350 lastPing = remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime;
5351
5352 // Ignore super high spikes in the average
5353 if ( lastPing <= 0 || ( ( ping < ( lastPing * 3 ) ) && ping < 1200 ) )
5354 {
5355 remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime = ( unsigned short ) ping;
5356 // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
5357 // Divide each integer by 2, rather than the sum by 2, to prevent overflow
5358 remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].clockDifferential = sendPongTime - ( timeMS/2 + sendPingTime/2 );
5359
5360 if ( remoteSystem->lowestPing == (unsigned short)-1 || remoteSystem->lowestPing > (int) ping )
5361 remoteSystem->lowestPing = (unsigned short) ping;
5362
5363 // Reliability layer calculates its own ping
5364 // Most packets should arrive by the ping time.
5365 //RakAssert(ping < 10000); // Sanity check - could hit due to negative pings causing the var to overflow
5366 //remoteSystem->reliabilityLayer.SetPing( (unsigned short) ping );
5367
5368 if ( ++( remoteSystem->pingAndClockDifferentialWriteIndex ) == PING_TIMES_ARRAY_SIZE )
5369 remoteSystem->pingAndClockDifferentialWriteIndex = 0;
5370
5371 remoteSystem->reliabilityLayer.OnExternalPing((double) ping);
5372 }
5373 }
5374 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearBufferedCommands(void)5375 void RakPeer::ClearBufferedCommands(void)
5376 {
5377 BufferedCommandStruct *bcs;
5378
5379 #ifdef _RAKNET_THREADSAFE
5380 while ((bcs=bufferedCommands.Pop())!=0)
5381 {
5382 if (bcs->data)
5383 rakFree_Ex(bcs->data, __FILE__, __LINE__ );
5384
5385 bufferedCommands.Deallocate(bcs, __FILE__,__LINE__);
5386 }
5387 bufferedCommands.Clear(__FILE__, __LINE__);
5388 #else
5389 while ((bcs=bufferedCommands.ReadLock())!=0)
5390 {
5391 if (bcs->data)
5392 rakFree_Ex(bcs->data, __FILE__, __LINE__ );
5393
5394 bufferedCommands.ReadUnlock();
5395 }
5396 bufferedCommands.Clear(__FILE__, __LINE__);
5397 #endif
5398 }
5399 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearBufferedPackets(void)5400 void RakPeer::ClearBufferedPackets(void)
5401 {
5402 RecvFromStruct *bcs;
5403
5404 #ifdef _RAKNET_THREADSAFE
5405 while ((bcs=bufferedPackets.Pop())!=0)
5406 {
5407 bufferedPackets.Deallocate(bcs, __FILE__,__LINE__);
5408 }
5409 bufferedPackets.Clear(__FILE__, __LINE__);
5410 #else
5411 while ((bcs=bufferedPackets.ReadLock())!=0)
5412 {
5413 bufferedPackets.ReadUnlock();
5414 }
5415 bufferedPackets.Clear(__FILE__, __LINE__);
5416 #endif
5417 }
5418 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearSocketQueryOutput(void)5419 void RakPeer::ClearSocketQueryOutput(void)
5420 {
5421 socketQueryOutput.Clear(__FILE__, __LINE__);
5422 }
5423 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearRequestedConnectionList(void)5424 void RakPeer::ClearRequestedConnectionList(void)
5425 {
5426 DataStructures::Queue<RequestedConnectionStruct*> freeQueue;
5427 requestedConnectionQueueMutex.Lock();
5428 while (requestedConnectionQueue.Size())
5429 freeQueue.Push(requestedConnectionQueue.Pop(), __FILE__, __LINE__ );
5430 requestedConnectionQueueMutex.Unlock();
5431 unsigned i;
5432 for (i=0; i < freeQueue.Size(); i++)
5433 RakNet::OP_DELETE(freeQueue[i], __FILE__, __LINE__ );
5434 }
AddPacketToProducer(Packet * p)5435 inline void RakPeer::AddPacketToProducer(Packet *p)
5436 {
5437 packetReturnMutex.Lock();
5438 packetReturnQueue.Push(p,__FILE__,__LINE__);
5439 packetReturnMutex.Unlock();
5440 }
5441 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GenerateGUID(void)5442 void RakPeer::GenerateGUID(void)
5443 {
5444 // Mac address is a poor solution because you can't have multiple connections from the same system
5445
5446
5447
5448
5449
5450
5451
5452
5453 #if defined(_WIN32)
5454 myGuid.g=RakNet::GetTimeUS();
5455
5456 RakNetTimeUS lastTime, thisTime;
5457 int j;
5458 // Sleep a small random time, then use the last 4 bits as a source of randomness
5459 for (j=0; j < 8; j++)
5460 {
5461 lastTime = RakNet::GetTimeUS();
5462 RakSleep(1);
5463 RakSleep(0);
5464 thisTime = RakNet::GetTimeUS();
5465 RakNetTimeUS diff = thisTime-lastTime;
5466 unsigned int diff4Bits = (unsigned int) (diff & 15);
5467 diff4Bits <<= 32-4;
5468 diff4Bits >>= j*4;
5469 ((char*)&myGuid.g)[j] ^= diff4Bits;
5470 }
5471
5472 #else
5473 struct timeval tv;
5474 gettimeofday(&tv, NULL);
5475 myGuid.g=tv.tv_usec + tv.tv_sec * 1000000;
5476 #endif
5477 }
5478 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ProcessPortUnreachable(unsigned int binaryAddress,unsigned short port,RakPeer * rakPeer)5479 void ProcessPortUnreachable( unsigned int binaryAddress, unsigned short port, RakPeer *rakPeer )
5480 {
5481 (void) binaryAddress;
5482 (void) port;
5483 (void) rakPeer;
5484
5485 }
5486 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ProcessOfflineNetworkPacket(const SystemAddress systemAddress,const char * data,const int length,RakPeer * rakPeer,RakNetSmartPtr<RakNetSocket> rakNetSocket,bool * isOfflineMessage,RakNetTimeUS timeRead)5487 bool ProcessOfflineNetworkPacket( const SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSmartPtr<RakNetSocket> rakNetSocket, bool *isOfflineMessage, RakNetTimeUS timeRead )
5488 {
5489 (void) timeRead;
5490 RakPeer::RemoteSystemStruct *remoteSystem;
5491 Packet *packet;
5492 unsigned i;
5493
5494
5495 char str1[64];
5496 systemAddress.ToString(false, str1);
5497 if (rakPeer->IsBanned( str1 ))
5498 {
5499 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5500 rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
5501
5502 RakNet::BitStream bs;
5503 bs.Write((MessageID)ID_CONNECTION_BANNED);
5504 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5505 bs.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5506
5507 unsigned i;
5508 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5509 rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
5510 SocketLayer::SendTo( rakNetSocket->s, (char*) bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5511
5512 return true;
5513 }
5514
5515
5516
5517 // 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,
5518 // and a regular encoding. So I insert OFFLINE_MESSAGE_DATA_ID into the stream, the encoding of which is essentially impossible to hit by random chance
5519 if (length <=2)
5520 {
5521 *isOfflineMessage=true;
5522 }
5523 else if (
5524 ((unsigned char)data[0] == ID_PING ||
5525 (unsigned char)data[0] == ID_PING_OPEN_CONNECTIONS) &&
5526 length == sizeof(unsigned char) + sizeof(RakNetTime) + sizeof(OFFLINE_MESSAGE_DATA_ID))
5527 {
5528 *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(RakNetTime), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
5529 }
5530 else if ((unsigned char)data[0] == ID_PONG && (size_t) length >= sizeof(unsigned char) + sizeof(RakNetTime) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
5531 {
5532 *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(RakNetTime) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
5533 }
5534 else if (
5535 (unsigned char)data[0] == ID_OUT_OF_BAND_INTERNAL &&
5536 (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
5537 {
5538 *isOfflineMessage=memcmp(data+sizeof(MessageID) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
5539 }
5540 else if (
5541 (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST &&
5542 (size_t) length >= sizeof(MessageID)*2 + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
5543 {
5544 *isOfflineMessage=memcmp(data+sizeof(MessageID)*2 + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
5545 }
5546 else if (
5547 (
5548 (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY ||
5549 (unsigned char)data[0] == ID_CONNECTION_ATTEMPT_FAILED ||
5550 (unsigned char)data[0] == ID_NO_FREE_INCOMING_CONNECTIONS ||
5551 (unsigned char)data[0] == ID_CONNECTION_BANNED ||
5552 (unsigned char)data[0] == ID_ALREADY_CONNECTED ||
5553 (unsigned char)data[0] == ID_IP_RECENTLY_CONNECTED ||
5554 (unsigned char)data[0] == ID_CONNECTION_REQUEST) &&
5555 (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
5556 {
5557 *isOfflineMessage=memcmp(data+sizeof(MessageID), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
5558 }
5559 else if (((unsigned char)data[0] == ID_INCOMPATIBLE_PROTOCOL_VERSION&&
5560 (size_t) length == sizeof(MessageID)*2 + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID)))
5561 {
5562 *isOfflineMessage=memcmp(data+sizeof(MessageID)*2, OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
5563 }
5564 else
5565 {
5566 *isOfflineMessage=false;
5567 }
5568
5569 if (*isOfflineMessage)
5570 {
5571 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5572 rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
5573
5574 // These are all messages from unconnected systems. Messages here can be any size, but are never processed from connected systems.
5575 if ( ( (unsigned char) data[ 0 ] == ID_PING_OPEN_CONNECTIONS
5576 || (unsigned char)(data)[0] == ID_PING) && length == sizeof(unsigned char)+sizeof(RakNetTime)+sizeof(OFFLINE_MESSAGE_DATA_ID) )
5577 {
5578 if ( (unsigned char)(data)[0] == ID_PING ||
5579 rakPeer->AllowIncomingConnections() ) // Open connections with players
5580 {
5581 // #if !defined(_XBOX) && !defined(X360)
5582 RakNet::BitStream inBitStream( (unsigned char *) data, length, false );
5583 inBitStream.IgnoreBits(8);
5584 RakNetTime sendPingTime;
5585 inBitStream.Read(sendPingTime);
5586
5587 RakNet::BitStream outBitStream;
5588 outBitStream.Write((MessageID)ID_PONG); // Should be named ID_UNCONNECTED_PONG eventually
5589 outBitStream.Write(sendPingTime);
5590 outBitStream.Write(rakPeer->myGuid);
5591 outBitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5592
5593 rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Lock();
5594 // They are connected, so append offline ping data
5595 outBitStream.Write( (char*)rakPeer->offlinePingResponse.GetData(), rakPeer->offlinePingResponse.GetNumberOfBytesUsed() );
5596 rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Unlock();
5597
5598 unsigned i;
5599 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5600 rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*)outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), systemAddress);
5601
5602 char str1[64];
5603 systemAddress.ToString(false, str1);
5604 SocketLayer::SendTo( rakNetSocket->s, (const char*)outBitStream.GetData(), (unsigned int) outBitStream.GetNumberOfBytesUsed(), str1 , systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5605
5606 packet=rakPeer->AllocPacket(sizeof(MessageID), __FILE__, __LINE__);
5607 packet->data[0]=data[0];
5608 packet->systemAddress = systemAddress;
5609 packet->guid=UNASSIGNED_RAKNET_GUID;
5610 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
5611 packet->guid.systemIndex=packet->systemAddress.systemIndex;
5612 rakPeer->AddPacketToProducer(packet);
5613 // #endif
5614 }
5615 }
5616 // UNCONNECTED MESSAGE Pong with no data.
5617 else if ((unsigned char) data[ 0 ] == ID_PONG && (size_t) length >= sizeof(unsigned char)+sizeof(RakNetTime)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID) && (size_t) length < sizeof(unsigned char)+sizeof(RakNetTime)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID)+MAX_OFFLINE_DATA_LENGTH)
5618 {
5619 packet=rakPeer->AllocPacket((unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()), __FILE__, __LINE__);
5620 RakNet::BitStream bs((unsigned char*) data, length, false);
5621 bs.IgnoreBytes(sizeof(unsigned char)+sizeof(RakNetTime));
5622 bs.Read(packet->guid);
5623 packet->data[0]=ID_PONG;
5624 // Don't endian swap the time, so the user can do so when reading out as a bitstream
5625 memcpy(packet->data+sizeof(unsigned char), data+sizeof(unsigned char), sizeof(RakNetTime));
5626 // RakNetTime test1;
5627 // memcpy(&test1,data+sizeof(unsigned char), sizeof(RakNetTime));
5628 // RakNetTime test2;
5629 // test2=RakNet::GetTime();
5630 memcpy(packet->data+sizeof(unsigned char)+sizeof(RakNetTime), data+sizeof(unsigned char)+sizeof(RakNetTime)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID), length-sizeof(unsigned char)-sizeof(RakNetTime)-RakNetGUID::size()-sizeof(OFFLINE_MESSAGE_DATA_ID));
5631 packet->bitSize = BYTES_TO_BITS(packet->length);
5632 packet->systemAddress = systemAddress;
5633 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
5634 packet->guid.systemIndex=packet->systemAddress.systemIndex;
5635 rakPeer->AddPacketToProducer(packet);
5636 }
5637 else if ((unsigned char) data[ 0 ] == ID_OUT_OF_BAND_INTERNAL &&
5638 (size_t) length < MAX_OFFLINE_DATA_LENGTH+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)+RakNetGUID::size())
5639 {
5640 unsigned int dataLength = (unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()-sizeof(MessageID));
5641 RakAssert(dataLength<1024);
5642 packet=rakPeer->AllocPacket(dataLength+sizeof(MessageID), __FILE__, __LINE__);
5643 RakAssert(packet->length<1024);
5644
5645 RakNet::BitStream bs2((unsigned char*) data, length, false);
5646 bs2.IgnoreBytes(sizeof(MessageID));
5647 bs2.Read(packet->guid);
5648
5649 if (data[sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID) + RakNetGUID::size()]==ID_ADVERTISE_SYSTEM)
5650 {
5651 packet->length--;
5652 packet->bitSize=BYTES_TO_BITS(packet->length);
5653 packet->data[0]=ID_ADVERTISE_SYSTEM;
5654 memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)*2 + RakNetGUID::size(), dataLength);
5655 }
5656 else
5657 {
5658 packet->data[0]=ID_OUT_OF_BAND_INTERNAL;
5659 memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID) + RakNetGUID::size(), dataLength);
5660 }
5661
5662 packet->systemAddress = systemAddress;
5663 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
5664 packet->guid.systemIndex=packet->systemAddress.systemIndex;
5665 rakPeer->AddPacketToProducer(packet);
5666 }
5667 else if ((unsigned char)(data)[0] == (MessageID)ID_OPEN_CONNECTION_REPLY)
5668 {
5669 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5670 rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
5671
5672 RakNet::BitStream bs((unsigned char*) data,length,false);
5673 bs.IgnoreBytes(sizeof(MessageID));
5674 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
5675 RakNetGUID guid;
5676 bs.Read(guid);
5677 SystemAddress bindingAddress;
5678 bs.Read(bindingAddress);
5679
5680 RakPeer::RequestedConnectionStruct *rcs;
5681 bool unlock=true;
5682 unsigned i;
5683 rakPeer->requestedConnectionQueueMutex.Lock();
5684 for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
5685 {
5686 rcs=rakPeer->requestedConnectionQueue[i];
5687 if (rcs->systemAddress==systemAddress)
5688 {
5689 rakPeer->requestedConnectionQueueMutex.Unlock();
5690 unlock=false;
5691
5692 RakAssert(rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT);
5693 // You might get this when already connected because of cross-connections
5694 bool thisIPConnectedRecently=false;
5695 remoteSystem=rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
5696 // Removeme
5697 // printf("1 p=%i\n", rakPeer->mySystemAddress->port);
5698 if (remoteSystem==0)
5699 {
5700 // Removeme
5701 // printf("2 p=%i\n", rakPeer->mySystemAddress->port);
5702 if (rcs->socket.IsNull())
5703 {
5704 // Removeme
5705 // printf("3 p=%i\n", rakPeer->mySystemAddress->port);
5706 remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, length+UDP_HEADER_SIZE, guid);
5707 }
5708 else
5709 {
5710 // Removeme
5711 // printf("4 p=%i\n", rakPeer->mySystemAddress->port);
5712 remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rcs->socket, &thisIPConnectedRecently, bindingAddress, length+UDP_HEADER_SIZE, guid);
5713 }
5714
5715
5716 // printf("System %i got ID_OPEN_CONNECTION_REPLY from %i\n", rakPeer->mySystemAddress[0].port, systemAddress.port);
5717 }
5718
5719 // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
5720 // Ignore connection attempts if this IP address connected within the last 100 milliseconds
5721 if (thisIPConnectedRecently==false)
5722 {
5723 // Don't check GetRemoteSystemFromGUID, server will verify
5724 if (remoteSystem)
5725 {
5726 // RakNetTimeUS time = RakNet::GetTimeNS();
5727 remoteSystem->weInitiatedTheConnection=true;
5728 remoteSystem->connectMode=RakPeer::RemoteSystemStruct::REQUESTED_CONNECTION;
5729 if (rcs->timeoutTime!=0)
5730 remoteSystem->reliabilityLayer.SetTimeoutTime(rcs->timeoutTime);
5731
5732
5733 RakNet::BitStream temp;
5734 temp.Write( (MessageID)ID_CONNECTION_REQUEST );
5735 temp.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5736 temp.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5737 temp.Write(RakNet::GetTime());
5738
5739 if ( rcs->outgoingPasswordLength > 0 )
5740 temp.Write( ( char* ) rcs->outgoingPassword, rcs->outgoingPasswordLength );
5741
5742 rakPeer->SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, timeRead, 0 );
5743 }
5744 else
5745 {
5746 // Failed, no connections available anymore
5747 packet=rakPeer->AllocPacket(sizeof( char ), __FILE__, __LINE__);
5748 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
5749 packet->bitSize = ( sizeof( char ) * 8);
5750 packet->systemAddress = rcs->systemAddress;
5751 packet->guid=guid;
5752 rakPeer->AddPacketToProducer(packet);
5753 }
5754 }
5755
5756 rakPeer->requestedConnectionQueueMutex.Lock();
5757 for (unsigned int k=0; k < rakPeer->requestedConnectionQueue.Size(); k++)
5758 {
5759 if (rakPeer->requestedConnectionQueue[k]->systemAddress==systemAddress)
5760 {
5761 rakPeer->requestedConnectionQueue.RemoveAtIndex(k);
5762 break;
5763 }
5764 }
5765 rakPeer->requestedConnectionQueueMutex.Unlock();
5766
5767 RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
5768
5769 break;
5770 }
5771 }
5772
5773 if (unlock)
5774 rakPeer->requestedConnectionQueueMutex.Unlock();
5775
5776 return true;
5777
5778 }
5779 else if ((unsigned char)(data)[0] == (MessageID)ID_CONNECTION_ATTEMPT_FAILED ||
5780 (unsigned char)(data)[0] == (MessageID)ID_NO_FREE_INCOMING_CONNECTIONS ||
5781 (unsigned char)(data)[0] == (MessageID)ID_CONNECTION_BANNED ||
5782 (unsigned char)(data)[0] == (MessageID)ID_ALREADY_CONNECTED ||
5783 (unsigned char)(data)[0] == (MessageID)ID_INVALID_PASSWORD ||
5784 (unsigned char)(data)[0] == (MessageID)ID_IP_RECENTLY_CONNECTED ||
5785 (unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
5786 {
5787
5788 RakNet::BitStream bs((unsigned char*) data,length,false);
5789 bs.IgnoreBytes(sizeof(MessageID));
5790 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
5791 if ((unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
5792 bs.IgnoreBytes(sizeof(unsigned char));
5793
5794 RakNetGUID guid;
5795 bs.Read(guid);
5796
5797 RakPeer::RequestedConnectionStruct *rcs;
5798 bool connectionAttemptCancelled=false;
5799 unsigned i;
5800 rakPeer->requestedConnectionQueueMutex.Lock();
5801 for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
5802 {
5803 rcs=rakPeer->requestedConnectionQueue[i];
5804 if (rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT && rcs->systemAddress==systemAddress)
5805 {
5806 connectionAttemptCancelled=true;
5807
5808
5809
5810
5811 rakPeer->requestedConnectionQueue.RemoveAtIndex(i);
5812 RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
5813 break;
5814 }
5815 }
5816
5817 rakPeer->requestedConnectionQueueMutex.Unlock();
5818
5819 if (connectionAttemptCancelled)
5820 {
5821 // Tell user of connection attempt failed
5822 packet=rakPeer->AllocPacket(sizeof( char ), __FILE__, __LINE__);
5823 packet->data[ 0 ] = data[0]; // Attempted a connection and couldn't
5824 packet->bitSize = ( sizeof( char ) * 8);
5825 packet->systemAddress = systemAddress;
5826 packet->guid=guid;
5827 rakPeer->AddPacketToProducer(packet);
5828 }
5829 }
5830 else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST && length >= sizeof(unsigned char)*2)
5831 {
5832 // if (rakPeer->mySystemAddress[0].port!=60481)
5833 // return;
5834
5835 unsigned int i;
5836 //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
5837 char remoteProtocol=data[1];
5838 if (remoteProtocol!=RAKNET_PROTOCOL_VERSION)
5839 {
5840 RakNet::BitStream bs;
5841 bs.Write((MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION);
5842 bs.Write((unsigned char)RAKNET_PROTOCOL_VERSION);
5843 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5844 bs.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5845
5846 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5847 rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*)bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
5848
5849 SocketLayer::SendTo( rakNetSocket->s, (char*)bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5850 return true;
5851 }
5852
5853 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5854 rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
5855
5856 RakNetGUID guid;
5857 RakNet::BitStream bsOut;
5858 RakNet::BitStream bs((unsigned char*) data, length, false);
5859 bs.IgnoreBytes(sizeof(MessageID)*2);
5860 bs.Read(guid);
5861 bs.AlignReadToByteBoundary();
5862 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
5863 SystemAddress bindingAddress;
5864 bs.Read(bindingAddress);
5865
5866 RakPeer::RemoteSystemStruct *rssFromSA = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
5867 bool IPAddrInUse = rssFromSA != 0 && rssFromSA->isActive;
5868 RakPeer::RemoteSystemStruct *rssFromGuid = rakPeer->GetRemoteSystemFromGUID(guid, true);
5869 bool GUIDInUse = rssFromGuid != 0 && rssFromGuid->isActive;
5870
5871 // IPAddrInUse, GuidInUse, outcome
5872 // TRUE, , TRUE , ID_OPEN_CONNECTION_REPLY if they are the same, else ID_ALREADY_CONNECTED
5873 // FALSE, , TRUE , ID_ALREADY_CONNECTED (someone else took this guid)
5874 // TRUE, , FALSE , ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
5875 // FALSE , FALSE , Allow connection
5876
5877 int outcome;
5878 if (IPAddrInUse & GUIDInUse)
5879 {
5880 if (rssFromSA==rssFromGuid && rssFromSA->connectMode==RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER)
5881 {
5882 // ID_OPEN_CONNECTION_REPLY if they are the same
5883 outcome=1;
5884 }
5885 else
5886 {
5887 // ID_ALREADY_CONNECTED (restarted raknet, connected again from same ip, plus someone else took this guid)
5888 outcome=2;
5889 }
5890 }
5891 else if (IPAddrInUse==false && GUIDInUse==true)
5892 {
5893 // ID_ALREADY_CONNECTED (someone else took this guid)
5894 outcome=3;
5895 }
5896 else if (IPAddrInUse==true && GUIDInUse==false)
5897 {
5898 // ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
5899 outcome=4;
5900 }
5901 else
5902 {
5903 // Allow connection
5904 outcome=0;
5905 }
5906
5907 if (outcome==1)
5908 {
5909 // Duplicate connection request packet
5910 bsOut.Write((MessageID)ID_OPEN_CONNECTION_REPLY);
5911 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5912 bsOut.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5913 bsOut.Write(systemAddress);
5914 bsOut.PadWithZeroToByteLength(length); // Pad to the same MTU
5915 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5916 rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5917 SocketLayer::SetDoNotFragment(rakNetSocket->s, 1);
5918 SocketLayer::SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5919 SocketLayer::SetDoNotFragment(rakNetSocket->s, 0);
5920 return true;
5921 }
5922 else if (outcome!=0)
5923 {
5924 bsOut.Write((MessageID)ID_ALREADY_CONNECTED);
5925 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5926 bsOut.Write(guid);
5927 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5928 rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5929 SocketLayer::SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5930
5931 return true;
5932 }
5933
5934 if (rakPeer->AllowIncomingConnections()==false)
5935 {
5936 bsOut.Write((MessageID)ID_NO_FREE_INCOMING_CONNECTIONS);
5937 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5938 bsOut.Write(guid);
5939 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5940 rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5941 SocketLayer::SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5942
5943 return true;
5944 }
5945
5946 bool thisIPConnectedRecently=false;
5947 rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, length+UDP_HEADER_SIZE, guid);
5948
5949 if (thisIPConnectedRecently==true)
5950 {
5951 bsOut.Write((MessageID)ID_IP_RECENTLY_CONNECTED);
5952 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5953 bsOut.Write(guid);
5954 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5955 rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5956 SocketLayer::SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5957
5958 return true;
5959 }
5960
5961 bsOut.Write((MessageID)ID_OPEN_CONNECTION_REPLY);
5962 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5963 bsOut.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5964 bsOut.Write(systemAddress);
5965 bsOut.PadWithZeroToByteLength(length); // Pad to the same MTU
5966 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
5967 rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5968 SocketLayer::SetDoNotFragment(rakNetSocket->s, 1);
5969 SocketLayer::SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
5970 SocketLayer::SetDoNotFragment(rakNetSocket->s, 0);
5971
5972
5973 }
5974 return true;
5975 }
5976
5977 return false;
5978 }
5979 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ProcessNetworkPacket(const SystemAddress systemAddress,const char * data,const int length,RakPeer * rakPeer,RakNetTimeUS timeRead)5980 void ProcessNetworkPacket( const SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetTimeUS timeRead )
5981 {
5982 ProcessNetworkPacket(systemAddress,data,length,rakPeer,rakPeer->socketList[0],timeRead);
5983 }
ProcessNetworkPacket(const SystemAddress systemAddress,const char * data,const int length,RakPeer * rakPeer,RakNetSmartPtr<RakNetSocket> rakNetSocket,RakNetTimeUS timeRead)5984 void ProcessNetworkPacket( const SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSmartPtr<RakNetSocket> rakNetSocket, RakNetTimeUS timeRead )
5985 {
5986 RakAssert(systemAddress.port);
5987 bool isOfflineMessage;
5988 if (ProcessOfflineNetworkPacket(systemAddress, data, length, rakPeer, rakNetSocket, &isOfflineMessage, timeRead))
5989 {
5990 return;
5991 }
5992
5993 Packet *packet;
5994 RakPeer::RemoteSystemStruct *remoteSystem;
5995
5996 // See if this datagram came from a connected system
5997 remoteSystem = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
5998 if ( remoteSystem )
5999 {
6000 if (remoteSystem->connectMode==RakPeer::RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET && (length & 15)==0) // & 15 = mod 16
6001 {
6002 // Test the key before setting it
6003 unsigned int newLength;
6004 char output[ MAXIMUM_MTU_SIZE ];
6005 DataBlockEncryptor testEncryptor;
6006 testEncryptor.SetKey(remoteSystem->AESKey);
6007 //if ( testEncryptor.Decrypt( ( unsigned char* ) data, length, (unsigned char*) output,&newLength ) == true )
6008 if ( testEncryptor.Decrypt( ( unsigned char* ) data, length, (unsigned char*) output, &newLength ) == true )
6009 remoteSystem->reliabilityLayer.SetEncryptionKey( remoteSystem->AESKey);
6010 }
6011
6012 // Handle regular incoming data
6013 // HandleSocketReceiveFromConnectedPlayer is only safe to be called from the same thread as Update, which is this thread
6014 if ( isOfflineMessage==false)
6015 {
6016 if (remoteSystem->reliabilityLayer.HandleSocketReceiveFromConnectedPlayer(
6017 data, length, systemAddress, rakPeer->messageHandlerList, remoteSystem->MTUSize,
6018 rakNetSocket->s, &rnr, rakNetSocket->remotePortRakNetWasStartedOn_PS3, timeRead) == false)
6019 {
6020 // These kinds of packets may have been duplicated and incorrectly determined to be
6021 // cheat packets. Anything else really is a cheat packet
6022 if ( !(
6023 ( (unsigned char)data[0] == ID_CONNECTION_BANNED ) ||
6024 ( (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST ) ||
6025 ( (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY ) ||
6026 ( (unsigned char)data[0] == ID_CONNECTION_ATTEMPT_FAILED ) ||
6027 ( (unsigned char)data[0] == ID_IP_RECENTLY_CONNECTED ) ||
6028 ( (unsigned char)data[0] == ID_INCOMPATIBLE_PROTOCOL_VERSION ))
6029 )
6030 {
6031 // Unknown message. Could be caused by old out of order stuff from unconnected or no longer connected systems, etc.
6032 packet=rakPeer->AllocPacket(1, __FILE__, __LINE__);
6033 packet->data[ 0 ] = ID_MODIFIED_PACKET;
6034 packet->bitSize = sizeof( char ) * 8;
6035 packet->systemAddress = systemAddress;
6036 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
6037 packet->guid=remoteSystem->guid;
6038 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6039 rakPeer->AddPacketToProducer(packet);
6040 }
6041 }
6042 }
6043 }
6044 }
6045 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GenerateSeedFromGuid(void)6046 unsigned int RakPeer::GenerateSeedFromGuid(void)
6047 {
6048 /*
6049 // Construct a random seed based on the initial guid value, and the last digits of the difference to each subsequent number
6050 // This assumes that only the last 3 bits of each guidId integer has a meaningful amount of randomness between it and the prior number
6051 unsigned int t = guid.g[0];
6052 unsigned int i;
6053 for (i=1; i < sizeof(guid.g) / sizeof(guid.g[0]); i++)
6054 {
6055 unsigned int diff = guid.g[i]-guid.g[i-1];
6056 unsigned int diff3Bits = diff & 0x0007;
6057 diff3Bits <<= 29;
6058 diff3Bits >>= (i-1)*3;
6059 t ^= diff3Bits;
6060 }
6061
6062 return t;
6063 */
6064 return (unsigned int) ((myGuid.g >> 32) ^ myGuid.g);
6065 }
6066 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DerefAllSockets(void)6067 void RakPeer::DerefAllSockets(void)
6068 {
6069 unsigned int i;
6070 for (i=0; i < socketList.Size(); i++)
6071 {
6072 socketList[i].SetNull();
6073 }
6074 socketList.Clear(false, __FILE__, __LINE__);
6075 }
6076 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRakNetSocketFromUserConnectionSocketIndex(unsigned int userIndex) const6077 unsigned int RakPeer::GetRakNetSocketFromUserConnectionSocketIndex(unsigned int userIndex) const
6078 {
6079 unsigned int i;
6080 for (i=0; i < socketList.Size(); i++)
6081 {
6082 if (socketList[i]->userConnectionSocketIndex==userIndex)
6083 return i;
6084 }
6085 RakAssert("GetRakNetSocketFromUserConnectionSocketIndex failed" && 0);
6086 return (unsigned int) -1;
6087 }
6088 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RunUpdateCycle(RakNetTimeUS timeNS,RakNetTime timeMS)6089 bool RakPeer::RunUpdateCycle( RakNetTimeUS timeNS, RakNetTime timeMS )
6090 {
6091 RakPeer::RemoteSystemStruct * remoteSystem;
6092 unsigned remoteSystemIndex;
6093 Packet *packet;
6094 // int currentSentBytes,currentReceivedBytes;
6095 // unsigned numberOfBytesUsed;
6096 BitSize_t numberOfBitsUsed;
6097 //SystemAddress authoritativeClientSystemAddress;
6098 BitSize_t bitSize;
6099 unsigned int byteSize;
6100 unsigned char *data;
6101 SystemAddress systemAddress;
6102 BufferedCommandStruct *bcs;
6103 bool callerDataAllocationUsed;
6104 RakNetStatistics *rnss;
6105
6106 /*
6107 int errorCode;
6108 int gotData;
6109 unsigned connectionSocketIndex;
6110 for (connectionSocketIndex=0; connectionSocketIndex < socketList.Size(); connectionSocketIndex++)
6111 {
6112 do
6113 {
6114 gotData = SocketLayer::RecvFrom( socketList[connectionSocketIndex]->s, this, &errorCode, socketList[connectionSocketIndex], socketList[connectionSocketIndex]->remotePortRakNetWasStartedOn_PS3 );
6115
6116 if ( gotData == -1 )
6117 {
6118 #ifdef _WIN32
6119 if ( errorCode == WSAECONNRESET )
6120 {
6121 gotData=false;
6122 }
6123 else
6124 if ( errorCode != 0 && endThreads == false )
6125 {
6126 #ifdef _DO_PRINTF
6127 RAKNET_DEBUG_PRINTF( "Server RecvFrom critical failure!\n" );
6128 #endif
6129 // Some kind of critical error
6130 // peer->isRecvfromThreadActive=false;
6131 endThreads = true;
6132 Shutdown( 0, 0 );
6133 return false;
6134 }
6135
6136 #else
6137 if ( errorCode == -1 )
6138 {
6139 // isRecvfromThreadActive=false;
6140 endThreads = true;
6141 Shutdown( 0 );
6142 return false;
6143 }
6144 #endif
6145 }
6146
6147 if ( endThreads )
6148 return false;
6149 }
6150 while ( gotData>0 ); // Read until there is nothing left
6151 }
6152 */
6153
6154 // This is here so RecvFromBlocking actually gets data from the same thread
6155 if (SocketLayer::GetSocketLayerOverride())
6156 {
6157 SystemAddress sender;
6158 char dataOut[ MAXIMUM_MTU_SIZE ];
6159 int len = SocketLayer::GetSocketLayerOverride()->RakNetRecvFrom(socketList[0]->s,this,dataOut,&sender,true);
6160 if (len>0)
6161 {
6162 ProcessNetworkPacket( sender, dataOut, len, this, socketList[0], RakNet::GetTimeUS() );
6163 return 1;
6164 }
6165 }
6166
6167 unsigned int socketListIndex;
6168 RakPeer::RecvFromStruct *recvFromStruct;
6169 while ((recvFromStruct=bufferedPackets.PopInaccurate())!=0)
6170 {
6171 for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
6172 {
6173 if (socketList[socketListIndex]->s==recvFromStruct->s)
6174 break;
6175 }
6176 if (socketListIndex!=socketList.Size())
6177 ProcessNetworkPacket(recvFromStruct->systemAddress, recvFromStruct->data, recvFromStruct->bytesRead, this, socketList[socketListIndex], recvFromStruct->timeRead);
6178 bufferedPackets.Deallocate(recvFromStruct, __FILE__,__LINE__);
6179 }
6180
6181 #ifdef _RAKNET_THREADSAFE
6182 while ((bcs=bufferedCommands.PopInaccurate())!=0)
6183 #else
6184 // Process all the deferred user thread Send and connect calls
6185 while ((bcs=bufferedCommands.ReadLock())!=0)
6186 #endif
6187 {
6188 if (bcs->command==BufferedCommandStruct::BCS_SEND)
6189 {
6190 // GetTime is a very slow call so do it once and as late as possible
6191 if (timeNS==0)
6192 {
6193 timeNS = RakNet::GetTimeNS();
6194 timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
6195 }
6196
6197 callerDataAllocationUsed=SendImmediate((char*)bcs->data, bcs->numberOfBitsToSend, bcs->priority, bcs->reliability, bcs->orderingChannel, bcs->systemIdentifier, bcs->broadcast, true, timeNS, bcs->receipt);
6198 if ( callerDataAllocationUsed==false )
6199 {
6200 rakFree_Ex(bcs->data, __FILE__, __LINE__ );
6201 bcs->data=0;
6202 }
6203
6204 // 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
6205 if (bcs->connectionMode!=RemoteSystemStruct::NO_ACTION )
6206 {
6207 remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
6208 if (remoteSystem)
6209 remoteSystem->connectMode=bcs->connectionMode;
6210 }
6211 }
6212 else if (bcs->command==BufferedCommandStruct::BCS_SEND_OUT_OF_BAND)
6213 {
6214 char host[128];
6215 bcs->systemIdentifier.systemAddress.ToString(false,host);
6216
6217 unsigned i;
6218 for (i=0; i < messageHandlerList.Size(); i++)
6219 messageHandlerList[i]->OnDirectSocketSend(bcs->data, bcs->numberOfBitsToSend, systemAddress);
6220 unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(bcs->connectionSocketIndex);
6221 SocketLayer::SendTo( socketList[realIndex]->s, bcs->data, (int) BITS_TO_BYTES(bcs->numberOfBitsToSend), ( char* ) host, bcs->systemIdentifier.systemAddress.port, socketList[realIndex]->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ );
6222
6223 rakFree_Ex(bcs->data, __FILE__, __LINE__ );
6224 bcs->data=0;
6225 }
6226 else if (bcs->command==BufferedCommandStruct::BCS_CLOSE_CONNECTION)
6227 {
6228 CloseConnectionInternal(bcs->systemIdentifier, false, true, bcs->orderingChannel, bcs->priority);
6229 }
6230 else if (bcs->command==BufferedCommandStruct::BCS_CHANGE_SYSTEM_ADDRESS)
6231 {
6232 // Reroute
6233 RakPeer::RemoteSystemStruct *rssFromGuid = GetRemoteSystem(bcs->systemIdentifier.rakNetGuid,true,true);
6234 if (rssFromGuid!=0)
6235 {
6236 unsigned int existingSystemIndex = GetRemoteSystemIndex(rssFromGuid->systemAddress);
6237 ReferenceRemoteSystem(bcs->systemIdentifier.systemAddress, existingSystemIndex);
6238 }
6239 }
6240 else if (bcs->command==BufferedCommandStruct::BCS_GET_SOCKET)
6241 {
6242 SocketQueryOutput *sqo;
6243 if (bcs->systemIdentifier.IsUndefined())
6244 {
6245 #ifdef _RAKNET_THREADSAFE
6246 sqo = socketQueryOutput.Allocate( __FILE__, __LINE__ );
6247 sqo->sockets=socketList;
6248 socketQueryOutput.Push(sqo);
6249 #else
6250 sqo = socketQueryOutput.WriteLock();
6251 sqo->sockets=socketList;
6252 socketQueryOutput.WriteUnlock();
6253 #endif
6254 }
6255 else
6256 {
6257 remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
6258 #ifdef _RAKNET_THREADSAFE
6259 sqo = socketQueryOutput.Allocate( __FILE__, __LINE__ );
6260 #else
6261 sqo = socketQueryOutput.WriteLock();
6262 #endif
6263 sqo->sockets.Clear(false, __FILE__, __LINE__);
6264 if (remoteSystem)
6265 {
6266 sqo->sockets.Push(remoteSystem->rakNetSocket, __FILE__, __LINE__ );
6267 }
6268 else
6269 {
6270 // Leave empty smart pointer
6271 }
6272 #ifdef _RAKNET_THREADSAFE
6273 socketQueryOutput.Push(sqo);
6274 #else
6275 socketQueryOutput.WriteUnlock();
6276 #endif
6277 }
6278
6279 }
6280
6281
6282 #ifdef _RAKNET_THREADSAFE
6283 bufferedCommands.Deallocate(bcs, __FILE__,__LINE__);
6284 #else
6285 bufferedCommands.ReadUnlock();
6286 #endif
6287 }
6288
6289 if (requestedConnectionQueue.IsEmpty()==false)
6290 {
6291 if (timeNS==0)
6292 {
6293 timeNS = RakNet::GetTimeNS();
6294 timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
6295 }
6296
6297 bool condition1, condition2;
6298 RequestedConnectionStruct *rcs;
6299 unsigned requestedConnectionQueueIndex=0;
6300 requestedConnectionQueueMutex.Lock();
6301 while (requestedConnectionQueueIndex < requestedConnectionQueue.Size())
6302 {
6303 rcs = requestedConnectionQueue[requestedConnectionQueueIndex];
6304 requestedConnectionQueueMutex.Unlock();
6305 if (rcs->nextRequestTime < timeMS)
6306 {
6307 condition1=rcs->requestsMade==rcs->sendConnectionAttemptCount+1;
6308 condition2=(bool)((rcs->systemAddress==UNASSIGNED_SYSTEM_ADDRESS)==1);
6309 // If too many requests made or a hole then remove this if possible, otherwise invalidate it
6310 if (condition1 || condition2)
6311 {
6312 if (rcs->data)
6313 {
6314 rakFree_Ex(rcs->data, __FILE__, __LINE__ );
6315 rcs->data=0;
6316 }
6317
6318 if (condition1 && !condition2 && rcs->actionToTake==RequestedConnectionStruct::CONNECT)
6319 {
6320 // Tell user of connection attempt failed
6321 packet=AllocPacket(sizeof( char ), __FILE__, __LINE__);
6322 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
6323 packet->bitSize = ( sizeof( char ) * 8);
6324 packet->systemAddress = rcs->systemAddress;
6325 AddPacketToProducer(packet);
6326 }
6327
6328 RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
6329
6330 requestedConnectionQueueMutex.Lock();
6331 for (unsigned int k=0; k < requestedConnectionQueue.Size(); k++)
6332 {
6333 if (requestedConnectionQueue[k]==rcs)
6334 {
6335 requestedConnectionQueue.RemoveAtIndex(k);
6336 break;
6337 }
6338 }
6339 requestedConnectionQueueMutex.Unlock();
6340 }
6341 else
6342 {
6343
6344 int MTUSizeIndex = rcs->requestsMade / (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES);
6345 if (MTUSizeIndex>=NUM_MTU_SIZES)
6346 MTUSizeIndex=NUM_MTU_SIZES-1;
6347 rcs->requestsMade++;
6348 rcs->nextRequestTime=timeMS+rcs->timeBetweenSendConnectionAttemptsMS;
6349 // char c[MAXIMUM_MTU_SIZE];
6350 // c[0] = ID_OPEN_CONNECTION_REQUEST;
6351 // c[1] = RAKNET_PROTOCOL_VERSION;
6352
6353 RakNet::BitStream bitStream;
6354 bitStream.Write((MessageID)ID_OPEN_CONNECTION_REQUEST);
6355 bitStream.Write((MessageID)RAKNET_PROTOCOL_VERSION);
6356 bitStream.Write(myGuid);
6357 bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
6358 bitStream.Write(rcs->systemAddress);
6359 // Pad out to MTU test size
6360 bitStream.PadWithZeroToByteLength(mtuSizes[MTUSizeIndex]-UDP_HEADER_SIZE);
6361
6362 // bool isProperOfflineMessage=memcmp(bitStream.GetData()+sizeof(MessageID)*2 + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
6363 // RakAssert(isProperOfflineMessage);
6364
6365 char str[256];
6366 rcs->systemAddress.ToString(true,str);
6367
6368 //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
6369
6370 unsigned i;
6371 for (i=0; i < messageHandlerList.Size(); i++)
6372 messageHandlerList[i]->OnDirectSocketSend((const char*) bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), rcs->systemAddress);
6373
6374 if (rcs->socket.IsNull())
6375 {
6376 SocketLayer::SetDoNotFragment(socketList[rcs->socketIndex]->s, 1);
6377 RakNetTime sendToStart=RakNet::GetTime();
6378 if (SocketLayer::SendTo( socketList[rcs->socketIndex]->s, (const char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), rcs->systemAddress.binaryAddress, rcs->systemAddress.port, socketList[rcs->socketIndex]->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ )==-10040)
6379 {
6380 if (rcs->requestsMade==rcs->sendConnectionAttemptCount+1)
6381 {
6382 // every size is returning -10040
6383 rcs->requestsMade=rcs->sendConnectionAttemptCount+1;
6384 }
6385 else
6386 {
6387 // Don't use this MTU size again
6388 rcs->requestsMade = (unsigned char) ((MTUSizeIndex + 1) * (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES));
6389 rcs->nextRequestTime=timeMS;
6390 }
6391 }
6392 else
6393 {
6394 RakNetTime sendToEnd=RakNet::GetTime();
6395 if (sendToEnd-sendToStart>100)
6396 {
6397 // Drop to lowest MTU
6398 int lowestMtuIndex = rcs->sendConnectionAttemptCount/NUM_MTU_SIZES * (NUM_MTU_SIZES - 1);
6399 if (lowestMtuIndex > rcs->requestsMade)
6400 {
6401 rcs->requestsMade = lowestMtuIndex;
6402 rcs->nextRequestTime=timeMS;
6403 }
6404 else
6405 rcs->requestsMade=rcs->sendConnectionAttemptCount+1;
6406 }
6407 }
6408 SocketLayer::SetDoNotFragment(socketList[rcs->socketIndex]->s, 0);
6409 }
6410 else
6411 {
6412 SocketLayer::SetDoNotFragment(rcs->socket->s, 1);
6413 RakNetTime sendToStart=RakNet::GetTime();
6414 if (SocketLayer::SendTo( rcs->socket->s, (const char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), rcs->systemAddress.binaryAddress, rcs->systemAddress.port, socketList[rcs->socketIndex]->remotePortRakNetWasStartedOn_PS3, __FILE__, __LINE__ )==-10040)
6415 {
6416 if (rcs->requestsMade==rcs->sendConnectionAttemptCount+1)
6417 {
6418 // every size is returning -10040
6419 rcs->requestsMade=rcs->sendConnectionAttemptCount+1;
6420 }
6421 else
6422 {
6423 // Don't use this MTU size again
6424 rcs->requestsMade = (unsigned char) ((MTUSizeIndex + 1) * (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES));
6425 rcs->nextRequestTime=timeMS;
6426 }
6427 }
6428 else
6429 {
6430 RakNetTime sendToEnd=RakNet::GetTime();
6431 if (sendToEnd-sendToStart>100)
6432 {
6433 // Drop to lowest MTU
6434 int lowestMtuIndex = rcs->sendConnectionAttemptCount/NUM_MTU_SIZES * (NUM_MTU_SIZES - 1);
6435 if (lowestMtuIndex > rcs->requestsMade)
6436 {
6437 rcs->requestsMade = lowestMtuIndex;
6438 rcs->nextRequestTime=timeMS;
6439 }
6440 else
6441 rcs->requestsMade=rcs->sendConnectionAttemptCount+1;
6442 }
6443 }
6444 SocketLayer::SetDoNotFragment(socketList[rcs->socketIndex]->s, 0);
6445 }
6446 // printf("ID_OPEN_CONNECTION_REQUEST\n");
6447
6448 requestedConnectionQueueIndex++;
6449 }
6450 }
6451 else
6452 requestedConnectionQueueIndex++;
6453
6454 requestedConnectionQueueMutex.Lock();
6455 }
6456 requestedConnectionQueueMutex.Unlock();
6457 }
6458
6459 // remoteSystemList in network thread
6460 for ( remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
6461 //for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; ++remoteSystemIndex )
6462 {
6463 // I'm using systemAddress from remoteSystemList but am not locking it because this loop is called very frequently and it doesn't
6464 // matter if we miss or do an extra update. The reliability layers themselves never care which player they are associated with
6465 //systemAddress = remoteSystemList[ remoteSystemIndex ].systemAddress;
6466 // Allow the systemAddress for this remote system list to change. We don't care if it changes now.
6467 // remoteSystemList[ remoteSystemIndex ].allowSystemAddressAssigment=true;
6468 if ( remoteSystemList[ remoteSystemIndex ].isActive )
6469 {
6470 systemAddress = remoteSystemList[ remoteSystemIndex ].systemAddress;
6471 RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
6472
6473 // Found an active remote system
6474 remoteSystem = remoteSystemList + remoteSystemIndex;
6475 // Update is only safe to call from the same thread that calls HandleSocketReceiveFromConnectedPlayer,
6476 // which is this thread
6477
6478 if (timeNS==0)
6479 {
6480 timeNS = RakNet::GetTimeNS();
6481 timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
6482 //RAKNET_DEBUG_PRINTF("timeNS = %I64i timeMS=%i\n", timeNS, timeMS);
6483 }
6484
6485
6486 if (timeMS > remoteSystem->lastReliableSend && timeMS-remoteSystem->lastReliableSend > defaultTimeoutTime/2 && remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
6487 {
6488 // If no reliable packets are waiting for an ack, do a one byte reliable send so that disconnections are noticed
6489 RakNetStatistics rakNetStatistics;
6490 rnss=remoteSystem->reliabilityLayer.GetStatistics(&rakNetStatistics);
6491 if (rnss->messagesInResendBuffer==0)
6492 {
6493 PingInternal( systemAddress, true, RELIABLE );
6494 /*
6495 unsigned char keepAlive=ID_DETECT_LOST_CONNECTIONS;
6496 SendImmediate((char*)&keepAlive,8,LOW_PRIORITY, RELIABLE, 0, remoteSystem->systemAddress, false, false, timeNS);
6497 */
6498 //remoteSystem->lastReliableSend=timeMS+remoteSystem->reliabilityLayer.GetTimeoutTime();
6499 remoteSystem->lastReliableSend=timeMS;
6500 }
6501 }
6502
6503 remoteSystem->reliabilityLayer.Update( remoteSystem->rakNetSocket->s, systemAddress, remoteSystem->MTUSize, timeNS, maxOutgoingBPS, messageHandlerList, &rnr, remoteSystem->rakNetSocket->remotePortRakNetWasStartedOn_PS3 ); // systemAddress only used for the internet simulator test
6504
6505 // Check for failure conditions
6506 if ( remoteSystem->reliabilityLayer.IsDeadConnection() ||
6507 ((remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY) && remoteSystem->reliabilityLayer.IsOutgoingDataWaiting()==false) ||
6508 (remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK && (remoteSystem->reliabilityLayer.AreAcksWaiting()==false || remoteSystem->reliabilityLayer.AckTimeout(timeMS)==true)) ||
6509 ((
6510 (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
6511 remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
6512 remoteSystem->connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
6513 remoteSystem->connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET)
6514 && timeMS > remoteSystem->connectionTime && timeMS - remoteSystem->connectionTime > 10000))
6515 )
6516 {
6517 // RAKNET_DEBUG_PRINTF("timeMS=%i remoteSystem->connectionTime=%i\n", timeMS, remoteSystem->connectionTime );
6518
6519 // Failed. Inform the user?
6520 // TODO - RakNet 4.0 - Return a different message identifier for DISCONNECT_ASAP_SILENTLY and DISCONNECT_ASAP than for DISCONNECT_ON_NO_ACK
6521 // The first two mean we called CloseConnection(), the last means the other system sent us ID_DISCONNECTION_NOTIFICATION
6522 if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED || remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION
6523 || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
6524 {
6525
6526 // RakNet::BitStream undeliveredMessages;
6527 // remoteSystem->reliabilityLayer.GetUndeliveredMessages(&undeliveredMessages,remoteSystem->MTUSize);
6528
6529 // packet=AllocPacket(sizeof( char ) + undeliveredMessages.GetNumberOfBytesUsed());
6530 packet=AllocPacket(sizeof( char ), __FILE__, __LINE__);
6531 if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
6532 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
6533 else if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
6534 packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
6535 else
6536 packet->data[ 0 ] = ID_DISCONNECTION_NOTIFICATION; // DeadConnection
6537
6538 // memcpy(packet->data+1, undeliveredMessages.GetData(), undeliveredMessages.GetNumberOfBytesUsed());
6539
6540 packet->guid = remoteSystem->guid;
6541 packet->systemAddress = systemAddress;
6542 packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
6543 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6544
6545 AddPacketToProducer(packet);
6546 }
6547 // else connection shutting down, don't bother telling the user
6548
6549 #ifdef _DO_PRINTF
6550 RAKNET_DEBUG_PRINTF("Connection dropped for player %i:%i\n", systemAddress.binaryAddress, systemAddress.port);
6551 #endif
6552 CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
6553 continue;
6554 }
6555
6556 // Did the reliability layer detect a modified packet?
6557 if ( remoteSystem->reliabilityLayer.IsCheater() )
6558 {
6559 packet=AllocPacket(sizeof(char), __FILE__, __LINE__);
6560 packet->bitSize=8;
6561 packet->data[ 0 ] = (MessageID)ID_MODIFIED_PACKET;
6562 packet->systemAddress = systemAddress;
6563 packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
6564 packet->guid = remoteSystem->guid;
6565 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6566 AddPacketToProducer(packet);
6567 continue;
6568 }
6569
6570 // Ping this guy if it is time to do so
6571 if ( remoteSystem->connectMode==RemoteSystemStruct::CONNECTED && timeMS > remoteSystem->nextPingTime && ( occasionalPing || remoteSystem->lowestPing == (unsigned short)-1 ) )
6572 {
6573 remoteSystem->nextPingTime = timeMS + 5000;
6574 PingInternal( systemAddress, true, UNRELIABLE );
6575
6576 // Update again immediately after this tick so the ping goes out right away
6577 quitAndDataEvents.SetEvent();
6578 }
6579
6580 // Find whoever has the lowest player ID
6581 //if (systemAddress < authoritativeClientSystemAddress)
6582 // authoritativeClientSystemAddress=systemAddress;
6583
6584 // Does the reliability layer have any packets waiting for us?
6585 // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
6586 bitSize = remoteSystem->reliabilityLayer.Receive( &data );
6587
6588 while ( bitSize > 0 )
6589 {
6590 // These types are for internal use and should never arrive from a network packet
6591 if (data[0]==ID_CONNECTION_ATTEMPT_FAILED || data[0]==ID_MODIFIED_PACKET)
6592 {
6593 RakAssert(0);
6594 bitSize=0;
6595 continue;
6596 }
6597
6598 // Put the input through compression if necessary
6599 if ( inputTree )
6600 {
6601 RakNet::BitStream dataBitStream( MAXIMUM_MTU_SIZE );
6602 // Since we are decompressing input, we need to copy to a bitstream, decompress, then copy back to a probably
6603 // larger data block. It's slow, but the user should have known that anyway
6604 dataBitStream.Reset();
6605 dataBitStream.WriteAlignedBytes( ( unsigned char* ) data, BITS_TO_BYTES( bitSize ) );
6606 rawBytesReceived += (unsigned int) dataBitStream.GetNumberOfBytesUsed();
6607
6608 // numberOfBytesUsed = dataBitStream.GetNumberOfBytesUsed();
6609 numberOfBitsUsed = dataBitStream.GetNumberOfBitsUsed();
6610 //rawBytesReceived += numberOfBytesUsed;
6611 // Decompress the input data.
6612
6613 if (numberOfBitsUsed>0)
6614 {
6615 unsigned char *dataCopy = (unsigned char*) rakMalloc_Ex( (unsigned int) dataBitStream.GetNumberOfBytesUsed(), __FILE__, __LINE__ );
6616 memcpy( dataCopy, dataBitStream.GetData(), (size_t) dataBitStream.GetNumberOfBytesUsed() );
6617 dataBitStream.Reset();
6618 inputTree->DecodeArray( dataCopy, numberOfBitsUsed, &dataBitStream );
6619 compressedBytesReceived += (unsigned int) dataBitStream.GetNumberOfBytesUsed();
6620 rakFree_Ex(dataCopy, __FILE__, __LINE__ );
6621
6622 byteSize = (unsigned int) dataBitStream.GetNumberOfBytesUsed();
6623
6624 if ( byteSize > BITS_TO_BYTES( bitSize ) ) // Probably the case - otherwise why decompress?
6625 {
6626 rakFree_Ex(data, __FILE__, __LINE__ );
6627 data = (unsigned char*) rakMalloc_Ex( (size_t) byteSize, __FILE__, __LINE__ );
6628 }
6629 bitSize = (BitSize_t) dataBitStream.GetNumberOfBitsUsed();
6630 memcpy( data, dataBitStream.GetData(), byteSize );
6631 }
6632 else
6633 byteSize=0;
6634 }
6635 else
6636 // Fast and easy - just use the data that was returned
6637 byteSize = (unsigned int) BITS_TO_BYTES( bitSize );
6638
6639 // For unknown senders we only accept a few specific packets
6640 if (remoteSystem->connectMode==RemoteSystemStruct::UNVERIFIED_SENDER)
6641 {
6642 if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
6643 {
6644 ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
6645 rakFree_Ex(data, __FILE__, __LINE__ );
6646 }
6647 else
6648 {
6649 CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
6650 #ifdef _DO_PRINTF
6651 RAKNET_DEBUG_PRINTF("Temporarily banning %i:%i for sending nonsense data\n", systemAddress.binaryAddress, systemAddress.port);
6652 #endif
6653
6654 char str1[64];
6655 systemAddress.ToString(false, str1);
6656 AddToBanList(str1, remoteSystem->reliabilityLayer.GetTimeoutTime());
6657
6658
6659 rakFree_Ex(data, __FILE__, __LINE__ );
6660 }
6661 }
6662 else
6663 {
6664 // However, if we are connected we still take a connection request in case both systems are trying to connect to each other
6665 // at the same time
6666 if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
6667 {
6668 // 04/27/06 This is wrong. With cross connections, we can both have initiated the connection are in state REQUESTED_CONNECTION
6669 // 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))
6670 if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
6671 {
6672 ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
6673 }
6674 else
6675 {
6676
6677 RakNet::BitStream bs((unsigned char*) data,byteSize,false);
6678 bs.IgnoreBytes(sizeof(MessageID));
6679 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
6680 bs.IgnoreBytes(RakNetGUID::size());
6681 RakNetTime incomingTimestamp;
6682 bs.Read(incomingTimestamp);
6683
6684 // Got a connection request message from someone we are already connected to. Just reply normally.
6685 // This can happen due to race conditions with the fully connected mesh
6686 SendConnectionRequestAccepted(remoteSystem, incomingTimestamp);
6687 }
6688 rakFree_Ex(data, __FILE__, __LINE__ );
6689 }
6690 else if ( (unsigned char) data[ 0 ] == ID_NEW_INCOMING_CONNECTION && byteSize > sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(RakNetTime)*2 )
6691 {
6692
6693 if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
6694 // WHy was this here? In CrossConnectinoTest it resulted in returning both ID_NEW_INCOMING_CONNECTION and ID_CONNECTION_REQUEST_ACCEPTED
6695 // remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
6696 remoteSystem->connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET)
6697 {
6698 // Removeme
6699 // static int count5=1;
6700 // printf("Processed ID_NEW_INCOMING_CONNECTION count=%i\n", count5++);
6701
6702 remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
6703 PingInternal( systemAddress, true, UNRELIABLE );
6704
6705 // Update again immediately after this tick so the ping goes out right away
6706 quitAndDataEvents.SetEvent();
6707
6708 RakNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
6709 SystemAddress bsSystemAddress;
6710
6711 inBitStream.IgnoreBits(8);
6712 inBitStream.Read(bsSystemAddress);
6713 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
6714 inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
6715
6716 RakNetTime sendPingTime, sendPongTime;
6717 inBitStream.Read(sendPingTime);
6718 inBitStream.Read(sendPongTime);
6719 OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
6720
6721 // Overwrite the data in the packet
6722 // NewIncomingConnectionStruct newIncomingConnectionStruct;
6723 // RakNet::BitStream nICS_BS( data, NewIncomingConnectionStruct_Size, false );
6724 // newIncomingConnectionStruct.Deserialize( nICS_BS );
6725
6726 remoteSystem->myExternalSystemAddress = bsSystemAddress;
6727 firstExternalID=bsSystemAddress;
6728
6729 // Send this info down to the game
6730 packet=AllocPacket(byteSize, data, __FILE__, __LINE__);
6731 packet->bitSize = bitSize;
6732 packet->systemAddress = systemAddress;
6733 packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
6734 packet->guid = remoteSystem->guid;
6735 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6736 AddPacketToProducer(packet);
6737 }
6738 }
6739 else if ( (unsigned char) data[ 0 ] == ID_CONNECTED_PONG && byteSize == sizeof(unsigned char)+sizeof(RakNetTime)*2 )
6740 {
6741 RakNetTime sendPingTime, sendPongTime;
6742
6743 // Copy into the ping times array the current time - the value returned
6744 // First extract the sent ping
6745 RakNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
6746 //PingStruct ps;
6747 //ps.Deserialize(psBS);
6748 inBitStream.IgnoreBits(8);
6749 inBitStream.Read(sendPingTime);
6750 inBitStream.Read(sendPongTime);
6751
6752 OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
6753
6754 rakFree_Ex(data, __FILE__, __LINE__ );
6755 }
6756 else if ( (unsigned char)data[0] == ID_INTERNAL_PING && byteSize == sizeof(unsigned char)+sizeof(RakNetTime) )
6757 {
6758 RakNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
6759 inBitStream.IgnoreBits(8);
6760 RakNetTime sendPingTime;
6761 inBitStream.Read(sendPingTime);
6762
6763 RakNet::BitStream outBitStream;
6764 outBitStream.Write((MessageID)ID_CONNECTED_PONG);
6765 outBitStream.Write(sendPingTime);
6766 timeMS = RakNet::GetTime();
6767 timeNS = RakNet::GetTimeNS();
6768 outBitStream.Write(timeMS);
6769 SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, UNRELIABLE, 0, systemAddress, false, false, timeNS, 0 );
6770
6771 // Update again immediately after this tick so the ping goes out right away
6772 quitAndDataEvents.SetEvent();
6773
6774 rakFree_Ex(data, __FILE__, __LINE__ );
6775 }
6776 else if ( (unsigned char) data[ 0 ] == ID_DISCONNECTION_NOTIFICATION )
6777 {
6778 // We shouldn't close the connection immediately because we need to ack the ID_DISCONNECTION_NOTIFICATION
6779 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ON_NO_ACK;
6780 rakFree_Ex(data, __FILE__, __LINE__ );
6781
6782 // AddPacketToProducer(packet);
6783 }
6784 else if ( (unsigned char) data[ 0 ] == ID_RPC_MAPPING )
6785 {
6786 RakNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
6787 RPCIndex index;
6788 char output[256];
6789 inBitStream.IgnoreBits(8);
6790 stringCompressor->DecodeString(output, 255, &inBitStream);
6791 inBitStream.ReadCompressed(index);
6792 remoteSystem->rpcMap.AddIdentifierAtIndex((char*)output,index);
6793 rakFree_Ex(data, __FILE__, __LINE__ );
6794 }
6795 #if !defined(_WIN32_WCE)
6796 else if ( (unsigned char)(data)[0] == ID_SECURED_CONNECTION_RESPONSE &&
6797 byteSize == 1 + sizeof( uint32_t ) + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS + 20 )
6798 {
6799 SecuredConnectionConfirmation( remoteSystem, (char*)data );
6800 rakFree_Ex(data, __FILE__, __LINE__ );
6801 }
6802 else if ( (unsigned char)(data)[0] == ID_SECURED_CONNECTION_CONFIRMATION &&
6803 byteSize == 1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS + sizeof(RakNetTime) )
6804 {
6805 CSHA1 sha1;
6806 bool confirmedHash;
6807 //bool newRandNumber;
6808
6809 confirmedHash = false;
6810
6811 // Hash the SYN-Cookie
6812 // s2c syn-cookie = SHA1_HASH(source ip address + source port + random number)
6813 sha1.Reset();
6814 sha1.Update( ( unsigned char* ) & systemAddress.binaryAddress, sizeof( systemAddress.binaryAddress ) );
6815 sha1.Update( ( unsigned char* ) & systemAddress.port, sizeof( systemAddress.port ) );
6816 sha1.Update( ( unsigned char* ) & ( newRandomNumber ), 20 );
6817 sha1.Final();
6818
6819 //newRandNumber = false;
6820
6821 // Confirm if
6822 //syn-cookie ?= HASH(source ip address + source port + last random number)
6823 //syn-cookie ?= HASH(source ip address + source port + current random number)
6824 if ( memcmp( sha1.GetHash(), data + 1, 20 ) == 0 )
6825 {
6826 confirmedHash = true;
6827 }
6828 else
6829 {
6830 sha1.Reset();
6831 sha1.Update( ( unsigned char* ) & systemAddress.binaryAddress, sizeof( systemAddress.binaryAddress ) );
6832 sha1.Update( ( unsigned char* ) & systemAddress.port, sizeof( systemAddress.port ) );
6833 sha1.Update( ( unsigned char* ) & ( oldRandomNumber ), 20 );
6834 sha1.Final();
6835
6836 if ( memcmp( sha1.GetHash(), data + 1, 20 ) == 0 )
6837 confirmedHash = true;
6838 }
6839 if ( confirmedHash )
6840 {
6841 int i;
6842 unsigned char AESKey[ 16 ];
6843 //RSA_BIT_SIZE message, encryptedMessage;
6844 uint32_t message[RAKNET_RSA_FACTOR_LIMBS], encryptedMessage[RAKNET_RSA_FACTOR_LIMBS];
6845
6846 // On connection accept, AES key is c2s RSA_Decrypt(random number) XOR s2c syn-cookie
6847 // Get the random number first
6848
6849 memcpy( encryptedMessage, data + 1 + 20, sizeof( encryptedMessage ) );
6850
6851 // printf("enc3[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
6852
6853 if (RakNet::BitStream::DoEndianSwap())
6854 {
6855 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
6856 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &encryptedMessage[i], sizeof(encryptedMessage[i]));
6857 }
6858
6859 // printf("enc4[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
6860
6861 // rsacrypt.decrypt( encryptedMessage, message );
6862 rsacrypt.decrypt( message, encryptedMessage );
6863
6864 // printf("message[0]=%i,%i\n", message[0], message[19]);
6865
6866
6867
6868 // if (RakNet::BitStream::DoEndianSwap())
6869 // {
6870 // The entire message is endian swapped, then just the random number
6871 // unsigned char randomNumber[ 20 ];
6872 // if (RakNet::BitStream::DoEndianSwap())
6873 // {
6874 // for (int i=0; i < 20; i++)
6875 // RakNet::BitStream::ReverseBytesInPlace((unsigned char*) message[i], sizeof(message[i]));
6876 // }
6877 // }
6878
6879 /*
6880 // On connection accept, AES key is c2s RSA_Decrypt(random number) XOR s2c syn-cookie
6881 // Get the random number first
6882 #ifdef HOST_ENDIAN_IS_BIG
6883 BSWAPCPY( (unsigned char *) encryptedMessage, (unsigned char *)(data + 1 + 20), sizeof( RSA_BIT_SIZE ) );
6884 #else
6885 memcpy( encryptedMessage, data + 1 + 20, sizeof( RSA_BIT_SIZE ) );
6886 #endif
6887 rsacrypt.decrypt( encryptedMessage, message );
6888 #ifdef HOST_ENDIAN_IS_BIG
6889 BSWAPSELF( (unsigned char *) message, sizeof( RSA_BIT_SIZE ) );
6890 #endif
6891 */
6892
6893 // Save the AES key
6894 for ( i = 0; i < 16; i++ )
6895 AESKey[ i ] = data[ 1 + i ] ^ ( ( unsigned char* ) ( message ) ) [ i ];
6896
6897 RakNet::BitStream bsTimestamp(data+1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS,sizeof(RakNetTime),false);
6898 RakNetTime timeStamp;
6899 bsTimestamp.Read(timeStamp);
6900
6901 // Connect this player assuming we have open slots
6902 OnConnectionRequest( remoteSystem, AESKey, true, timeStamp );
6903 }
6904 rakFree_Ex(data, __FILE__, __LINE__ );
6905 }
6906 #endif // #if !defined(_XBOX) && !defined(_WIN32_WCE)
6907 else if ( (unsigned char)(data)[0] == ID_DETECT_LOST_CONNECTIONS && byteSize == sizeof(unsigned char) )
6908 {
6909 // Do nothing
6910 rakFree_Ex(data, __FILE__, __LINE__ );
6911 }
6912 else if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST_ACCEPTED )
6913 {
6914 if (byteSize > sizeof(MessageID)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(SystemIndex)+sizeof(RakNetTime)*2)
6915 {
6916 // Make sure this connection accept is from someone we wanted to connect to
6917 bool allowConnection, alreadyConnected;
6918
6919 if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
6920 remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
6921 allowConnectionResponseIPMigration)
6922 allowConnection=true;
6923 else
6924 allowConnection=false;
6925
6926 if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST)
6927 alreadyConnected=true;
6928 else
6929 alreadyConnected=false;
6930
6931 if ( allowConnection )
6932 {
6933 SystemAddress externalID;
6934 SystemIndex systemIndex;
6935 // SystemAddress internalID;
6936
6937 RakNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
6938 inBitStream.IgnoreBits(8); // ID_CONNECTION_REQUEST_ACCEPTED
6939 // inBitStream.Read(remotePort);
6940 inBitStream.Read(externalID);
6941 inBitStream.Read(systemIndex);
6942 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
6943 inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
6944
6945 RakNetTime sendPingTime, sendPongTime;
6946 inBitStream.Read(sendPingTime);
6947 inBitStream.Read(sendPongTime);
6948 OnConnectedPong(sendPingTime, sendPongTime, remoteSystem);
6949
6950 // Find a free remote system struct to use
6951 // RakNet::BitStream casBitS(data, byteSize, false);
6952 // ConnectionAcceptStruct cas;
6953 // cas.Deserialize(casBitS);
6954 // systemAddress.port = remotePort;
6955
6956 // The remote system told us our external IP, so save it
6957 remoteSystem->myExternalSystemAddress = externalID;
6958 remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
6959
6960 firstExternalID=externalID;
6961
6962 if (alreadyConnected==false)
6963 {
6964 // Use the stored encryption key
6965 if (remoteSystem->setAESKey)
6966 remoteSystem->reliabilityLayer.SetEncryptionKey( remoteSystem->AESKey );
6967 else
6968 remoteSystem->reliabilityLayer.SetEncryptionKey( 0 );
6969 }
6970
6971 // Send the connection request complete to the game
6972 packet=AllocPacket(byteSize, data, __FILE__, __LINE__);
6973 packet->bitSize = byteSize * 8;
6974 packet->systemAddress = systemAddress;
6975 packet->systemAddress.systemIndex = ( SystemIndex ) GetIndexFromSystemAddress( systemAddress, true );
6976 packet->guid = remoteSystem->guid;
6977 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6978 AddPacketToProducer(packet);
6979
6980
6981 // Removeme
6982 // static int count3=1;
6983 // printf("Send ID_NEW_INCOMING_CONNECTION count=%i\n", count3++);
6984
6985 RakNet::BitStream outBitStream;
6986 outBitStream.Write((MessageID)ID_NEW_INCOMING_CONNECTION);
6987 outBitStream.Write(systemAddress);
6988 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
6989 outBitStream.Write(mySystemAddress[i]);
6990 outBitStream.Write(sendPongTime);
6991 outBitStream.Write(RakNet::GetTime());
6992
6993
6994 // We turned on encryption with SetEncryptionKey. This pads packets to up to a multiple of 16 bytes.
6995 // As soon as a multiple of 16 byte packet arrives on the remote system, we will turn on AES. This works because all encrypted packets are multiples of 16 and the
6996 // packets I happen to be sending before this are not a multiple of 16 bytes. Otherwise there is no way to know if a packet that arrived is
6997 // encrypted or not so the other side won't know to turn on encryption or not.
6998 RakAssert((outBitStream.GetNumberOfBytesUsed()&15)!=0);
6999 SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0 );
7000
7001 if (alreadyConnected==false)
7002 {
7003 PingInternal( systemAddress, true, UNRELIABLE );
7004 }
7005 }
7006 else
7007 {
7008 // Ignore, already connected
7009 rakFree_Ex(data, __FILE__, __LINE__ );
7010 }
7011 }
7012 else
7013 {
7014 // Version mismatch error?
7015 RakAssert(0);
7016 rakFree_Ex(data, __FILE__, __LINE__ );
7017 }
7018 }
7019 else
7020 {
7021 // What do I do if I get a message from a system, before I am fully connected?
7022 // I can either ignore it or give it to the user
7023 // It seems like giving it to the user is a better option
7024 if (data[0]>=(MessageID)ID_RPC &&
7025 remoteSystem->isActive
7026 /*
7027 (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED ||
7028 remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP ||
7029 remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY ||
7030 remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
7031 */
7032 )
7033 {
7034 packet=AllocPacket(byteSize, data, __FILE__, __LINE__);
7035 packet->bitSize = bitSize;
7036 packet->systemAddress = systemAddress;
7037 packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
7038 packet->guid = remoteSystem->guid;
7039 packet->guid.systemIndex=packet->systemAddress.systemIndex;
7040 AddPacketToProducer(packet);
7041 }
7042 else
7043 {
7044 rakFree_Ex(data, __FILE__, __LINE__ );
7045 }
7046 }
7047 }
7048
7049 // Does the reliability layer have any more packets waiting for us?
7050 // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
7051 bitSize = remoteSystem->reliabilityLayer.Receive( &data );
7052 }
7053 }
7054 }
7055
7056 return true;
7057 }
7058 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RAK_THREAD_DECLARATION(RecvFromLoop)7059 RAK_THREAD_DECLARATION(RecvFromLoop)
7060 {
7061 RakPeerAndIndex *rpai = ( RakPeerAndIndex * ) arguments;
7062 RakPeer * rakPeer = rpai->rakPeer;
7063 SOCKET s = rpai->s;
7064 unsigned short remotePortRakNetWasStartedOn_PS3 = rpai->remotePortRakNetWasStartedOn_PS3;
7065
7066 rakPeer->isRecvFromLoopThreadActive = true;
7067
7068 RakPeer::RecvFromStruct *recvFromStruct;
7069 while ( rakPeer->endThreads == false )
7070 {
7071 recvFromStruct=rakPeer->bufferedPackets.Allocate( __FILE__, __LINE__ );
7072 recvFromStruct->s=s;
7073 recvFromStruct->remotePortRakNetWasStartedOn_PS3=remotePortRakNetWasStartedOn_PS3;
7074 SocketLayer::RecvFromBlocking(s, rakPeer, remotePortRakNetWasStartedOn_PS3, recvFromStruct->data, &recvFromStruct->bytesRead, &recvFromStruct->systemAddress, &recvFromStruct->timeRead);
7075 if (recvFromStruct->bytesRead>0)
7076 {
7077 RakAssert(recvFromStruct->systemAddress.port);
7078 rakPeer->bufferedPackets.Push(recvFromStruct);
7079
7080 rakPeer->quitAndDataEvents.SetEvent();
7081 }
7082 else
7083 {
7084 rakPeer->bufferedPackets.Deallocate(recvFromStruct, __FILE__,__LINE__);
7085 }
7086 }
7087 rakPeer->isRecvFromLoopThreadActive = false;
7088 return 0;
7089 }
7090 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RAK_THREAD_DECLARATION(UpdateNetworkLoop)7091 RAK_THREAD_DECLARATION(UpdateNetworkLoop)
7092 {
7093 RakPeer * rakPeer = ( RakPeer * ) arguments;
7094
7095 /*
7096 // 11/15/05 - this is slower than Sleep()
7097 #ifdef _WIN32
7098 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
7099 // Lets see if these timers give better performance than Sleep
7100 HANDLE timerHandle;
7101 LARGE_INTEGER dueTime;
7102
7103 if ( rakPeer->threadSleepTimer <= 0 )
7104 rakPeer->threadSleepTimer = 1;
7105
7106 // 2nd parameter of false means synchronization timer instead of manual-reset timer
7107 timerHandle = CreateWaitableTimer( NULL, FALSE, 0 );
7108
7109 RakAssert( timerHandle );
7110
7111 dueTime.QuadPart = -10000 * rakPeer->threadSleepTimer; // 10000 is 1 ms?
7112
7113 BOOL success = SetWaitableTimer( timerHandle, &dueTime, rakPeer->threadSleepTimer, NULL, NULL, FALSE );
7114 (void) success;
7115 RakAssert( success );
7116
7117 #endif
7118 #endif
7119 */
7120
7121 RakNetTimeUS timeNS;
7122 RakNetTimeMS timeMS;
7123
7124 rakPeer->isMainLoopThreadActive = true;
7125
7126 // #ifdef _DEBUG
7127 // RakNetTime lastCall=RakNet::GetTime();
7128 // #endif
7129 while ( rakPeer->endThreads == false )
7130 {
7131 // Set inside RunUpdateCycle() itself, this is here for testing
7132 timeNS=0;
7133 timeMS=0;
7134
7135 // #ifdef _DEBUG
7136 // // Sanity check, make sure RunUpdateCycle does not block or not otherwise get called for a long time
7137 // RakNetTime thisCall=RakNet::GetTime();
7138 // RakAssert(thisCall-lastCall<250);
7139 // lastCall=thisCall;
7140 // #endif
7141 if (rakPeer->userUpdateThreadPtr)
7142 rakPeer->userUpdateThreadPtr(rakPeer, rakPeer->userUpdateThreadData);
7143
7144 rakPeer->RunUpdateCycle(timeNS, timeMS);
7145
7146 // Pending sends go out this often, unless quitAndDataEvents is set
7147 rakPeer->quitAndDataEvents.WaitOnEvent(10);
7148
7149 /*
7150
7151 // #if ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) &&
7152 #if defined(USE_WAIT_FOR_MULTIPLE_EVENTS) && defined(_WIN32)
7153
7154 if (rakPeer->threadSleepTimer>0)
7155 {
7156 WSAEVENT eventArray[256];
7157 unsigned int i, eventArrayIndex;
7158 for (i=0,eventArrayIndex=0; i < rakPeer->socketList.Size(); i++)
7159 {
7160 if (rakPeer->socketList[i]->recvEvent!=INVALID_HANDLE_VALUE)
7161 {
7162 eventArray[eventArrayIndex]=rakPeer->socketList[i]->recvEvent;
7163 eventArrayIndex++;
7164 if (eventArrayIndex==256)
7165 break;
7166 }
7167 }
7168 WSAWaitForMultipleEvents(eventArrayIndex,(const HANDLE*) &eventArray,FALSE,rakPeer->threadSleepTimer,FALSE);
7169 }
7170 else
7171 {
7172 RakSleep(0);
7173 }
7174
7175 #else // ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
7176 #pragma message("-- RakNet: Using Sleep(). Uncomment USE_WAIT_FOR_MULTIPLE_EVENTS in RakNetDefines.h if you want to use WaitForSingleObject instead. --")
7177
7178 RakSleep( rakPeer->threadSleepTimer );
7179 #endif
7180 */
7181 }
7182
7183 rakPeer->isMainLoopThreadActive = false;
7184
7185 /*
7186 #ifdef _WIN32
7187 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
7188 CloseHandle(timerHandle);
7189 #endif
7190 #endif
7191 */
7192
7193 return 0;
7194 }
7195
7196 #if defined(RMO_NEW_UNDEF_ALLOCATING_QUEUE)
7197 #pragma pop_macro("new")
7198 #undef RMO_NEW_UNDEF_ALLOCATING_QUEUE
7199 #endif
7200
7201
7202 #ifdef _MSC_VER
7203 #pragma warning( pop )
7204 #endif
7205