1 /* -*- mode: c++; c-file-style: raknet; tab-always-indent: nil; -*- */
2 /**
3  * @file
4  * @brief RakPeer Implementation
5  *
6  * Copyright (c) 2003, Rakkarsoft LLC and Kevin Jenkins
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in the
15  *       documentation and/or other materials provided with the distribution.
16  *     * Neither the name of the <organization> nor the
17  *       names of its contributors may be used to endorse or promote products
18  *       derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include "RakPeer.h"
32 #include "NetworkTypes.h"
33 
34 #ifdef _WIN32
35 #include <process.h>
36 #else
37 #define closesocket close
38 #include <unistd.h>
39 #include <pthread.h>
40 #endif
41 #include <ctype.h> // toupper
42 
43 #include "GetTime.h"
44 #include "PacketEnumerations.h"
45 #include "PacketPool.h"
46 
47 // alloca
48 #ifdef _WIN32
49 #include <malloc.h>
50 #else
51 #include <stdlib.h>
52 #endif
53 
54 #include <cstring>
55 
56 // On a Little-endian machine the RSA key and message are mangled, but we're
57 // trying to be friendly to the little endians, so we do byte order
58 // mangling on Big-Endian machines.  Note that this mangling is independent
59 // of the byte order used on the network (which also defaults to little-end).
60 #ifdef HOST_ENDIAN_IS_BIG
BSWAPCPY(unsigned char * dest,unsigned char * source,int bytesize)61 	void __inline BSWAPCPY(unsigned char *dest, unsigned char *source, int bytesize)
62 	{
63 	#ifdef _DEBUG
64 		assert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
65 	#endif
66 		int i;
67 		for (i=0; i<bytesize; i+=4)
68 		{
69 			dest[i] = source[i+3];
70 			dest[i+1] = source[i+2];
71 			dest[i+2] = source[i+1];
72 			dest[i+3] = source[i];
73 		}
74 	}
BSWAPSELF(unsigned char * source,int bytesize)75 	void __inline BSWAPSELF(unsigned char *source, int bytesize)
76 	{
77 	#ifdef _DEBUG
78 		assert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
79 	#endif
80 		int i;
81 		unsigned char a, b;
82 		for (i=0; i<bytesize; i+=4)
83 		{
84 			a = source[i];
85 			b = source[i+1];
86 			source[i] = source[i+3];
87 			source[i+1] = source[i+2];
88 			source[i+2] = b;
89 			source[i+3] = a;
90 		}
91 	}
92 #endif
93 
94 static const unsigned int SYN_COOKIE_OLD_RANDOM_NUMBER_DURATION = 5000;
95 static const 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.
96 
97 //#define _DO_PRINTF
98 
99 // UPDATE_THREAD_POLL_TIME is how often the update thread will poll to see
100 // if receive wasn't called within UPDATE_THREAD_UPDATE_TIME.  If it wasn't called within that time,
101 // the updating thread will activate and take over network communication until Receive is called again.
102 //static const unsigned int UPDATE_THREAD_UPDATE_TIME=30;
103 //static const unsigned int UPDATE_THREAD_POLL_TIME=30;
104 
105 
106 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
107 // Constructor
108 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RakPeer()109 RakPeer::RakPeer()
110 {
111 	connectionSocket = INVALID_SOCKET;
112 	MTUSize = DEFAULT_MTU_SIZE;
113 	maximumIncomingConnections = 0;
114 	maximumNumberOfPeers = 0;
115 	remoteSystemListSize=0;
116 	remoteSystemList = 0;
117 	bytesSentPerSecond = bytesReceivedPerSecond = 0;
118 	endThreads = true;
119 	isMainLoopThreadActive = false;
120 	connectionSocket = INVALID_SOCKET;
121 	myPlayerId = UNASSIGNED_PLAYER_ID;
122 	allowConnectionResponseIPMigration = false;
123 	incomingPacketQueue.clearAndForceAllocation(128);
124 }
125 
126 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
127 // Destructor
128 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
~RakPeer()129 RakPeer::~RakPeer()
130 {
131 	Disconnect( 0 );
132 }
133 
134 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
135 // Description:
136 // Starts the network threads, opens the listen port
137 // You must call this before calling SetMaximumIncomingConnections or Connect
138 // Multiple calls while already active are ignored.  To call this function again with different settings, you must first call Disconnect()
139 //
140 // Parameters:
141 // MaximumNumberOfPeers:  Required so the network can preallocate and for thread safety.
142 // - A pure client would set this to 1.  A pure server would set it to the number of allowed clients.
143 // - A hybrid would set it to the sum of both types of connections
144 // localPort: The port to listen for connections on.
145 // _threadSleepTimer: >=0 for how many ms to Sleep each internal update cycle (recommended 30 for low performance, 0 for regular)
146  // forceHostAddress Can force RakNet to use a particular IP to host on.  Pass 0 to automatically pick an IP
147 // Returns:
148 // False on failure (can't create socket or thread), true on success.
149 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Initialize(unsigned short MaximumNumberOfPeers,unsigned short localPort,int _threadSleepTimer,const char * forceHostAddress)150 bool RakPeer::Initialize( unsigned short MaximumNumberOfPeers, unsigned short localPort, int _threadSleepTimer, const char *forceHostAddress )
151 {
152 	// Maximum number of peers must be > 0
153 	assert(MaximumNumberOfPeers > 0);
154 
155 	if (MaximumNumberOfPeers <= 0)
156 	{
157 		return false;
158 	}
159 
160 	if ( connectionSocket == INVALID_SOCKET )
161 	{
162 		connectionSocket = SocketLayer::Instance()->CreateBoundSocket( localPort, true, forceHostAddress );
163 
164 		if ( connectionSocket == INVALID_SOCKET )
165 			return false;
166 	}
167 
168 	if ( _threadSleepTimer < 0 )
169 		return false;
170 
171 	if ( maximumNumberOfPeers == 0 )
172 	{
173 		// Don't allow more incoming connections than we have peers.
174 		if ( maximumIncomingConnections > MaximumNumberOfPeers )
175 			maximumIncomingConnections = MaximumNumberOfPeers;
176 
177 		maximumNumberOfPeers = MaximumNumberOfPeers;
178 		// Allocate a few extra remote systems to handle new connections from players trying to connect when the server is full
179 		remoteSystemListSize = MaximumNumberOfPeers + 1 + MaximumNumberOfPeers/8;
180 
181 	//	rakPeerMutexes[ RakPeer::remoteSystemList_Mutex ].Lock();
182 		remoteSystemList = new RemoteSystemStruct[ remoteSystemListSize ];
183 	//	rakPeerMutexes[ RakPeer::remoteSystemList_Mutex ].Unlock();
184 		for ( unsigned i = 0; i < remoteSystemListSize; i++ )
185 		{
186 			remoteSystemList[ i ].playerId = UNASSIGNED_PLAYER_ID;
187 	//		remoteSystemList[ i ].allowPlayerIdAssigment=true;
188 		}
189 	}
190 
191 	// For histogram statistics
192 	// nextReadBytesTime=0;
193 	// lastSentBytes=lastReceivedBytes=0;
194 
195 	if ( endThreads )
196 	{
197 		lastUserUpdateCycle = 0;
198 
199 		updateCycleIsRunning = false;
200 		endThreads = false;
201 		// Create the threads
202 		threadSleepTimer = _threadSleepTimer;
203 
204 		ClearBufferedCommands();
205 
206 		char ipList[ 10 ][ 16 ];
207 		SocketLayer::Instance()->GetMyIP( ipList );
208 		myPlayerId.port = localPort;
209 		myPlayerId.binaryAddress = inet_addr( ipList[ 0 ] );
210 		{
211 #ifdef _WIN32
212 
213 			if ( isMainLoopThreadActive == false )
214 			{
215 				unsigned ProcessPacketsThreadID = 0;
216 				processPacketsThreadHandle = ( HANDLE ) _beginthreadex( NULL, 0, UpdateNetworkLoop, this, 0, &ProcessPacketsThreadID );
217 
218 				if ( processPacketsThreadHandle == 0 )
219 				{
220 					Disconnect( 0 );
221 					return false;
222 				}
223 
224 				// SetThreadPriority(processPacketsThreadHandle, THREAD_PRIORITY_HIGHEST);
225 
226 				CloseHandle( processPacketsThreadHandle );
227 
228 				processPacketsThreadHandle = 0;
229 
230 			}
231 
232 #else
233 			pthread_attr_t attr;
234 			pthread_attr_init( &attr );
235 			pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
236 
237 			//  sched_param sp;
238 			//  sp.sched_priority = sched_get_priority_max(SCHED_OTHER);
239 			//  pthread_attr_setschedparam(&attr, &sp);
240 
241 			if ( isMainLoopThreadActive == false )
242 			{
243 				int error = pthread_create( &processPacketsThreadHandle, &attr, &UpdateNetworkLoop, this );
244 
245 				if ( error )
246 				{
247 					Disconnect( 0 );
248 					return false;
249 				}
250 			}
251 
252 			processPacketsThreadHandle = 0;
253 #endif
254 
255 
256 			// Wait for the threads to activate.  When they are active they will set these variables to true
257 
258 			while (  /*isRecvfromThreadActive==false || */isMainLoopThreadActive == false )
259 #ifdef _WIN32
260 				Sleep( 10 );
261 #else
262 				usleep( 10 * 1000 );
263 #endif
264 
265 		}
266 
267 	}
268 
269 	return true;
270 }
271 
272 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
273 // Description:
274 // Sets how many incoming connections are allowed.  If this is less than the number of players currently connected, no
275 // more players will be allowed to connect.  If this is greater than the maximum number of peers allowed, it will be reduced
276 // to the maximum number of peers allowed.  Defaults to 0.
277 //
278 // Parameters:
279 // numberAllowed - Maximum number of incoming connections allowed.
280 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetMaximumIncomingConnections(unsigned short numberAllowed)281 void RakPeer::SetMaximumIncomingConnections( unsigned short numberAllowed )
282 {
283 	maximumIncomingConnections = numberAllowed;
284 }
285 
286 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
287 // Description:
288 // Returns the maximum number of incoming connections, which is always <= MaximumNumberOfPeers
289 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetMaximumIncomingConnections(void) const290 unsigned short RakPeer::GetMaximumIncomingConnections( void ) const
291 {
292 	return maximumIncomingConnections;
293 }
294 
295 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
296 // Description:
297 // Call this to connect to the specified host (ip or domain name) and server port.
298 // Calling Connect and not calling SetMaximumIncomingConnections acts as a dedicated client.  Calling both acts as a true peer.
299 // This is a non-blocking connection.  You know the connection is successful when IsConnected() returns true
300 // or receive gets a packet with the type identifier ID_CONNECTION_ACCEPTED.  If the connection is not
301 // successful, such as rejected connection or no response then neither of these things will happen.
302 // Requires that you first call Initialize
303 //
304 // Parameters:
305 // host: Either a dotted IP address or a domain name
306 // remotePort: Which port to connect to on the remote machine.
307 // 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
308 // passwordDataLength: The length in bytes of passwordData
309 //
310 // Returns:
311 // True on successful initiation. False on incorrect parameters, internal error, or too many existing peers
312 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Connect(const char * host,unsigned short remotePort)313 bool RakPeer::Connect( const char* host, unsigned short remotePort )
314 {
315 	// If endThreads is true here you didn't call Initialize() first.
316 	if ( host == 0 || endThreads || connectionSocket == INVALID_SOCKET )
317 		return false;
318 
319 	// If the host starts with something other than 0, 1, or 2 it's (probably) a domain name.
320 	if ( host[ 0 ] < '0' || host[ 0 ] > '2' )
321 	{
322 		host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host );
323 
324 		if (host==0)
325 			return false;
326 	}
327 
328 	// Connecting to ourselves in the same instance of the program?
329 	if ( ( strcmp( host, "127.0.0.1" ) == 0 || strcmp( host, "0.0.0.0" ) == 0 ) && remotePort == myPlayerId.port )
330 	{
331 		// Feedback loop.
332 		if ( !AllowIncomingConnections() )
333 		{
334 			// Tell the game that this person has connected
335 			Packet * p;
336 			p = packetPool.GetPointer();
337 
338 			p->data = new unsigned char [ 1 ];
339 			p->data[ 0 ] = (unsigned char) ID_NO_FREE_INCOMING_CONNECTIONS;
340 			p->playerId = myPlayerId;
341 			p->playerIndex = ( PlayerIndex ) GetIndexFromPlayerID( myPlayerId );
342 			p->length = 1;
343 			p->bitSize = 8;
344 
345 #ifdef _DEBUG
346 
347 			assert( p->data );
348 #endif
349 
350 			incomingQueueMutex.Lock();
351 			incomingPacketQueue.push( p );
352 			incomingQueueMutex.Unlock();
353 		}
354 		else
355 		{
356 			// Just assume we are connected.  This is really just for testing.
357 		//	RemoteSystemStruct* remoteSystem = AssignPlayerIDToRemoteSystemList( myPlayerId, RemoteSystemStruct::CONNECTED );
358 
359 		//	if ( remoteSystem != 0 )
360 		//	{
361 				RakNet::BitStream bitStream(sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short));
362 				bitStream.Write((unsigned char)ID_NEW_INCOMING_CONNECTION);
363 				bitStream.Write(myPlayerId.binaryAddress);
364 				bitStream.Write(myPlayerId.port);
365 		//		Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, myPlayerId, false );
366 				SendBuffered(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, myPlayerId, false, RemoteSystemStruct::CONNECTED);
367 				return true;
368 		//	}
369 		//	else
370 		//		return false;
371 		}
372 	}
373 
374 	return SendConnectionRequest( host, remotePort );
375 }
376 
377 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
378 // Description:
379 // Stops the network threads and close all connections.  Multiple calls are ok.
380 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Disconnect(unsigned int blockDuration)381 void RakPeer::Disconnect( unsigned int blockDuration )
382 {
383 	unsigned i;
384 	unsigned short systemListSize = remoteSystemListSize; // This is done for threading reasons
385 
386 	if ( blockDuration > 0 )
387 	{
388 		for ( i = 0; i < systemListSize; i++ )
389 		{
390 			NotifyAndFlagForDisconnect(remoteSystemList[i].playerId, false);
391 		}
392 
393 		unsigned time = RakNet::GetTime();
394 		unsigned stopWaitingTime = time + blockDuration;
395 		while ( time < stopWaitingTime )
396 		{
397 			bool anyActive = false;
398 			for (unsigned j = 0; j < systemListSize; j++)
399 			{
400 				if (remoteSystemList[j].playerId!=UNASSIGNED_PLAYER_ID)
401 				{
402 					anyActive=true;
403 					break;
404 				}
405 			}
406 
407 			// If this system is out of packets to send, then stop waiting
408 			if ( anyActive==false )
409 				break;
410 
411 			// This will probably cause the update thread to run which will probably
412 			// send the disconnection notification
413 #ifdef _WIN32
414 			Sleep( 15 );
415 #else
416 			usleep( 15 * 1000 );
417 #endif
418 			time = RakNet::GetTime();
419 		}
420 	}
421 
422 	if ( endThreads == false )
423 	{
424 		// Stop the threads
425 		endThreads = true;
426 
427 		// Normally the thread will call DecreaseUserCount on termination but if we aren't using threads just do it
428 		// manually
429 	}
430 
431 	while ( isMainLoopThreadActive )
432 #ifdef _WIN32
433 		Sleep( 15 );
434 #else
435 		usleep( 15 * 1000 );
436 #endif
437 
438 	// Reset the remote system list after the threads are known to have stopped so threads do not add or update data to them after they are reset
439 	//rakPeerMutexes[ RakPeer::remoteSystemList_Mutex ].Lock();
440 	for ( i = 0; i < systemListSize; i++ )
441 	{
442 		// Reserve this reliability layer for ourselves
443 		remoteSystemList[ i ].playerId = UNASSIGNED_PLAYER_ID;
444 
445 		// Remove any remaining packets
446 		remoteSystemList[ i ].reliabilityLayer.Reset();
447 	}
448 	//rakPeerMutexes[ remoteSystemList_Mutex ].Unlock();
449 
450 	// Setting maximumNumberOfPeers to 0 allows remoteSystemList to be reallocated in Initialize.
451 	// Setting remoteSystemListSize prevents threads from accessing the reliability layer
452 	maximumNumberOfPeers = 0;
453 	remoteSystemListSize = 0;
454 
455 	if ( connectionSocket != INVALID_SOCKET )
456 	{
457 		closesocket( connectionSocket );
458 		connectionSocket = INVALID_SOCKET;
459 	}
460 
461 	// Clear out the queues
462 	while ( incomingPacketQueue.size() )
463 		packetPool.ReleasePointer( incomingPacketQueue.pop() );
464 
465 	ClearBufferedCommands();
466 	bytesSentPerSecond = bytesReceivedPerSecond = 0;
467 
468 	ClearRequestedConnectionList();
469 
470 
471 	// Clear out the reliabilty layer list in case we want to reallocate it in a successive call to Init.
472 	RemoteSystemStruct * temp = remoteSystemList;
473 	remoteSystemList = 0;
474 	delete [] temp;
475 
476 	packetPool.ClearPool();
477 }
478 
479 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
480 // Description:
481 // Returns true if the network threads are running
482 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IsActive(void) const483 bool RakPeer::IsActive( void ) const
484 {
485 	return endThreads == false;
486 }
487 
488 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
489 // Description:
490 // Fills the array remoteSystems with the playerID of all the systems we are connected to
491 //
492 // Parameters:
493 // remoteSystems (out): An array of PlayerID structures to be filled with the PlayerIDs of the systems we are connected to
494 // - pass 0 to remoteSystems to only get the number of systems we are connected to
495 // numberOfSystems (int, out): As input, the size of remoteSystems array.  As output, the number of elements put into the array
496 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetConnectionList(PlayerID * remoteSystems,unsigned short * numberOfSystems) const497 bool RakPeer::GetConnectionList( PlayerID *remoteSystems, unsigned short *numberOfSystems ) const
498 {
499 	int count, index;
500 	count=0;
501 
502 	if ( remoteSystemList == 0 || endThreads == true )
503 	{
504 		*numberOfSystems = 0;
505 		return false;
506 	}
507 
508 	// This is called a lot so I unrolled the loop
509 	if ( remoteSystems )
510 	{
511 		for ( count = 0, index = 0; index < remoteSystemListSize; ++index )
512 			if ( remoteSystemList[ index ].playerId != UNASSIGNED_PLAYER_ID && remoteSystemList[ index ].connectMode==RemoteSystemStruct::CONNECTED)
513 			{
514 				if ( count < *numberOfSystems )
515 					remoteSystems[ count ] = remoteSystemList[ index ].playerId;
516 
517 				++count;
518 			}
519 	}
520 	else
521 	{
522 		for ( count = 0, index = 0; index < remoteSystemListSize; ++index )
523 			if ( remoteSystemList[ index ].playerId != UNASSIGNED_PLAYER_ID && remoteSystemList[ index ].connectMode==RemoteSystemStruct::CONNECTED)
524 				++count;
525 	}
526 
527 	*numberOfSystems = ( unsigned short ) count;
528 
529 	return 0;
530 }
531 
532 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
533 // Description:
534 // Sends a block of data to the specified system that you are connected to.
535 // This function only works while the client is connected (Use the Connect function).
536 //
537 // Parameters:
538 // data: The block of data to send
539 // length: The size in bytes of the data to send
540 // bitStream: The bitstream to send
541 // priority: What priority level to send on.
542 // reliability: How reliability to send this data
543 // orderingChannel: When using ordered or sequenced packets, what channel to order these on.
544 // - Packets are only ordered relative to other packets on the same stream
545 // playerId: Who to send this packet to, or in the case of broadcasting who not to send it to. Use UNASSIGNED_PLAYER_ID to specify none
546 // broadcast: True to send this packet to all connected systems.  If true, then playerId specifies who not to send the packet to.
547 // Returns:
548 // False if we are not connected to the specified recipient.  True otherwise
549 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Send(const char * data,const long length,PacketPriority priority,PacketReliability reliability,char orderingChannel,PlayerID playerId,bool broadcast)550 bool RakPeer::Send( const char *data, const long length, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast )
551 {
552 #ifdef _DEBUG
553 	assert( data && length > 0 );
554 #endif
555 
556 	if ( data == 0 || length < 0 )
557 		return false;
558 
559 	RakNet::BitStream temp( (char*)data, length, false );
560 	return Send( &temp, priority, reliability, orderingChannel, playerId, broadcast );
561 
562 }
563 
Send(const RakNet::BitStream * bitStream,PacketPriority priority,PacketReliability reliability,char orderingChannel,PlayerID playerId,bool broadcast)564 bool RakPeer::Send( const RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast )
565 {
566 #ifdef _DEBUG
567 	assert( bitStream->GetNumberOfBytesUsed() > 0 );
568 #endif
569 
570 	if ( bitStream->GetNumberOfBytesUsed() == 0 )
571 		return false;
572 
573 	if ( remoteSystemList == 0 || endThreads == true )
574 		return false;
575 
576 	if ( broadcast == false && playerId == UNASSIGNED_PLAYER_ID )
577 		return false;
578 
579 	if (ValidSendTarget(playerId, broadcast))
580 	{
581 		// Sends need to be buffered and processed in the update thread because the playerID associated with the reliability layer can change,
582 		// from that thread, resulting in a send to the wrong player!  While I could mutex the playerID, that is much slower than doing this
583 		SendBuffered(bitStream, priority, reliability, orderingChannel, playerId, broadcast, RemoteSystemStruct::NO_ACTION);
584 		return true;
585 	}
586 
587 	return false;
588 }
589 
590 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
591 // Description:
592 // Gets a packet from the incoming packet queue. Use DeallocatePacket to deallocate the packet after you are done with it.
593 // Check the Packet struct at the top of CoreNetworkStructures.h for the format of the struct
594 //
595 // Returns:
596 // 0 if no packets are waiting to be handled, otherwise an allocated packet
597 // If the client is not active this will also return 0, as all waiting packets are flushed when the client is Disconnected
598 // This also updates all memory blocks associated with synchronized memory and distributed objects
599 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Receive(void)600 packet_ptr RakPeer::Receive( void )
601 {
602 	if ( !( IsActive() ) )
603 		return packet_ptr();
604 
605 	Packet *val;
606 
607 	#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
608 	while ( true )
609 	{
610 		if (incomingPacketQueue.size() > 0) // First fast unlocked check
611 		{
612 			incomingQueueMutex.Lock();
613 			if ( incomingPacketQueue.size() > 0 ) // Second safe locked check
614 			{
615 				val = incomingPacketQueue.pop();
616 			}
617 
618 			else
619 			{
620 				incomingQueueMutex.Unlock();
621 				return packet_ptr();
622 			}
623 			incomingQueueMutex.Unlock();
624 		}
625 		else
626 			return packet_ptr();
627 
628 		break;
629 	}
630 
631 
632 #ifdef _DEBUG
633 	assert( val->data );
634 #endif
635 
636 	struct deleter
637 	{
638 		RakPeer* peer;
639 		void operator()(Packet* p)
640 		{
641 			if ( p == 0 )
642 				return ;
643 
644 			peer->packetPool.ReleasePointer( p );
645 		}
646 	};
647 
648 	deleter del;
649 	del.peer = this;
650 	return packet_ptr(val, del);
651 }
652 
653 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
654 // Description:
655 // Return the total number of connections we are allowed
656 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetMaximumNumberOfPeers(void) const657 unsigned short RakPeer::GetMaximumNumberOfPeers( void ) const
658 {
659 	return maximumNumberOfPeers;
660 }
661 
662 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
663 // Description:
664 // Close the connection to another host (if we initiated the connection it will disconnect, if they did it will kick them out).
665 //
666 // Parameters:
667 // target: Which connection to close
668 // sendDisconnectionNotification: True to send ID_DISCONNECTION_NOTIFICATION to the recipient. False to close it silently.
669 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloseConnection(PlayerID target,bool sendDisconnectionNotification)670 void RakPeer::CloseConnection( PlayerID target, bool sendDisconnectionNotification )
671 {
672 	CloseConnectionInternalBuffered(target, sendDisconnectionNotification);
673 }
674 
675 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
676 // Description:
677 // Given a playerID, returns an index from 0 to the maximum number of players allowed - 1.
678 //
679 // Parameters
680 // playerId - The playerID to search for
681 //
682 // Returns
683 // An integer from 0 to the maximum number of peers -1, or -1 if that player is not found
684 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetIndexFromPlayerID(PlayerID playerId)685 int RakPeer::GetIndexFromPlayerID( PlayerID playerId )
686 {
687 	unsigned i;
688 
689 	if ( playerId == UNASSIGNED_PLAYER_ID )
690 		return -1;
691 
692 	for ( i = 0; i < maximumNumberOfPeers; i++ )
693 		if ( remoteSystemList[ i ].playerId == playerId )
694 			return i;
695 
696 	return -1;
697 }
698 
699 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
700 // Description:
701 // This function is only useful for looping through all players.
702 //
703 // Parameters
704 // index - an integer between 0 and the maximum number of players allowed - 1.
705 //
706 // Returns
707 // A valid playerID or UNASSIGNED_PLAYER_ID if no such player at that index
708 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetPlayerIDFromIndex(int index)709 PlayerID RakPeer::GetPlayerIDFromIndex( int index )
710 {
711 	if ( index >= 0 && index < remoteSystemListSize )
712 		if (remoteSystemList[ index ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED) // Don't give the user players that aren't fully connected, since sends will fail
713 			return remoteSystemList[ index ].playerId;
714 
715 	return UNASSIGNED_PLAYER_ID;
716 }
717 
718 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
719 // Description:
720 // Send a ping to the specified connected system.
721 //
722 // Parameters:
723 // target - who to ping
724 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ping(PlayerID target)725 void RakPeer::Ping( PlayerID target )
726 {
727 	PingInternal(target, false);
728 }
729 
730 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
731 // Description:
732 // Send a ping to the specified unconnected system.
733 // The remote system, if it is Initialized, will respond with ID_PONG.
734 // The final ping time will be encoded in the following 4 bytes (2-5) as an unsigned int
735 //
736 // Requires:
737 // The sender and recipient must already be started via a successful call to Initialize
738 //
739 // Parameters:
740 // host: Either a dotted IP address or a domain name.  Can be 255.255.255.255 for LAN broadcast.
741 // remotePort: Which port to connect to on the remote machine.
742 // onlyReplyOnAcceptingConnections: Only request a reply if the remote system has open connections
743 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ping(const char * host,unsigned short remotePort,bool onlyReplyOnAcceptingConnections)744 void RakPeer::Ping( const char* host, unsigned short remotePort, bool onlyReplyOnAcceptingConnections )
745 {
746 	if ( host == 0 )
747 		return;
748 
749 	if ( IsActive() == false )
750 		return;
751 
752 	// If the host starts with something other than 0, 1, or 2 it's (probably) a domain name.
753 	if ( host[ 0 ] < '0' || host[ 0 ] > '2' )
754 	{
755 		host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host );
756 	}
757 
758 	if ( host == NULL )
759 		return;
760 
761 	PlayerID playerId;
762 	IPToPlayerID( host, remotePort, &playerId );
763 
764 	// disabled so can send while shutting down
765 //	if (GetRemoteSystemFromPlayerID(playerId))
766 //		return;
767 
768 	if (strcmp(host, "255.255.255.255")==0)
769 	{
770 		RakNet::BitStream bitStream( sizeof(unsigned char) + sizeof(unsigned int) );
771 		if ( onlyReplyOnAcceptingConnections )
772 			bitStream.Write((unsigned char)ID_UNCONNECTED_PING_OPEN_CONNECTIONS);
773 		else
774 			bitStream.Write((unsigned char)ID_UNCONNECTED_PING);
775 		// No timestamp for 255.255.255.255
776 		SocketLayer::Instance()->SendTo( connectionSocket, (const char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), ( char* ) host, remotePort );
777 	}
778 	else
779 	{
780 		RequestedConnectionStruct *rcs = requestedConnectionList.WriteLock();
781 		rcs->playerId=playerId;
782 		rcs->nextRequestTime=RakNet::GetTime();
783 		rcs->requestsMade=0;
784 		rcs->data=0;
785 		if (onlyReplyOnAcceptingConnections)
786 			rcs->actionToTake=RequestedConnectionStruct::PING_OPEN_CONNECTIONS;
787 		else
788 			rcs->actionToTake=RequestedConnectionStruct::PING;
789 		requestedConnectionList.WriteUnlock();
790 	}
791 }
792 
793 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
794 // Description:
795 // Returns the last ping time read for the specific player or -1 if none read yet
796 //
797 // Parameters:
798 // target - whose time to read
799 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetLastPing(PlayerID playerId) const800 int RakPeer::GetLastPing( PlayerID playerId ) const
801 {
802 	RemoteSystemStruct * remoteSystem = GetRemoteSystemFromPlayerID( playerId );
803 
804 	if ( remoteSystem == 0 )
805 		return -1;
806 
807 	return remoteSystem->pingTime;
808 }
809 
810 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
811 // Description:
812 // Returns the lowest ping time read or -1 if none read yet
813 //
814 // Parameters:
815 // target - whose time to read
816 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetLowestPing(PlayerID playerId) const817 int RakPeer::GetLowestPing( PlayerID playerId ) const
818 {
819 	RemoteSystemStruct * remoteSystem = GetRemoteSystemFromPlayerID( playerId );
820 
821 	if ( remoteSystem == 0 )
822 		return -1;
823 
824 	return remoteSystem->lowestPing;
825 }
826 
827 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
828 // Description:
829 // Return the unique PlayerID that represents you on the the network
830 // Note that unlike in previous versions, this is a struct and is not sequential
831 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetInternalID(void) const832 PlayerID RakPeer::GetInternalID( void ) const
833 {
834 	return myPlayerId;
835 }
836 
837 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
838 // Description:
839 // Return the unique address identifier that represents you on the the network and is based on your external
840 // IP / port (the IP / port the specified player uses to communicate with you)
841 // Note that unlike in previous versions, this is a struct and is not sequential
842 //
843 // Parameters:
844 // target: Which remote system you are referring to for your external ID
845 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetExternalID(PlayerID target) const846 PlayerID RakPeer::GetExternalID( PlayerID target ) const
847 {
848 	RemoteSystemStruct * remoteSystem = GetRemoteSystemFromPlayerID( target );
849 
850 	if ( remoteSystem == 0 )
851 		return UNASSIGNED_PLAYER_ID;
852 	else
853 		return remoteSystem->myExternalPlayerId;
854 }
855 
856 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
857 // Description:
858 // Change the MTU size in order to improve performance when sending large packets
859 // This can only be called when not connected.
860 // A too high of value will cause packets not to arrive at worst and be fragmented at best.
861 // A too low of value will split packets unnecessarily.
862 //
863 // Parameters:
864 // size: Set according to the following table:
865 // 1500. The largest Ethernet packet size
866 // This is the typical setting for non-PPPoE, non-VPN connections. The default value for NETGEAR routers, adapters and switches.
867 // 1492. The size PPPoE prefers.
868 // 1472. Maximum size to use for pinging. (Bigger packets are fragmented.)
869 // 1468. The size DHCP prefers.
870 // 1460. Usable by AOL if you don't have large email attachments, etc.
871 // 1430. The size VPN and PPTP prefer.
872 // 1400. Maximum size for AOL DSL.
873 // 576. Typical value to connect to dial-up ISPs. (Default)
874 //
875 // Returns:
876 // False on failure (we are connected).  True on success.  Maximum allowed size is MAXIMUM_MTU_SIZE
877 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SetMTUSize(int size)878 bool RakPeer::SetMTUSize( int size )
879 {
880 	if ( IsActive() )
881 		return false;
882 
883 	if ( size < 512 )
884 		size = 512;
885 	else if ( size > MAXIMUM_MTU_SIZE )
886 		size = MAXIMUM_MTU_SIZE;
887 
888 	MTUSize = size;
889 
890 	return true;
891 }
892 
893 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
894 // Description:
895 // Returns the current MTU size
896 //
897 // Returns:
898 // The MTU sized specified in SetMTUSize
899 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetMTUSize(void) const900 int RakPeer::GetMTUSize( void ) const
901 {
902 	return MTUSize;
903 }
904 
905 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
906 // Description:
907 // Returns the number of IP addresses we have
908 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetNumberOfAddresses(void)909 unsigned int RakPeer::GetNumberOfAddresses( void )
910 {
911 	char ipList[ 10 ][ 16 ];
912 	memset( ipList, 0, sizeof( char ) * 16 * 10 );
913 	SocketLayer::Instance()->GetMyIP( ipList );
914 
915 	int i = 0;
916 
917 	while ( ipList[ i ][ 0 ] )
918 		i++;
919 
920 	return i;
921 }
922 
923 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
924 // Description:
925 // Given a PlayerID struct, returns the dotted IP address string this binaryAddress field represents
926 //
927 // Returns:
928 // Null terminated dotted IP address string.
929 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PlayerIDToDottedIP(PlayerID playerId) const930 const char* RakPeer::PlayerIDToDottedIP( PlayerID playerId ) const
931 {
932 	in_addr in;
933 	in.s_addr = playerId.binaryAddress;
934 	return inet_ntoa( in );
935 }
936 
937 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
938 // Description:
939 // Returns an IP address at index 0 to GetNumberOfAddresses-1
940 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetLocalIP(unsigned int index)941 const char* RakPeer::GetLocalIP( unsigned int index )
942 {
943 	static char ipList[ 10 ][ 16 ];
944 
945 	if ( index >= 10 )
946 		index = 9;
947 
948 	memset( ipList, 0, sizeof( char ) * 16 * 10 );
949 
950 	SocketLayer::Instance()->GetMyIP( ipList );
951 
952 	return ipList[ index ];
953 }
954 
955 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
956 // Description:
957 // Allow or disallow connection responses from any IP. Normally this should be false, but may be necessary
958 // when connection to servers with multiple IP addresses
959 //
960 // Parameters:
961 // allow - True to allow this behavior, false to not allow.  Defaults to false.  Value persists between connections
962 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AllowConnectionResponseIPMigration(bool allow)963 void RakPeer::AllowConnectionResponseIPMigration( bool allow )
964 {
965 	allowConnectionResponseIPMigration = allow;
966 }
967 
968 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
969 // Description:
970 // Sends a one byte message ID_ADVERTISE_SYSTEM to the remote unconnected system.
971 // This will tell the remote system our external IP outside the LAN, and can be used for NAT punch through
972 //
973 // Requires:
974 // The sender and recipient must already be started via a successful call to Initialize
975 //
976 // host: Either a dotted IP address or a domain name
977 // remotePort: Which port to connect to on the remote machine.
978 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AdvertiseSystem(char * host,unsigned short remotePort,const char * data,int dataLength)979 void RakPeer::AdvertiseSystem( char *host, unsigned short remotePort, const char *data, int dataLength )
980 {
981 	if ( IsActive() == false )
982 		return ;
983 
984 	// This is a security measure.  Don't send data longer than this value
985 	assert(dataLength <= MAX_OFFLINE_DATA_LENGTH);
986 	assert(dataLength>=0);
987 
988 	// If the host starts with something other than 0, 1, or 2 it's (probably) a domain name.
989 	if ( host[ 0 ] < '0' || host[ 0 ] > '2' )
990 	{
991 		host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host );
992 	}
993 
994 	PlayerID playerId;
995 	IPToPlayerID( host, remotePort, &playerId );
996 
997 	// disabled so can send while shutting down
998 	//if (GetRemoteSystemFromPlayerID(playerId))
999 	//	return;
1000 
1001 	RequestedConnectionStruct *rcs = requestedConnectionList.WriteLock();
1002 	rcs->playerId=playerId;
1003 	rcs->nextRequestTime=RakNet::GetTime();
1004 	rcs->requestsMade=0;
1005 	if (data && dataLength>0)
1006 	{
1007 		rcs->data=new char [dataLength];
1008 		rcs->dataLength=dataLength;
1009 		memcpy(rcs->data, data, dataLength);
1010 	}
1011 	else
1012 	{
1013 		rcs->data=0;
1014 		rcs->dataLength=0;
1015 	}
1016 	rcs->actionToTake=RequestedConnectionStruct::ADVERTISE_SYSTEM;
1017 	requestedConnectionList.WriteUnlock();
1018 
1019 //	unsigned char c = ID_ADVERTISE_SYSTEM;
1020 //	RakNet::BitStream temp(sizeof(c));
1021 //	temp.Write((unsigned char)c);
1022 //	if (data && dataLength>0)
1023 //		temp.Write(data, dataLength);
1024 //	Send(&temp, SYSTEM_PRIORITY, UNRELIABLE, 0, playerId, false);
1025 	//SendBuffered(&temp, SYSTEM_PRIORITY, UNRELIABLE, 0, playerId, false, RemoteSystemStruct::DISCONNECT_ASAP);
1026 //	SocketLayer::Instance()->SendTo( connectionSocket, (const char*)temp.GetData(), temp.GetNumberOfBytesUsed(), ( char* ) host, remotePort );
1027 }
1028 
1029 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1030 // Description:
1031 // Put a packet back at the end of the receive queue in case you don't want to deal with it immediately
1032 //
1033 // Parameters
1034 // packet: The packet you want to push back.
1035 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PushBackPacket(Packet * packet)1036 void RakPeer::PushBackPacket( Packet *packet )
1037 {
1038 	if ( packet )
1039 	{
1040 #ifdef _DEBUG
1041 		assert( packet->data );
1042 #endif
1043 
1044 		incomingPacketQueue.pushAtHead( packet );
1045 	}
1046 }
1047 
1048 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetStatistics(PlayerID playerId)1049 RakNetStatisticsStruct * const RakPeer::GetStatistics( PlayerID playerId )
1050 {
1051 	RemoteSystemStruct * rss;
1052 	rss = GetRemoteSystemFromPlayerID( playerId );
1053 
1054 	if ( rss && endThreads==false )
1055 		return rss->reliabilityLayer.GetStatistics();
1056 
1057 	return 0;
1058 }
1059 
1060 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendConnectionRequest(const char * host,unsigned short remotePort)1061 bool RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort )
1062 {
1063 	PlayerID playerId;
1064 //	RemoteSystemStruct *rss;
1065 //	bool success;
1066 	IPToPlayerID( host, remotePort, &playerId );
1067 //	rss=AssignPlayerIDToRemoteSystemList(playerId, RemoteSystemStruct::REQUESTED_CONNECTION);
1068 //	if (rss==0)
1069 //		return false; // full or already connected
1070 
1071 	// Already connected?
1072 	if (GetRemoteSystemFromPlayerID(playerId))
1073 		return false;
1074 
1075 	RequestedConnectionStruct *rcs = requestedConnectionList.WriteLock();
1076 	rcs->playerId=playerId;
1077 	rcs->nextRequestTime=RakNet::GetTime();
1078 	rcs->requestsMade=0;
1079 	rcs->data=0;
1080 	rcs->actionToTake=RequestedConnectionStruct::CONNECT;
1081 	requestedConnectionList.WriteUnlock();
1082 
1083 	// Request will be sent in the other thread
1084 
1085 	//char c = ID_OPEN_CONNECTION_REQUEST;
1086 	//SocketLayer::Instance()->SendTo( connectionSocket, (char*)&c, 1, ( char* ) host, remotePort );
1087 
1088 
1089 	/*
1090 	RakNet::BitStream temp( sizeof(unsigned char) + outgoingPasswordBitStream.GetNumberOfBytesUsed() );
1091 	temp.Write( (unsigned char) ID_CONNECTION_REQUEST );
1092 	if ( outgoingPasswordBitStream.GetNumberOfBytesUsed() > 0 )
1093 		temp.Write( ( char* ) outgoingPasswordBitStream.GetData(), outgoingPasswordBitStream.GetNumberOfBytesUsed() );
1094 //	success=Send(&temp, SYSTEM_PRIORITY, RELIABLE, 0, playerId, false);
1095 	SendBuffered(&temp, SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, RemoteSystemStruct::REQUESTED_CONNECTION);
1096 //#ifdef _DEBUG
1097 //	assert(success);
1098 //#endif
1099 */
1100 
1101 	return true;
1102 }
1103 
1104 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IPToPlayerID(const char * host,unsigned short remotePort,PlayerID * playerId)1105 void RakPeer::IPToPlayerID( const char* host, unsigned short remotePort, PlayerID *playerId )
1106 {
1107 	if ( host == 0 )
1108 		return ;
1109 
1110 	playerId->binaryAddress = inet_addr( host );
1111 
1112 	playerId->port = remotePort;
1113 }
1114 
1115 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetRemoteSystemFromPlayerID(PlayerID playerID) const1116 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromPlayerID( PlayerID playerID ) const
1117 {
1118 	unsigned i;
1119 
1120 	if ( playerID == UNASSIGNED_PLAYER_ID )
1121 		return 0;
1122 
1123 	for ( i = 0; i < remoteSystemListSize; i++ )
1124 		if ( remoteSystemList[ i ].playerId == playerID )
1125 			return remoteSystemList + i;
1126 
1127 	return 0;
1128 }
1129 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ParseConnectionRequestPacket(RakPeer::RemoteSystemStruct * remoteSystem,PlayerID playerId,const char * data,int byteSize)1130 void RakPeer::ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, PlayerID playerId, const char *data, int byteSize )
1131 {
1132 	// If we are full tell the sender.
1133 	if ( !AllowIncomingConnections() )
1134 	{
1135 		unsigned char c = ID_NO_FREE_INCOMING_CONNECTIONS;
1136 		// SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, ( char* ) & c, sizeof( char ), playerId.binaryAddress, playerId.port );
1137 		SendImmediate(( char* ) & c, sizeof( char )*8, SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, false, RakNet::GetTime());
1138 		remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
1139 	}
1140 	else
1141 	{
1142 		remoteSystem->connectMode=RemoteSystemStruct::HANDLING_CONNECTION_REQUEST;
1143 
1144 		// Connect this player assuming we have open slots
1145 		OnConnectionRequest( remoteSystem );
1146 	}
1147 }
1148 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OnConnectionRequest(RakPeer::RemoteSystemStruct * remoteSystem)1149 void RakPeer::OnConnectionRequest( RakPeer::RemoteSystemStruct *remoteSystem )
1150 {
1151 	if ( AllowIncomingConnections() )
1152 	{
1153 
1154 
1155 		RakNet::BitStream bitStream(sizeof(unsigned char)+sizeof(unsigned short)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(PlayerIndex));
1156 		bitStream.Write((unsigned char)ID_CONNECTION_REQUEST_ACCEPTED);
1157 		bitStream.Write((unsigned short)myPlayerId.port);
1158 
1159 		bitStream.Write(remoteSystem->playerId.binaryAddress);
1160 		bitStream.Write(remoteSystem->playerId.port);
1161 		bitStream.Write(( PlayerIndex ) GetIndexFromPlayerID( remoteSystem->playerId ));
1162 
1163 		SendImmediate((char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, RELIABLE, 0, remoteSystem->playerId, false, false, RakNet::GetTime());
1164 	}
1165 	else
1166 	{
1167 		unsigned char c = ID_NO_FREE_INCOMING_CONNECTIONS;
1168 
1169 		SendImmediate((char*)&c, sizeof(c)*8, SYSTEM_PRIORITY, RELIABLE, 0, remoteSystem->playerId, false, false, RakNet::GetTime());
1170 		remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
1171 	}
1172 }
1173 
1174 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NotifyAndFlagForDisconnect(PlayerID playerId,bool performImmediate)1175 void RakPeer::NotifyAndFlagForDisconnect( PlayerID playerId, bool performImmediate )
1176 {
1177 	RakNet::BitStream temp( sizeof(unsigned char) );
1178 	temp.Write( (unsigned char) ID_DISCONNECTION_NOTIFICATION );
1179 	if (performImmediate)
1180 	{
1181 		SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, false, RakNet::GetTime());
1182 		RemoteSystemStruct *rss=GetRemoteSystemFromPlayerID(playerId);
1183 		rss->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
1184 	}
1185 	else
1186 	{
1187 		SendBuffered(&temp, SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, RemoteSystemStruct::DISCONNECT_ASAP);
1188 	}
1189 }
1190 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GetNumberOfRemoteInitiatedConnections(void) const1191 unsigned short RakPeer::GetNumberOfRemoteInitiatedConnections( void ) const
1192 {
1193 	unsigned short i, numberOfIncomingConnections;
1194 
1195 	if ( remoteSystemList == 0 || endThreads == true )
1196 		return 0;
1197 
1198 	numberOfIncomingConnections = 0;
1199 
1200 	for ( i = 0; i < remoteSystemListSize; i++ )
1201 	{
1202 		if ( remoteSystemList[ i ].playerId != UNASSIGNED_PLAYER_ID && remoteSystemList[ i ].weInitiatedTheConnection == false && remoteSystemList[i].connectMode==RemoteSystemStruct::CONNECTED)
1203 			numberOfIncomingConnections++;
1204 	}
1205 
1206 	return numberOfIncomingConnections;
1207 }
1208 
1209 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AssignPlayerIDToRemoteSystemList(PlayerID playerId,RemoteSystemStruct::ConnectMode connectionMode)1210 RakPeer::RemoteSystemStruct * RakPeer::AssignPlayerIDToRemoteSystemList( PlayerID playerId, RemoteSystemStruct::ConnectMode connectionMode )
1211 {
1212 	RemoteSystemStruct * remoteSystem = 0;
1213 	unsigned i;
1214 	unsigned int time = RakNet::GetTime();
1215 
1216 	// If this guy is already connected, return 0. This needs to be checked inside the mutex
1217 	// because threads may call the connection routine multiple times at the same time
1218 	for ( i = 0; i < remoteSystemListSize; i++ )
1219 	{
1220 		if ( remoteSystemList[ i ].playerId == playerId )
1221 		{
1222 			return 0;
1223 		}
1224 	}
1225 
1226 	for ( i = 0; i < remoteSystemListSize; i++ )
1227 	{
1228 		if ( remoteSystemList[ i ].playerId == UNASSIGNED_PLAYER_ID)
1229 		{
1230 			remoteSystem=remoteSystemList+i;
1231 			remoteSystem->playerId = playerId; // This one line causes future incoming packets to go through the reliability layer
1232 
1233 			remoteSystem->pingTime = -1;
1234 
1235 			remoteSystem->connectMode=connectionMode;
1236 			remoteSystem->lowestPing = -1;
1237 			remoteSystem->nextPingTime = 0; // Ping immediately
1238 			remoteSystem->weInitiatedTheConnection = false;
1239 			remoteSystem->connectionTime = time;
1240 			remoteSystem->myExternalPlayerId = UNASSIGNED_PLAYER_ID;
1241 			remoteSystem->lastReliableSend=time;
1242 
1243 			// Reserve this reliability layer for ourselves.
1244 			remoteSystem->reliabilityLayer.Reset();
1245 
1246 			return remoteSystem;
1247 		}
1248 	}
1249 
1250 	return remoteSystem;
1251 }
1252 
1253 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PushPortRefused(PlayerID target)1254 void RakPeer::PushPortRefused( PlayerID target )
1255 {
1256 	// Tell the game we can't connect to this host
1257 	Packet * p;
1258 	p = packetPool.GetPointer();
1259 	p->data = new unsigned char[ 1 ];
1260 	p->data[ 0 ] = ID_REMOTE_PORT_REFUSED;
1261 	p->length = sizeof( char );
1262 	p->playerId = target; // We don't know this!
1263 	p->playerIndex = ( PlayerIndex ) GetIndexFromPlayerID( p->playerId );
1264 
1265 #ifdef _DEBUG
1266 
1267 	assert( p->data );
1268 #endif
1269 	// Relay this message to the game
1270 	incomingQueueMutex.Lock();
1271 	incomingPacketQueue.push( p );
1272 	incomingQueueMutex.Unlock();
1273 }
1274 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AllowIncomingConnections(void) const1275 bool RakPeer::AllowIncomingConnections(void) const
1276 {
1277 	return GetNumberOfRemoteInitiatedConnections() < GetMaximumIncomingConnections();
1278 }
1279 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PingInternal(PlayerID target,bool performImmediate)1280 void RakPeer::PingInternal( PlayerID target, bool performImmediate )
1281 {
1282 	if ( IsActive() == false )
1283 		return ;
1284 
1285 	RakNet::BitStream bitStream(sizeof(unsigned char)+sizeof(unsigned int));
1286 	bitStream.Write((unsigned char)ID_CONNECTED_PING);
1287 	unsigned int currentTime = RakNet::GetTime();
1288 	bitStream.Write(currentTime);
1289 	if (performImmediate)
1290 		SendImmediate( (char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, UNRELIABLE, 0, target, false, false, currentTime );
1291 	else
1292 		Send( &bitStream, SYSTEM_PRIORITY, UNRELIABLE, 0, target, false );
1293 }
1294 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloseConnectionInternalBuffered(PlayerID target,bool sendDisconnectionNotification)1295 void RakPeer::CloseConnectionInternalBuffered( PlayerID target, bool sendDisconnectionNotification )
1296 {
1297 	if ( remoteSystemList == 0 || endThreads == true )
1298 		return;
1299 
1300 	if (sendDisconnectionNotification)
1301 	{
1302 		NotifyAndFlagForDisconnect(target, false);
1303 	}
1304 	else
1305 	{
1306 		BufferedCommandStruct *bcs;
1307 		bcs=bufferedCommands.WriteLock();
1308 		bcs->command=BufferedCommandStruct::BCS_CLOSE_CONNECTION;
1309 		bcs->playerId=target;
1310 		bcs->data=0;
1311 		bufferedCommands.WriteUnlock();
1312 	}
1313 }
1314 
1315 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloseConnectionInternalImmediate(PlayerID target)1316 void RakPeer::CloseConnectionInternalImmediate( PlayerID target)
1317 {
1318 	if ( remoteSystemList == 0 || endThreads == true )
1319 		return;
1320 
1321 	for (unsigned int i = 0 ; i < remoteSystemListSize; i++ )
1322 	{
1323 		if ( remoteSystemList[ i ].playerId == target )
1324 		{
1325 			// Reserve this reliability layer for ourselves
1326 			remoteSystemList[ i ].playerId = UNASSIGNED_PLAYER_ID;
1327 			//	remoteSystemList[ i ].allowPlayerIdAssigment=false;
1328 
1329 			// Remove any remaining packets.
1330 			remoteSystemList[ i ].reliabilityLayer.Reset();
1331 			break;
1332 		}
1333 	}
1334 
1335 }
1336 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ValidSendTarget(PlayerID playerId,bool broadcast)1337 bool RakPeer::ValidSendTarget(PlayerID playerId, bool broadcast)
1338 {
1339 	unsigned remoteSystemIndex;
1340 	for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; remoteSystemIndex++ )
1341 	{
1342 		if ( remoteSystemList[ remoteSystemIndex ].playerId != UNASSIGNED_PLAYER_ID &&
1343 			remoteSystemList[ remoteSystemIndex ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED && // Not fully connected players are not valid user-send targets because the reliability layer wasn't reset yet
1344 			( ( broadcast == false && remoteSystemList[ remoteSystemIndex ].playerId == playerId ) ||
1345 			( broadcast == true && remoteSystemList[ remoteSystemIndex ].playerId != playerId ) )
1346 			)
1347 			return true;
1348 	}
1349 
1350 	return false;
1351 }
1352 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendBuffered(const RakNet::BitStream * bitStream,PacketPriority priority,PacketReliability reliability,char orderingChannel,PlayerID playerId,bool broadcast,RemoteSystemStruct::ConnectMode connectionMode)1353 void RakPeer::SendBuffered( const RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, RemoteSystemStruct::ConnectMode connectionMode )
1354 {
1355 	BufferedCommandStruct *bcs;
1356 	bcs=bufferedCommands.WriteLock();
1357 
1358 	bcs->data = new char[bitStream->GetNumberOfBytesUsed()]; // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
1359 	memcpy(bcs->data, bitStream->GetData(), bitStream->GetNumberOfBytesUsed());
1360     bcs->numberOfBitsToSend=bitStream->GetNumberOfBitsUsed();
1361 	bcs->priority=priority;
1362 	bcs->reliability=reliability;
1363 	bcs->orderingChannel=orderingChannel;
1364 	bcs->playerId=playerId;
1365 	bcs->broadcast=broadcast;
1366 	bcs->connectionMode=connectionMode;
1367 	bcs->command=BufferedCommandStruct::BCS_SEND;
1368 	bufferedCommands.WriteUnlock();
1369 }
1370 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SendImmediate(char * data,int numberOfBitsToSend,PacketPriority priority,PacketReliability reliability,char orderingChannel,PlayerID playerId,bool broadcast,bool useCallerDataAllocation,unsigned int currentTime)1371 bool RakPeer::SendImmediate( char *data, int numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool useCallerDataAllocation, unsigned int currentTime )
1372 {
1373 	unsigned *sendList;
1374 	unsigned sendListSize;
1375 	bool callerDataAllocationUsed;
1376 	unsigned remoteSystemIndex, sendListIndex; // Iterates into the list of remote systems
1377 	callerDataAllocationUsed=false;
1378 
1379 	sendList=(unsigned *)alloca(sizeof(unsigned)*remoteSystemListSize);
1380 	sendListSize=0;
1381 
1382 	for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; remoteSystemIndex++ )
1383 	{
1384 		if ( remoteSystemList[ remoteSystemIndex ].playerId != UNASSIGNED_PLAYER_ID &&
1385 			( ( broadcast == false && remoteSystemList[ remoteSystemIndex ].playerId == playerId ) ||
1386 			( broadcast == true && remoteSystemList[ remoteSystemIndex ].playerId != playerId ) )	)
1387 				sendList[sendListSize++]=remoteSystemIndex;
1388 	}
1389 
1390 	if (sendListSize==0)
1391 		return false;
1392 
1393 	for (sendListIndex=0; sendListIndex < sendListSize; sendListIndex++)
1394 	{
1395 		// Send may split the packet and thus deallocate data.  Don't assume data is valid if we use the callerAllocationData
1396 		bool useData = useCallerDataAllocation && callerDataAllocationUsed==false && sendListIndex+1==sendListSize;
1397 		remoteSystemList[sendList[sendListIndex]].reliabilityLayer.Send( data, numberOfBitsToSend, priority, reliability, orderingChannel, useData==false, MTUSize, currentTime );
1398 		if (useData)
1399 			callerDataAllocationUsed=true;
1400 
1401 
1402 		if (reliability==RELIABLE || reliability==RELIABLE_ORDERED || reliability==RELIABLE_SEQUENCED)
1403 			remoteSystemList[sendList[sendListIndex]].lastReliableSend=currentTime;
1404 	}
1405 
1406 	// 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
1407 	return callerDataAllocationUsed;
1408 }
1409 
1410 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearBufferedCommands(void)1411 void RakPeer::ClearBufferedCommands(void)
1412 {
1413 	BufferedCommandStruct *bcs;
1414 	while ((bcs=bufferedCommands.ReadLock())!=0)
1415 	{
1416 		if (bcs->data)
1417 			delete [] bcs->data;
1418 
1419         bufferedCommands.ReadUnlock();
1420 	}
1421 	bufferedCommands.Clear();
1422 }
1423 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ClearRequestedConnectionList(void)1424 void RakPeer::ClearRequestedConnectionList(void)
1425 {
1426 	RequestedConnectionStruct *bcs;
1427 	while ((bcs=requestedConnectionList.ReadLock())!=0)
1428 	{
1429 		if (bcs->data)
1430 			delete [] bcs->data;
1431 
1432 		requestedConnectionList.ReadUnlock();
1433 	}
1434 	requestedConnectionList.Clear();
1435 }
1436 
1437 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1438 #ifdef _WIN32
ProcessNetworkPacket(unsigned int binaryAddress,unsigned short port,const char * data,int length,RakPeer * rakPeer)1439 void __stdcall ProcessNetworkPacket( unsigned int binaryAddress, unsigned short port, const char *data, int length, RakPeer *rakPeer )
1440 #else
1441 void ProcessNetworkPacket( unsigned int binaryAddress, unsigned short port, const char *data, int length, RakPeer *rakPeer )
1442 #endif
1443 {
1444 	PlayerID playerId;
1445 //	unsigned i;
1446 	RakPeer::RemoteSystemStruct *remoteSystem;
1447 	playerId.binaryAddress = binaryAddress;
1448 	playerId.port = port;
1449 
1450 	// UNCONNECTED MESSAGE to establish a connection
1451 	if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REPLY && length == sizeof(unsigned char))
1452 	{
1453 		// Verify that we were waiting for this
1454 		bool acceptOpenConnection;
1455 		int actionToTake=0;
1456 		char data[MAX_OFFLINE_DATA_LENGTH];
1457 		unsigned short dataLength;
1458 		RakPeer::RequestedConnectionStruct *rcsFirst, *rcs;
1459 		rcsFirst = rakPeer->requestedConnectionList.ReadLock();
1460 		rcs=rcsFirst;
1461 		acceptOpenConnection=false;
1462 		while (rcs)
1463 		{
1464 			if (rcs->playerId==playerId)
1465 			{
1466 				acceptOpenConnection=true;
1467 				actionToTake|=(int)rcs->actionToTake;
1468 				if (rcs->data)
1469 				{
1470 #ifdef _DEBUG
1471 					assert(rcs->actionToTake==RakPeer::RequestedConnectionStruct::ADVERTISE_SYSTEM);
1472 					assert(rcs->dataLength <= MAX_OFFLINE_DATA_LENGTH);
1473 #endif
1474 					memcpy(data, rcs->data, rcs->dataLength);
1475 					dataLength=rcs->dataLength;
1476 					delete [] rcs->data;
1477 					rcs->data=0;
1478 				}
1479 
1480 				if (rcs==rcsFirst)
1481 				{
1482 					rakPeer->requestedConnectionList.ReadUnlock();
1483 					rcsFirst=rakPeer->requestedConnectionList.ReadLock();
1484 					rcs=rcsFirst;
1485 					continue;
1486 				}
1487 				else
1488 				{
1489 					// Duplicate call - cancel it
1490 					rcs->playerId=UNASSIGNED_PLAYER_ID;
1491 				}
1492 			}
1493 
1494 			rcs=rakPeer->requestedConnectionList.ReadLock();
1495 		}
1496 		if (rcsFirst)
1497 			rakPeer->requestedConnectionList.CancelReadLock(rcsFirst);
1498 
1499 		if (acceptOpenConnection)
1500 		{
1501 			remoteSystem=rakPeer->AssignPlayerIDToRemoteSystemList(playerId, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER);
1502 	//		if (remoteSystem==0)
1503 	//			remoteSystem=rakPeer->GetRemoteSystemFromPlayerID(playerId); // Get the already connected guy
1504 			if (remoteSystem)
1505 			{
1506 				unsigned int time = RakNet::GetTime();
1507 				if (actionToTake & RakPeer::RequestedConnectionStruct::CONNECT)
1508 				{
1509 					remoteSystem->connectMode=RakPeer::RemoteSystemStruct::REQUESTED_CONNECTION;
1510 					remoteSystem->weInitiatedTheConnection=true;
1511 
1512 					RakNet::BitStream temp( sizeof(unsigned char) );
1513 					temp.Write( (unsigned char) ID_CONNECTION_REQUEST );
1514 					rakPeer->SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, false, time );
1515 				}
1516 
1517 				if ((actionToTake & RakPeer::RequestedConnectionStruct::PING) || (actionToTake & RakPeer::RequestedConnectionStruct::PING_OPEN_CONNECTIONS))
1518 				{
1519 					RakNet::BitStream temp( sizeof(unsigned char) + sizeof(unsigned int) );
1520 					if ( actionToTake & RakPeer::RequestedConnectionStruct::PING_OPEN_CONNECTIONS )
1521 						temp.Write((unsigned char)ID_UNCONNECTED_PING_OPEN_CONNECTIONS);
1522 					else
1523 						temp.Write((unsigned char)ID_UNCONNECTED_PING);
1524 					temp.Write(time);
1525 
1526 //					SocketLayer::Instance()->SendTo( connectionSocket, (const char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), ( char* ) host, remotePort );
1527 					rakPeer->SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, false, time );
1528 				}
1529 
1530 				if (actionToTake & RakPeer::RequestedConnectionStruct::ADVERTISE_SYSTEM)
1531 				{
1532 					RakNet::BitStream temp;
1533 					temp.Write((unsigned char)ID_ADVERTISE_SYSTEM);
1534 					if (dataLength>0)
1535 						temp.Write(data, dataLength);
1536 					rakPeer->SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, false, time );
1537 					remoteSystem->connectMode=RakPeer::RemoteSystemStruct::DISCONNECT_ASAP;
1538 				}
1539 			}
1540 		}
1541 
1542 		return;
1543 	}
1544 	// UNCONNECTED MESSAGE Broadcast ping with no data
1545 	else if ( ( (unsigned char) data[ 0 ] == ID_UNCONNECTED_PING_OPEN_CONNECTIONS
1546 		|| (unsigned char)(data)[0] == ID_UNCONNECTED_PING)	&& length == sizeof(unsigned char) )
1547 	{
1548 		if ( (unsigned char)(data)[0] == ID_UNCONNECTED_PING ||
1549 			rakPeer->AllowIncomingConnections() ) // Open connections with players
1550 		{
1551 			RakNet::BitStream outBitStream;
1552 			outBitStream.Write((unsigned char)ID_PONG); // Should be named ID_UNCONNECTED_PONG eventually
1553 			SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, (const char*)outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), (char*)rakPeer->PlayerIDToDottedIP(playerId) , playerId.port );
1554 		}
1555 
1556 		return;
1557 	}
1558 	// UNCONNECTED MESSAGE Pong with no data
1559 	else if ((unsigned char) data[ 0 ] == ID_PONG && length == sizeof(unsigned char) )
1560 	{
1561 		Packet * packet = rakPeer->packetPool.GetPointer();
1562 		packet->data = new unsigned char[ sizeof( char )+sizeof(unsigned int) ];
1563 		unsigned int zero=0;
1564 		packet->data[ 0 ] = ID_PONG;
1565 		memcpy(packet->data+sizeof( char ), (char*)&zero, sizeof(unsigned int));
1566 		packet->length = sizeof( char );
1567 		packet->bitSize = sizeof( char ) * 8;
1568 		packet->playerId = playerId;
1569 		packet->playerIndex = ( PlayerIndex ) rakPeer->GetIndexFromPlayerID( playerId );
1570 		rakPeer->incomingQueueMutex.Lock();
1571 		rakPeer->incomingPacketQueue.push( packet );
1572 		rakPeer->incomingQueueMutex.Unlock();
1573 		return;
1574 	}
1575 
1576 	remoteSystem = rakPeer->GetRemoteSystemFromPlayerID( playerId );
1577 	if ( remoteSystem )
1578 	{
1579 		// Handle regular incoming data
1580 		// HandleSocketReceiveFromConnectedPlayer is only safe to be called from the same thread as Update, which is this thread
1581 		if ( remoteSystem->reliabilityLayer.HandleSocketReceiveFromConnectedPlayer( data, length ) == false )
1582 		{
1583 			// These kinds of packets may have been duplicated and incorrectly determined to be
1584 			// cheat packets.  Anything else really is a cheat packet
1585 			if ( !(
1586 			( (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST && length == 1 ) ||
1587 			( (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY && length == 1 ) ||
1588 			(((unsigned char)data[0] == ID_UNCONNECTED_PING_OPEN_CONNECTIONS || (unsigned char)(data)[0] == ID_UNCONNECTED_PING) && length == sizeof(unsigned char)+sizeof(unsigned int) ) ||
1589 			( (unsigned char)data[0] == ID_PONG && length >= sizeof(unsigned char)+sizeof(unsigned int) ) ||
1590 			( (unsigned char)data[0] == ID_ADVERTISE_SYSTEM && length<MAX_OFFLINE_DATA_LENGTH )
1591 			) )
1592 			{
1593 				// Cheater
1594 				Packet * packet = rakPeer->packetPool.GetPointer();
1595 				packet->data = new unsigned char[ 1 ];
1596 				packet->data[ 0 ] = ID_MODIFIED_PACKET;
1597 				packet->length = sizeof( char );
1598 				packet->bitSize = sizeof( char ) * 8;
1599 				packet->playerId = playerId;
1600 				packet->playerIndex = ( PlayerIndex ) rakPeer->GetIndexFromPlayerID( playerId );
1601 				rakPeer->incomingQueueMutex.Lock();
1602 				rakPeer->incomingPacketQueue.push( packet );
1603 				rakPeer->incomingQueueMutex.Unlock();
1604 			}
1605 		}
1606 	}
1607 	else
1608 	{
1609 
1610 		// The reason for ID_OPEN_CONNECTION_REQUEST and ID_OPEN_CONNECTION_REPLY is that they are only one byte so I can be sure
1611 		// that they are offline messages and I know to reset the connections.  This is because the smallest possible connected packet is 17 bits.
1612 		// This is the only way I can tell for sure that a message is asking for a new connection.
1613 		// This fixes bugs where I ignore a connection request from a connected player or handle a message that looks like a connection request but actually wasn't.
1614 		if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST && length == sizeof(unsigned char))
1615 		{
1616 			remoteSystem=rakPeer->AssignPlayerIDToRemoteSystemList(playerId, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER);
1617 			if (remoteSystem) // If this guy is already connected remote system will be 0
1618 			{
1619 				char c = ID_OPEN_CONNECTION_REPLY;
1620 				SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, (char*)&c, 1, playerId.binaryAddress, playerId.port );
1621 			}
1622 		}
1623 	}
1624 }
1625 
1626 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RunUpdateCycle(void)1627 bool RakPeer::RunUpdateCycle( void )
1628 {
1629 	RakPeer::RemoteSystemStruct * remoteSystem;
1630 	unsigned remoteSystemIndex;
1631 	Packet *packet;
1632 	int ping, lastPing;
1633 	// int currentSentBytes,currentReceivedBytes;
1634 //	unsigned numberOfBytesUsed;
1635 	//PlayerID authoritativeClientPlayerId;
1636 	int bitSize, byteSize;
1637 	char *data;
1638 	int errorCode;
1639 	int gotData;
1640 	unsigned int time;
1641 	PlayerID playerId;
1642 	BufferedCommandStruct *bcs;
1643 	bool callerDataAllocationUsed;
1644 	RakNetStatisticsStruct *rnss;
1645 
1646 	do
1647 	{
1648 		// Read a packet
1649 		gotData = SocketLayer::Instance()->RecvFrom( connectionSocket, this, &errorCode );
1650 
1651 		if ( gotData == SOCKET_ERROR )
1652 		{
1653 #ifdef _WIN32
1654 			if ( errorCode == WSAECONNRESET )
1655 			{
1656 				gotData=false;
1657 				// 11/14/05 - RecvFrom now calls HandlePortUnreachable rather than PushPortRefused
1658 				//PushPortRefused( UNASSIGNED_PLAYER_ID );
1659 				//closesocket(peer->connectionSocket);
1660 
1661 				//peer->connectionSocket = SocketLayer::Instance()->CreateBoundSocket(peer->myPlayerId.port, true);
1662 			}
1663 			else
1664 				if ( errorCode != 0 && endThreads == false )
1665 				{
1666 #ifdef _DO_PRINTF
1667 					printf( "Server RecvFrom critical failure!\n" );
1668 #endif
1669 					// Some kind of critical error
1670 					// peer->isRecvfromThreadActive=false;
1671 					endThreads = true;
1672 					Disconnect( 0 );
1673 					return false;
1674 				}
1675 
1676 #else
1677 			if ( errorCode == -1 )
1678 			{
1679 				// isRecvfromThreadActive=false;
1680 				endThreads = true;
1681 				Disconnect( 0 );
1682 				return false;
1683 			}
1684 #endif
1685 		}
1686 
1687 		if ( endThreads )
1688 			return false;
1689 	}
1690 	while ( gotData>0 ); // Read until there is nothing left
1691 
1692 	time=0;
1693 
1694 	// Process all the deferred user thread Send and connect calls
1695 
1696 	while ( ( bcs = bufferedCommands.ReadLock() ) != 0 ) // Don't immediately check mutex since it's so slow to activate it
1697 	{
1698 		if (bcs->command==BufferedCommandStruct::BCS_SEND)
1699 		{
1700 			// This will create a new connection if requested
1701 			if (bcs->connectionMode!=RemoteSystemStruct::NO_ACTION)
1702 			{
1703 				remoteSystem=AssignPlayerIDToRemoteSystemList(bcs->playerId, bcs->connectionMode);
1704 				if (!remoteSystem)
1705 				{
1706 					// Does this system already exist?
1707 					remoteSystem=GetRemoteSystemFromPlayerID(bcs->playerId);
1708 					if (remoteSystem)
1709 						remoteSystem->connectMode=bcs->connectionMode;
1710 				}
1711 			}
1712 
1713 			// GetTime is a very slow call so do it once and as late as possible
1714 			if (time==0)
1715 				time = RakNet::GetTime();
1716 
1717 			callerDataAllocationUsed=SendImmediate((char*)bcs->data, bcs->numberOfBitsToSend, bcs->priority, bcs->reliability, bcs->orderingChannel, bcs->playerId, bcs->broadcast, true, time);
1718 			if ( callerDataAllocationUsed==false )
1719 				delete [] bcs->data;
1720 		}
1721 		else
1722 		{
1723 #ifdef _DEBUG
1724 			assert(bcs->command==BufferedCommandStruct::BCS_CLOSE_CONNECTION);
1725 #endif
1726 			CloseConnectionInternalImmediate(bcs->playerId);
1727 		}
1728 
1729 #ifdef _DEBUG
1730 		bcs->data=0;
1731 #endif
1732 		bufferedCommands.ReadUnlock();
1733 	}
1734 
1735 	// Process connection attempts
1736 	RequestedConnectionStruct *rcsFirst, *rcs;
1737 	bool condition1, condition2;
1738     rcsFirst = requestedConnectionList.ReadLock();
1739 	rcs=rcsFirst;
1740 	while (rcs)
1741 	{
1742 		if (time==0)
1743 			time = RakNet::GetTime();
1744 
1745 		if (rcs->nextRequestTime < time)
1746 		{
1747 			condition1=rcs->requestsMade==3;
1748 			condition2=(bool)((rcs->playerId==UNASSIGNED_PLAYER_ID)==1);
1749 			// If too many requests made or a hole then remove this if possible, otherwise invalidate it
1750 			if (condition1 || condition2)
1751 			{
1752 				if (rcs->data)
1753 				{
1754 					delete [] rcs->data;
1755 					rcs->data=0;
1756 				}
1757 
1758 				if (condition1 && !condition2 && rcs->actionToTake==RequestedConnectionStruct::CONNECT)
1759 				{
1760 					// Tell user of connection attempt failed
1761 					packet = packetPool.GetPointer();
1762 					packet->data = new unsigned char [ sizeof( char ) ];
1763 					packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
1764 					packet->length = sizeof( char );
1765 					packet->bitSize = ( sizeof( char ) * 8);
1766 					packet->playerId = myPlayerId;
1767 					packet->playerIndex = 65535;
1768 
1769 					incomingQueueMutex.Lock();
1770 					( incomingPacketQueue ).push( packet );
1771 					incomingQueueMutex.Unlock();
1772 				}
1773 
1774 				// Remove this if possible
1775 				if (rcs==rcsFirst)
1776 				{
1777 					requestedConnectionList.ReadUnlock();
1778 					rcsFirst = requestedConnectionList.ReadLock();
1779 					rcs=rcsFirst;
1780 				}
1781 				else
1782 				{
1783 					// Hole in the middle
1784 					rcs->playerId=UNASSIGNED_PLAYER_ID;
1785 					rcs=requestedConnectionList.ReadLock();
1786 				}
1787 
1788 				continue;
1789 			}
1790 
1791 			rcs->requestsMade++;
1792 			rcs->nextRequestTime=time+1000;
1793 			char c = ID_OPEN_CONNECTION_REQUEST;
1794 
1795 			SocketLayer::Instance()->SendTo( connectionSocket, (char*)&c, 1, ( char* ) PlayerIDToDottedIP(rcs->playerId), rcs->playerId.port );
1796 		}
1797 
1798 		rcs=requestedConnectionList.ReadLock();
1799 	}
1800 
1801 	if (rcsFirst)
1802 		requestedConnectionList.CancelReadLock(rcsFirst);
1803 
1804 	for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; ++remoteSystemIndex )
1805 	{
1806 		// I'm using playerId from remoteSystemList but am not locking it because this loop is called very frequently and it doesn't
1807 		// matter if we miss or do an extra update.  The reliability layers themselves never care which player they are associated with
1808 		playerId = remoteSystemList[ remoteSystemIndex ].playerId;
1809 		// Allow the playerID for this remote system list to change.  We don't care if it changes now.
1810 	//	remoteSystemList[ remoteSystemIndex ].allowPlayerIdAssigment=true;
1811 		if ( playerId != UNASSIGNED_PLAYER_ID )
1812 		{
1813 			// Found an active remote system
1814 			remoteSystem = remoteSystemList + remoteSystemIndex;
1815 			// Update is only safe to call from the same thread that calls HandleSocketReceiveFromConnectedPlayer,
1816 			// which is this thread
1817 
1818 			if (time==0)
1819 				time = RakNet::GetTime();
1820 
1821 
1822 			if (time > remoteSystem->lastReliableSend && time-remoteSystem->lastReliableSend > 5000 && remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
1823 			{
1824 				// If no reliable packets are waiting for an ack, do a one byte reliable send so that disconnections are noticed
1825 				rnss=remoteSystem->reliabilityLayer.GetStatistics();
1826 				if (rnss->messagesOnResendQueue==0)
1827 				{
1828 					unsigned char keepAlive=ID_KEEPALIVE;
1829 					SendImmediate((char*)&keepAlive,8,LOW_PRIORITY, RELIABLE, 0, remoteSystem->playerId, false, false, time);
1830 					remoteSystem->lastReliableSend=time+TIMEOUT_TIME;
1831 				}
1832 			}
1833 
1834 			remoteSystem->reliabilityLayer.Update( connectionSocket, playerId, MTUSize, time ); // playerId only used for the internet simulator test
1835 
1836 			// Check for failure conditions
1837 			if ( remoteSystem->reliabilityLayer.IsDeadConnection() ||
1838 				(remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP && remoteSystem->reliabilityLayer.IsDataWaiting()==false) ||
1839 				((remoteSystem->connectMode!=RemoteSystemStruct::CONNECTED && time > remoteSystem->connectionTime && time - remoteSystem->connectionTime > 10000))
1840 				)
1841 			{
1842 				// Failed.  Inform the user?
1843 				if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED || remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
1844 				{
1845 					// Inform the user of the connection failure.
1846 					packet = packetPool.GetPointer();
1847 
1848 					packet->data = new unsigned char [ sizeof( char ) ];
1849 					if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
1850 						packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
1851 					else
1852 						packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
1853 
1854 					packet->length = sizeof( char );
1855 					packet->bitSize = sizeof( char ) * 8;
1856 					packet->playerId = playerId;
1857 					packet->playerIndex = ( PlayerIndex ) remoteSystemIndex;
1858 
1859 					incomingQueueMutex.Lock();
1860 					( incomingPacketQueue ).push( packet );
1861 					incomingQueueMutex.Unlock();
1862 				}
1863 				// else connection shutting down, don't bother telling the user
1864 
1865 #ifdef _DO_PRINTF
1866 				printf("Connection dropped for player %i:%i\n", playerId.binaryAddress, playerId.port);
1867 #endif
1868 				CloseConnectionInternalImmediate( playerId );
1869 				continue;
1870 			}
1871 
1872 			// Ping this guy if it is time to do so
1873 			if ( remoteSystem->connectMode==RemoteSystemStruct::CONNECTED && time > remoteSystem->nextPingTime && ( remoteSystem->lowestPing == -1 ) )
1874 			{
1875 				remoteSystem->nextPingTime = time + 5000;
1876 				PingInternal( playerId, true );
1877 			}
1878 
1879 			// Find whoever has the lowest player ID
1880 			//if (playerId < authoritativeClientPlayerId)
1881 			// authoritativeClientPlayerId=playerId;
1882 
1883 			// Does the reliability layer have any packets waiting for us?
1884 			// To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
1885 			bitSize = remoteSystem->reliabilityLayer.Receive( &data );
1886 
1887 			while ( bitSize > 0 )
1888 			{
1889 				// Fast and easy - just use the data that was returned
1890 				byteSize = BITS_TO_BYTES( bitSize );
1891 
1892 				// For unknown senders we only accept a few specific packets
1893 				if (remoteSystem->connectMode==RemoteSystemStruct::UNVERIFIED_SENDER)
1894 				{
1895 					if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
1896 					{
1897 						ParseConnectionRequestPacket(remoteSystem, playerId, data, byteSize);
1898 						delete [] data;
1899 					}
1900 					else if ( ((unsigned char) data[0] == ID_PONG && byteSize >= sizeof(unsigned char)+sizeof(unsigned int)) ||
1901 						((unsigned char) data[0] == ID_ADVERTISE_SYSTEM && byteSize<=MAX_OFFLINE_DATA_LENGTH))
1902 					{
1903 						// Push to the user
1904 						Packet *packet = packetPool.GetPointer();
1905 						packet->data = ( unsigned char* ) data;
1906 						packet->length = byteSize;
1907 						packet->bitSize = byteSize*8;
1908 						packet->playerId = playerId;
1909 						packet->playerIndex=65535;
1910 						incomingQueueMutex.Lock();
1911 						incomingPacketQueue.push( packet );
1912 						incomingQueueMutex.Unlock();
1913 
1914 						if (remoteSystem->connectMode!=RemoteSystemStruct::CONNECTED)
1915 						{
1916 							remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
1917 						}
1918 					}
1919 					else if ( ( (unsigned char) data[ 0 ] == ID_UNCONNECTED_PING_OPEN_CONNECTIONS
1920 						|| (unsigned char)(data)[0] == ID_UNCONNECTED_PING)
1921 						&& byteSize == sizeof(unsigned char)+sizeof(unsigned int) )
1922 					{
1923 						RakNet::BitStream inBitStream( data, byteSize, false );
1924 						inBitStream.IgnoreBits(8);
1925 						unsigned int sendPingTime;
1926 						inBitStream.Read(sendPingTime);
1927 
1928 						if ( (unsigned char)(data)[0] == ID_UNCONNECTED_PING ||
1929 							AllowIncomingConnections() ) // Open connections with players
1930 						{
1931 							RakNet::BitStream outBitStream;
1932 							outBitStream.Write((unsigned char)ID_PONG); // Should be named ID_UNCONNECTED_PONG eventually
1933 							outBitStream.Write(sendPingTime);
1934 							SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, UNRELIABLE, 0, playerId, false, false, time );
1935 						}
1936 						// else ID_UNCONNECTED_PING_OPEN_CONNECTIONS and we are full so don't send anything
1937 
1938 						delete [] data;
1939 
1940 						// Disconnect them after replying to their offline ping
1941 						if (remoteSystem->connectMode!=RemoteSystemStruct::CONNECTED)
1942 							remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
1943 					}
1944 					else
1945 					{
1946 						CloseConnectionInternalImmediate( playerId );
1947 #ifdef _DO_PRINTF
1948 						printf("Temporarily banning %i:%i for sending nonsense data\n", playerId.binaryAddress, playerId.port);
1949 #endif
1950 						delete [] data;
1951 					}
1952 				}
1953 				else
1954 				{
1955 					// However, if we are connected we still take a connection request in case both systems are trying to connect to each other
1956 					// at the same time
1957 					if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
1958 					{
1959 						if (remoteSystem->weInitiatedTheConnection==false)
1960 							ParseConnectionRequestPacket(remoteSystem, playerId, data, byteSize);
1961 						delete [] data;
1962 					}
1963 					else if ( (unsigned char) data[ 0 ] == ID_NEW_INCOMING_CONNECTION && byteSize == sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short) )
1964 					{
1965 #ifdef _DEBUG
1966 						// This assert can be ignored since it could hit from duplicate packets.
1967 						// It's just here for internal testing since it should only happen rarely and will mostly be from bugs
1968 //						assert(remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST);
1969 #endif
1970 						if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
1971 							playerId==myPlayerId) // local system connect
1972 						{
1973 							remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
1974 							PingInternal( playerId, true );
1975 
1976 							RakNet::BitStream inBitStream(data, byteSize, false);
1977 							PlayerID bsPlayerId;
1978 
1979 							inBitStream.IgnoreBits(8);
1980 							inBitStream.Read(bsPlayerId.binaryAddress);
1981 							inBitStream.Read(bsPlayerId.port);
1982 
1983 							// Overwrite the data in the packet
1984 							//					NewIncomingConnectionStruct newIncomingConnectionStruct;
1985 							//					RakNet::BitStream nICS_BS( data, NewIncomingConnectionStruct_Size, false );
1986 							//					newIncomingConnectionStruct.Deserialize( nICS_BS );
1987 							remoteSystem->myExternalPlayerId = bsPlayerId;
1988 
1989 							// Send this info down to the game
1990 							packet = packetPool.GetPointer();
1991 							packet->data = ( unsigned char* ) data;
1992 							packet->length = byteSize;
1993 							packet->bitSize = bitSize;
1994 							packet->playerId = playerId;
1995 							packet->playerIndex = ( PlayerIndex ) remoteSystemIndex;
1996 
1997 #ifdef _DEBUG
1998 							assert( packet->data );
1999 #endif
2000 
2001 							incomingQueueMutex.Lock();
2002 							incomingPacketQueue.push( packet );
2003 							incomingQueueMutex.Unlock();
2004 						}
2005 						else
2006 							delete [] data;
2007 					}
2008 					else if ( (unsigned char) data[ 0 ] == ID_CONNECTED_PONG && byteSize == sizeof(unsigned char)+sizeof(unsigned int)*2 )
2009 					{
2010 						unsigned int sendPingTime, sendPongTime;
2011 
2012 						// Copy into the ping times array the current time - the value returned
2013 						// First extract the sent ping
2014 						RakNet::BitStream inBitStream( data, byteSize, false );
2015 						//PingStruct ps;
2016 						//ps.Deserialize(psBS);
2017 						inBitStream.IgnoreBits(8);
2018 						inBitStream.Read(sendPingTime);
2019 						inBitStream.Read(sendPongTime);
2020 
2021 						time = RakNet::GetTime(); // Update the time value to be accurate
2022 						ping = time - sendPingTime;
2023 						lastPing = remoteSystem->pingTime;
2024 
2025 						// Ignore super high spikes in the average
2026 						if ( lastPing <= 0 || ( ( ( int ) ping < ( lastPing * 3 ) ) && ping < 1200 ) )
2027 						{
2028 							remoteSystem->pingTime = ( short ) ping;
2029 
2030 							if ( remoteSystem->lowestPing == -1 || remoteSystem->lowestPing > ping )
2031 								remoteSystem->lowestPing = ping;
2032 
2033 							// Most packets should arrive by the ping time.
2034 							remoteSystem->reliabilityLayer.SetLostPacketResendDelay( ping * 2 );
2035 						}
2036 
2037 						delete [] data;
2038 					}
2039 					else if ( (unsigned char)data[0] == ID_CONNECTED_PING && byteSize == sizeof(unsigned char)+sizeof(unsigned int) )
2040 					{
2041 						RakNet::BitStream inBitStream( data, byteSize, false );
2042 						inBitStream.IgnoreBits(8);
2043 						unsigned int sendPingTime;
2044 						inBitStream.Read(sendPingTime);
2045 
2046 						if ((unsigned char)(data)[0] == ID_CONNECTED_PING)
2047 						{
2048 							RakNet::BitStream outBitStream;
2049 							outBitStream.Write((unsigned char)ID_CONNECTED_PONG);
2050 							outBitStream.Write(sendPingTime);
2051 							time = RakNet::GetTime();
2052 							outBitStream.Write((unsigned int)time);
2053 							SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, UNRELIABLE, 0, playerId, false, false, time );
2054 						}
2055 
2056 						delete [] data;
2057 					}
2058 					else if ( (unsigned char) data[ 0 ] == ID_DISCONNECTION_NOTIFICATION )
2059 					{
2060 						packet = packetPool.GetPointer();
2061 
2062 						packet->data = ( unsigned char* ) data;
2063 						packet->bitSize = 8;
2064 						packet->length = 1;
2065 
2066 						packet->playerId = playerId;
2067 						packet->playerIndex = ( PlayerIndex ) remoteSystemIndex;
2068 
2069 						// We shouldn't close the connection immediately because we need to ack the ID_DISCONNECTION_NOTIFICATION
2070 						remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
2071 						//CloseConnectionInternal( playerId, false, true );
2072 
2073 #ifdef _DEBUG
2074 						assert( packet->data );
2075 #endif
2076 						// Relay this message to the game
2077 						incomingQueueMutex.Lock();
2078 						incomingPacketQueue.push( packet );
2079 						incomingQueueMutex.Unlock();
2080 
2081 					}
2082 					else if ( (unsigned char)(data)[0] == ID_KEEPALIVE && byteSize == sizeof(unsigned char) )
2083 					{
2084 						// Do nothing
2085 						delete [] data;
2086 					}
2087 					else if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST_ACCEPTED && byteSize == sizeof(unsigned char)+sizeof(unsigned short)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(PlayerIndex) )
2088 					{
2089 						// Make sure this connection accept is from someone we wanted to connect to
2090 						bool allowConnection, alreadyConnected;
2091 
2092 						if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST || remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION || allowConnectionResponseIPMigration)
2093 							allowConnection=true;
2094 						else
2095 							allowConnection=false;
2096 						if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST)
2097 							alreadyConnected=true;
2098 						else
2099 							alreadyConnected=false;
2100 
2101 						if ( allowConnection )
2102 						{
2103 							if (alreadyConnected==false)
2104 							{
2105 								unsigned short remotePort;
2106 								PlayerID externalID;
2107 								PlayerIndex playerIndex;
2108 
2109 								RakNet::BitStream inBitStream(data, byteSize, false);
2110 								inBitStream.IgnoreBits(8); // ID_CONNECTION_REQUEST_ACCEPTED
2111 								inBitStream.Read(remotePort);
2112 								inBitStream.Read(externalID.binaryAddress);
2113 								inBitStream.Read(externalID.port);
2114 								inBitStream.Read(playerIndex);
2115 
2116 								// Find a free remote system struct to use
2117 								//						RakNet::BitStream casBitS(data, byteSize, false);
2118 								//						ConnectionAcceptStruct cas;
2119 								//						cas.Deserialize(casBitS);
2120 								playerId.port = remotePort;
2121 								remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
2122 
2123 								// The remote system told us our external IP, so save it
2124 								remoteSystem->myExternalPlayerId = externalID;
2125 							}
2126 
2127 							// Send the connection request complete to the game
2128 							Packet *packet = packetPool.GetPointer();
2129 
2130 							//packet->data = new unsigned char[ byteSize ];
2131 							//memcpy( packet->data, data, byteSize );
2132 							packet->data=(unsigned char*)data;
2133 
2134 							// packet->data[0]=ID_CONNECTION_REQUEST_ACCEPTED;
2135 							packet->length = byteSize;
2136 							packet->bitSize = byteSize * 8;
2137 							packet->playerId = playerId;
2138 							packet->playerIndex = ( PlayerIndex ) GetIndexFromPlayerID( playerId );
2139 
2140 #ifdef _DEBUG
2141 							assert( packet->data );
2142 #endif
2143 							incomingQueueMutex.Lock();
2144 							incomingPacketQueue.push( packet );
2145 							incomingQueueMutex.Unlock();
2146 
2147 							RakNet::BitStream outBitStream(sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short));
2148 							outBitStream.Write((unsigned char)ID_NEW_INCOMING_CONNECTION);
2149 							outBitStream.Write(playerId.binaryAddress);
2150 							outBitStream.Write(playerId.port);
2151 							SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, false, RakNet::GetTime() );
2152 
2153 							if (alreadyConnected==false)
2154 							{
2155 								PingInternal( playerId, true );
2156 							}
2157 						}
2158 						else
2159 						{
2160 							// Tell the remote system the connection failed
2161 							NotifyAndFlagForDisconnect(playerId, true);
2162 #ifdef _DO_PRINTF
2163 							printf( "Error: Got a connection accept when we didn't request the connection.\n" );
2164 #endif
2165 							delete [] data;
2166 						}
2167 					}
2168 					else
2169 					{
2170 						packet = packetPool.GetPointer();
2171 						packet->data = ( unsigned char* ) data;
2172 						packet->length = byteSize;
2173 						packet->bitSize = bitSize;
2174 						packet->playerId = playerId;
2175 						packet->playerIndex = ( PlayerIndex ) remoteSystemIndex;
2176 
2177 #ifdef _DEBUG
2178 						assert( packet->data );
2179 #endif
2180 						incomingQueueMutex.Lock();
2181 						incomingPacketQueue.push( packet );
2182 						incomingQueueMutex.Unlock();
2183 					}
2184 				}
2185 
2186 				// Does the reliability layer have any more packets waiting for us?
2187 				// To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
2188 				bitSize = remoteSystem->reliabilityLayer.Receive( &data );
2189 			}
2190 		}
2191 	}
2192 
2193 	return true;
2194 }
2195 
2196 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2197 #ifdef _WIN32
UpdateNetworkLoop(LPVOID arguments)2198 unsigned __stdcall UpdateNetworkLoop( LPVOID arguments )
2199 #else
2200 void* UpdateNetworkLoop( void* arguments )
2201 #endif
2202 {
2203 	RakPeer * rakPeer = ( RakPeer * ) arguments;
2204 
2205 	rakPeer->isMainLoopThreadActive = true;
2206 
2207 	while ( rakPeer->endThreads == false )
2208 	{
2209 		rakPeer->RunUpdateCycle();
2210 #ifdef _WIN32
2211 		Sleep( rakPeer->threadSleepTimer );
2212 #else
2213 		usleep( rakPeer->threadSleepTimer * 1000 );
2214 #endif
2215 
2216 	}
2217 
2218 	rakPeer->isMainLoopThreadActive = false;
2219 
2220 	return 0;
2221 }
2222 
2223