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