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