• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

RakPeer.cpp

Go to the documentation of this file.
00001 // \file
00002 //
00003 // This file is part of RakNet Copyright 2003 Jenkins Software LLC
00004 //
00005 // Usage of RakNet is subject to the appropriate license agreement.
00006 
00007 
00008 #include "RakNetDefines.h"
00009 #include "RakPeer.h"
00010 #include "RakNetTypes.h"
00011 
00012 #ifdef _WIN32
00013 #elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
00014                                
00015 #else
00016 #define closesocket close
00017 #include <unistd.h>
00018 #endif
00019 
00020 #if defined(new)
00021 #pragma push_macro("new")
00022 #undef new
00023 #define RMO_NEW_UNDEF_ALLOCATING_QUEUE
00024 #endif
00025 
00026 
00027 #include <time.h>
00028 
00029 #include <ctype.h> // toupper
00030 #include <string.h>
00031 #include "GetTime.h"
00032 #include "MessageIdentifiers.h"
00033 #include "DS_HuffmanEncodingTree.h"
00034 #include "Rand.h"
00035 #include "PluginInterface2.h"
00036 #include "StringCompressor.h"
00037 #include "StringTable.h"
00038 #include "NetworkIDObject.h"
00039 #include "RakNetTypes.h"
00040 #include "SHA1.h"
00041 #include "RakSleep.h"
00042 #include "RouterInterface.h"
00043 #include "RakAssert.h"
00044 #include "RakNetVersion.h"
00045 #include "NetworkIDManager.h"
00046 #include "DataBlockEncryptor.h"
00047 #include "gettimeofday.h"
00048 #include "SignaledEvent.h"
00049 #include "SuperFastHash.h"
00050 
00051 RAK_THREAD_DECLARATION(UpdateNetworkLoop);
00052 RAK_THREAD_DECLARATION(RecvFromLoop);
00053 RAK_THREAD_DECLARATION(UDTConnect);
00054 
00055 #define REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE 8
00056 
00057 #if !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ )
00058 #include <stdlib.h> // malloc
00059 #endif
00060 
00061 #if defined(_XBOX) || defined(X360)
00062   
00063 #elif defined(_WIN32)
00064 //
00065 #else
00066 /*
00067 #include <alloca.h> // Console 2
00068 #include <stdlib.h>
00069 extern bool _extern_Console2LoadModules(void);
00070 extern int _extern_Console2GetConnectionStatus(void);
00071 extern int _extern_Console2GetLobbyStatus(void);
00072 //extern bool Console2StartupFluff(unsigned int *);
00073 extern void Console2ShutdownFluff(void);
00074 //extern unsigned int Console2ActivateConnection(unsigned int, void *);
00075 //extern bool Console2BlockOnEstablished(void);
00076 extern void Console2GetIPAndPort(unsigned int, char *, unsigned short *, unsigned int );
00077 //extern void Console2DeactivateConnection(unsigned int, unsigned int);
00078 */
00079 #endif
00080 
00081 
00082 static const int NUM_MTU_SIZES=3;
00083 #if defined(_XBOX) || defined(X360)
00084                                                                                    
00085 #elif __PC__
00086 static const int mtuSizes[NUM_MTU_SIZES]={1200, 1200, 576};
00087 #else
00088 static const int mtuSizes[NUM_MTU_SIZES]={MAXIMUM_MTU_SIZE, 1200, 576};
00089 #endif
00090 
00091 
00092 #include "RakAlloca.h"
00093 
00094 // Note to self - if I change this it might affect RECIPIENT_OFFLINE_MESSAGE_INTERVAL in Natpunchthrough.cpp
00095 //static const int MAX_OPEN_CONNECTION_REQUESTS=8;
00096 //static const int TIME_BETWEEN_OPEN_CONNECTION_REQUESTS=500;
00097 
00098 #ifdef _MSC_VER
00099 #pragma warning( push )
00100 #endif
00101 
00102 using namespace RakNet;
00103 
00104 static RakNetRandom rnr;
00105 
00106 struct RakPeerAndIndex
00107 {
00108         SOCKET s;
00109         unsigned short remotePortRakNetWasStartedOn_PS3;
00110         RakPeer *rakPeer;
00111 };
00112 
00113 // On a Little-endian machine the RSA key and message are mangled, but we're
00114 // trying to be friendly to the little endians, so we do byte order
00115 // mangling on Big-Endian machines.  Note that this mangling is independent
00116 // of the byte order used on the network (which also defaults to little-end).
00117 #ifdef HOST_ENDIAN_IS_BIG
00118         void __inline BSWAPCPY(unsigned char *dest, unsigned char *source, int bytesize)
00119         {
00120         #ifdef _DEBUG
00121                 RakAssert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
00122         #endif
00123                 int i;
00124                 for (i=0; i<bytesize; i+=4)
00125                 {
00126                         dest[i] = source[i+3];
00127                         dest[i+1] = source[i+2];
00128                         dest[i+2] = source[i+1];
00129                         dest[i+3] = source[i];
00130                 }
00131         }
00132         void __inline BSWAPSELF(unsigned char *source, int bytesize)
00133         {
00134         #ifdef _DEBUG
00135                 RakAssert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
00136         #endif
00137                 int i;
00138                 unsigned char a, b;
00139                 for (i=0; i<bytesize; i+=4)
00140                 {
00141                         a = source[i];
00142                         b = source[i+1];
00143                         source[i] = source[i+3];
00144                         source[i+1] = source[i+2];
00145                         source[i+2] = b;
00146                         source[i+3] = a;
00147                 }
00148         }
00149 #endif
00150 
00151 static const unsigned int SYN_COOKIE_OLD_RANDOM_NUMBER_DURATION = 10000;
00152 static const unsigned int MAX_OFFLINE_DATA_LENGTH=400; // I set this because I limit ID_CONNECTION_REQUEST to 512 bytes, and the password is appended to that packet.
00153 
00154 // Used to distinguish between offline messages with data, and messages from the reliability layer
00155 // Should be different than any message that could result from messages from the reliability layer
00156 #pragma warning(disable:4309) // 'initializing' : truncation of constant value
00157 // Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false
00158 static const char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78};
00159 
00160 //#define _DO_PRINTF
00161 
00162 // UPDATE_THREAD_POLL_TIME is how often the update thread will poll to see
00163 // if receive wasn't called within UPDATE_THREAD_UPDATE_TIME.  If it wasn't called within that time,
00164 // the updating thread will activate and take over network communication until Receive is called again.
00165 //static const unsigned int UPDATE_THREAD_UPDATE_TIME=30;
00166 //static const unsigned int UPDATE_THREAD_POLL_TIME=30;
00167 
00168 //#define _TEST_AES
00169 
00170 struct PacketFollowedByData
00171 {
00172         Packet p;
00173         unsigned char data[1];
00174 };
00175 
00176 Packet *RakPeer::AllocPacket(unsigned dataSize, const char *file, unsigned int line)
00177 {
00178         // Crashes when dataSize is 4 bytes - not sure why
00179 //      unsigned char *data = (unsigned char *) rakMalloc_Ex(sizeof(PacketFollowedByData)+dataSize, file, line);
00180 //      Packet *p = &((PacketFollowedByData *)data)->p;
00181 //      p->data=((PacketFollowedByData *)data)->data;
00182 //      p->length=dataSize;
00183 //      p->bitSize=BYTES_TO_BITS(dataSize);
00184 //      p->deleteData=false;
00185 //      p->guid=UNASSIGNED_RAKNET_GUID;
00186 //      return p;
00187 
00188         Packet *p;
00189         packetAllocationPoolMutex.Lock();
00190         p = packetAllocationPool.Allocate(file,line);
00191         packetAllocationPoolMutex.Unlock();
00192         p = new ((void*)p) Packet;
00193         p->data=(unsigned char*) rakMalloc_Ex(dataSize,file,line);
00194         p->length=dataSize;
00195         p->bitSize=BYTES_TO_BITS(dataSize);
00196         p->deleteData=true;
00197         p->guid=UNASSIGNED_RAKNET_GUID;
00198         return p;
00199 }
00200 
00201 Packet *RakPeer::AllocPacket(unsigned dataSize, unsigned char *data, const char *file, unsigned int line)
00202 {
00203         // Packet *p = (Packet *)rakMalloc_Ex(sizeof(Packet), file, line);
00204         Packet *p;
00205         packetAllocationPoolMutex.Lock();
00206         p = packetAllocationPool.Allocate(file,line);
00207         packetAllocationPoolMutex.Unlock();
00208         p = new ((void*)p) Packet;
00209         p->data=data;
00210         p->length=dataSize;
00211         p->bitSize=BYTES_TO_BITS(dataSize);
00212         p->deleteData=true;
00213         p->guid=UNASSIGNED_RAKNET_GUID;
00214         return p;
00215 }
00216 
00217 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00218 // Constructor
00219 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00220 RakPeer::RakPeer()
00221 {
00222         StringCompressor::AddReference();
00223         RakNet::StringTable::AddReference();
00224 
00225 #if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
00226         usingSecurity = false;
00227 #endif
00228         memset( frequencyTable, 0, sizeof( unsigned int ) * 256 );
00229         rawBytesSent = rawBytesReceived = compressedBytesSent = compressedBytesReceived = 0;
00230         outputTree = inputTree = 0;
00231         defaultMTUSize = mtuSizes[NUM_MTU_SIZES-1];
00232         trackFrequencyTable = false;
00233         maximumIncomingConnections = 0;
00234         maximumNumberOfPeers = 0;
00235         //remoteSystemListSize=0;
00236         remoteSystemList = 0;
00237         remoteSystemLookup=0;
00238         bytesSentPerSecond = bytesReceivedPerSecond = 0;
00239         endThreads = true;
00240         isMainLoopThreadActive = false;
00241         isRecvFromLoopThreadActive = false;
00242         // isRecvfromThreadActive=false;
00243 #if defined(GET_TIME_SPIKE_LIMIT) && GET_TIME_SPIKE_LIMIT>0
00244         occasionalPing = true;
00245 #else
00246         occasionalPing = false;
00247 #endif
00248         allowInternalRouting=false;
00249         for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
00250                 mySystemAddress[i]=UNASSIGNED_SYSTEM_ADDRESS;
00251         allowConnectionResponseIPMigration = false;
00252         blockOnRPCReply=false;
00253         //incomingPasswordLength=outgoingPasswordLength=0;
00254         incomingPasswordLength=0;
00255         router=0;
00256         splitMessageProgressInterval=0;
00257         //unreliableTimeout=0;
00258         unreliableTimeout=1000;
00259         networkIDManager=0;
00260         maxOutgoingBPS=0;
00261         firstExternalID=UNASSIGNED_SYSTEM_ADDRESS;
00262         myGuid=UNASSIGNED_RAKNET_GUID;
00263         networkIDManager=0;
00264         userUpdateThreadPtr=0;
00265         userUpdateThreadData=0;
00266 
00267 #ifdef _DEBUG
00268         // Wait longer to disconnect in debug so I don't get disconnected while tracing
00269         defaultTimeoutTime=30000;
00270 #else
00271         defaultTimeoutTime=10000;
00272 #endif
00273 
00274 #ifdef _DEBUG
00275         _packetloss=0.0;
00276         _minExtraPing=0;
00277         _extraPingVariance=0;
00278 #endif
00279 
00280 #ifdef _RAKNET_THREADSAFE
00281         bufferedCommands.SetPageSize(sizeof(BufferedCommandStruct)*32);
00282         socketQueryOutput.SetPageSize(sizeof(SocketQueryOutput)*8);
00283         bufferedPackets.SetPageSize(sizeof(RecvFromStruct)*32);
00284 #endif
00285 
00286         packetAllocationPoolMutex.Lock();
00287         packetAllocationPool.SetPageSize(sizeof(DataStructures::MemoryPool<Packet>::MemoryWithPage)*32);
00288         packetAllocationPoolMutex.Unlock();
00289 
00290         remoteSystemIndexPool.SetPageSize(sizeof(DataStructures::MemoryPool<RemoteSystemIndex>::MemoryWithPage)*32);
00291 
00292         GenerateGUID();
00293 
00294         quitAndDataEvents.InitEvent();
00295         limitConnectionFrequencyFromTheSameIP=false;
00296         ResetSendReceipt();
00297 }
00298 
00299 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00300 // Destructor
00301 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00302 RakPeer::~RakPeer()
00303 {
00304 //      unsigned i;
00305 
00306 
00307         Shutdown( 0, 0 );
00308 
00309         // Free the ban list.
00310         ClearBanList();
00311 
00312         StringCompressor::RemoveReference();
00313         RakNet::StringTable::RemoveReference();
00314 
00315         quitAndDataEvents.CloseEvent();
00316 }
00317 
00318 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00319 // \brief Starts the network threads, opens the listen port.
00320 // You must call this before calling Connect().
00321 // Multiple calls while already active are ignored.  To call this function again with different settings, you must first call Shutdown().
00322 // \note Call SetMaximumIncomingConnections if you want to accept incoming connections
00323 // \note Set _RAKNET_THREADSAFE in RakNetDefines.h if you want to call RakNet functions from multiple threads (not recommended, as it is much slower and RakNet is already asynchronous).
00324 // \param[in] maxConnections The maximum number of connections between this instance of RakPeer and another instance of RakPeer. Required so the network can preallocate and for thread safety. A pure client would set this to 1.  A pure server would set it to the number of allowed clients.- A hybrid would set it to the sum of both types of connections
00325 // \param[in] localPort The port to listen for connections on.
00326 // \param[in] _threadSleepTimer How many ms to Sleep each internal update cycle. With new congestion control, the best results will be obtained by passing 10.
00327 // \param[in] socketDescriptors An array of SocketDescriptor structures to force RakNet to listen on a particular IP address or port (or both).  Each SocketDescriptor will represent one unique socket.  Do not pass redundant structures.  To listen on a specific port, you can pass &socketDescriptor, 1SocketDescriptor(myPort,0); such as for a server.  For a client, it is usually OK to just pass SocketDescriptor();
00328 // \param[in] socketDescriptorCount The size of the \a socketDescriptors array.  Pass 1 if you are not sure what to pass.
00329 // \return False on failure (can't create socket or thread), true on success.
00330 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00331 bool RakPeer::Startup( unsigned short maxConnections, int _threadSleepTimer, SocketDescriptor *socketDescriptors, unsigned socketDescriptorCount, int threadPriority )
00332 {
00333         if (IsActive())
00334                 return false;
00335 
00336         if (threadPriority==-99999)
00337         {
00338 #if defined(_XBOX) || defined(X360)
00339                    
00340 #elif defined(_WIN32)
00341                 threadPriority=0;
00342 #elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
00343                       
00344 #else
00345                 threadPriority=1000;
00346 #endif
00347         }
00348 
00349         // Fill out ipList structure
00350 #if !defined(_XBOX) && !defined(X360)
00351         memset( ipList, 0, sizeof( char ) * 16 * MAXIMUM_NUMBER_OF_INTERNAL_IDS );
00352         SocketLayer::Instance()->GetMyIP( ipList,binaryAddresses );
00353 #endif
00354 
00355         unsigned int i;
00356         if (myGuid==UNASSIGNED_RAKNET_GUID)
00357         {
00358                 seedMT( GenerateSeedFromGuid() );
00359         }
00360 
00361         rnr.SeedMT( GenerateSeedFromGuid() );
00362 
00363         RakPeerAndIndex rpai[32];
00364         RakAssert(socketDescriptorCount<32);
00365 
00366         RakAssert(socketDescriptors && socketDescriptorCount>=1);
00367 
00368         if (socketDescriptors==0 || socketDescriptorCount<1)
00369                 return false;
00370 
00371         //unsigned short localPort;
00372         //localPort=socketDescriptors[0].port;
00373 
00374         RakAssert( maxConnections > 0 );
00375 
00376         if ( maxConnections <= 0 )
00377                 return false;
00378 
00379         DerefAllSockets();
00380 
00381 
00382         // Go through all socket descriptors and precreate sockets on the specified addresses
00383         for (i=0; i<socketDescriptorCount; i++)
00384         {
00385                 if (socketDescriptors[i].port!=0 && SocketLayer::Instance()->IsPortInUse(socketDescriptors[i].port, socketDescriptors[i].hostAddress)==true)
00386                 {
00387                         DerefAllSockets();
00388                         return false;
00389                 }
00390 
00391                 RakNetSmartPtr<RakNetSocket> rns(RakNet::OP_NEW<RakNetSocket>(__FILE__,__LINE__));
00392                 if (socketDescriptors[i].remotePortRakNetWasStartedOn_PS3==0)
00393                         rns->s = (unsigned int) SocketLayer::Instance()->CreateBoundSocket( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress, 100 );
00394                 else // if (socketDescriptors[i].socketType==SocketDescriptor::PS3_LOBBY_UDP)
00395                         rns->s = (unsigned int) SocketLayer::Instance()->CreateBoundSocket_PS3Lobby( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress );
00396 
00397                 if ((SOCKET)rns->s==(SOCKET)-1)
00398                 {
00399                         DerefAllSockets();
00400                         return false;
00401                 }
00402 
00403 
00404                 rns->boundAddress=SocketLayer::GetSystemAddress( rns->s );
00405                 rns->remotePortRakNetWasStartedOn_PS3=socketDescriptors[i].remotePortRakNetWasStartedOn_PS3;
00406                 rns->userConnectionSocketIndex=i;
00407 
00408                 // Test the socket
00409                 int zero=0;
00410                 if (SocketLayer::Instance()->SendTo((SOCKET)rns->s, (const char*) &zero,4,"127.0.0.1", rns->boundAddress.port, rns->remotePortRakNetWasStartedOn_PS3)!=0)
00411                 {
00412                         DerefAllSockets();
00413                         return false;
00414                 }
00415 
00416                 socketList.Push(rns, __FILE__, __LINE__ );
00417 
00418                 /*
00419 #if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
00420                 if (_threadSleepTimer>0)
00421                 {
00422                         rns->recvEvent=CreateEvent(0,FALSE,FALSE,0);
00423                         WSAEventSelect(rns->s,rns->recvEvent,FD_READ);
00424                 }
00425 #endif
00426                 */
00427         }
00428 
00429         // 05/05/09 - Updated to dynamically bind sockets on IP addresses, so we always reply on the same address we recieved from
00430         /*
00431 
00432         for (i=0; i<connectionSocketsLength; i++)
00433         {
00434                 if (connectionSockets[i].haveRakNetCloseSocket && connectionSockets[i].s != (SOCKET) -1)
00435                         closesocket(connectionSockets[i].s);
00436         }
00437         if (connectionSockets)
00438         {
00439                 RakNet::OP_DELETE_ARRAY(connectionSockets, __FILE__, __LINE__);
00440         }
00441         connectionSocketsLength=0;
00442 
00443         connectionSockets=RakNet::OP_NEW_ARRAY<RakNetSocket>(socketDescriptorCount, __FILE__, __LINE__ );
00444         for (i=0; i<socketDescriptorCount; i++)
00445         {
00446                 if (socketDescriptors[i].socketType==SocketDescriptor::NONE)
00447                         connectionSockets[i].s = (SOCKET) -1;
00448                 else if (socketDescriptors[i].remotePortRakNetWasStartedOn_PS3==0)
00449                         connectionSockets[i].s = SocketLayer::Instance()->CreateBoundSocket( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress );
00450                 else if (socketDescriptors[i].socketType==SocketDescriptor::PS3_LOBBY_UDP)
00451                         connectionSockets[i].s = SocketLayer::Instance()->CreateBoundSocket_PS3Lobby( socketDescriptors[i].port, true, socketDescriptors[i].hostAddress );
00452                 connectionSockets[i].haveRakNetCloseSocket=true;
00453                 connectionSockets[i].socketType=socketDescriptors[i].socketType;
00454 
00455                 if (connectionSockets[i].s==(SOCKET)-1 && socketDescriptors[i].socketType!=SocketDescriptor::NONE)
00456                 {
00457                         unsigned int j;
00458                         for (j=0; j < i; j++)
00459                         {
00460                                 if (connectionSockets[j].haveRakNetCloseSocket)
00461                                         closesocket(connectionSockets[j].s);
00462                         }
00463                         if (connectionSockets)
00464                         {
00465                                 RakNet::OP_DELETE_ARRAY(connectionSockets, __FILE__, __LINE__);
00466                         }
00467                         connectionSocketsLength=0;
00468                         connectionSockets=0;
00469                         return false;
00470                 }
00471         }
00472 
00473         connectionSocketsLength=socketDescriptorCount;
00474 
00475 #if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
00476         if (_threadSleepTimer>0)
00477         {
00478                 recvEvent=CreateEvent(0,FALSE,FALSE,0);
00479                 for (i=0; i<socketDescriptorCount; i++)
00480                 {
00481                         if (socketDescriptors[i].socketType!=SocketDescriptor::NONE)
00482                                 WSAEventSelect(connectionSockets[i].s,recvEvent,FD_READ);
00483                 }
00484         }
00485         #endif
00486 */
00487 
00488         if ( maximumNumberOfPeers == 0 )
00489         {
00490                 // Don't allow more incoming connections than we have peers.
00491                 if ( maximumIncomingConnections > maxConnections )
00492                         maximumIncomingConnections = maxConnections;
00493 
00494                 maximumNumberOfPeers = maxConnections;
00495                 // 04/19/2006 - Don't overallocate because I'm no longer allowing connected pings.
00496                 // The disconnects are not consistently processed and the process was sloppy and complicated.
00497                 // Allocate 10% extra to handle new connections from players trying to connect when the server is full
00498                 //remoteSystemListSize = maxConnections;// * 11 / 10 + 1;
00499 
00500                 // remoteSystemList in Single thread
00501                 //remoteSystemList = RakNet::OP_NEW<RemoteSystemStruct[ remoteSystemListSize ]>( __FILE__, __LINE__ );
00502                 remoteSystemList = RakNet::OP_NEW_ARRAY<RemoteSystemStruct>(maximumNumberOfPeers, __FILE__, __LINE__ );
00503 
00504                 remoteSystemLookup = RakNet::OP_NEW_ARRAY<RemoteSystemIndex*>((unsigned int) maximumNumberOfPeers * REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE, __FILE__, __LINE__ );
00505 
00506                 for ( i = 0; i < maximumNumberOfPeers; i++ )
00507                 //for ( i = 0; i < remoteSystemListSize; i++ )
00508                 {
00509                         // remoteSystemList in Single thread
00510                         remoteSystemList[ i ].isActive = false;
00511                         remoteSystemList[ i ].systemAddress = UNASSIGNED_SYSTEM_ADDRESS;
00512                         remoteSystemList[ i ].guid = UNASSIGNED_RAKNET_GUID;
00513                         remoteSystemList[ i ].myExternalSystemAddress = UNASSIGNED_SYSTEM_ADDRESS;
00514                         remoteSystemList[ i ].connectMode=RemoteSystemStruct::NO_ACTION;
00515                         remoteSystemList[ i ].MTUSize = defaultMTUSize;
00516                         #ifdef _DEBUG
00517                         remoteSystemList[ i ].reliabilityLayer.ApplyNetworkSimulator(_packetloss, _minExtraPing, _extraPingVariance);
00518                         #endif
00519                 }
00520 
00521                 for (unsigned int i=0; i < (unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE; i++)
00522                 {
00523                         remoteSystemLookup[i]=0;
00524                 }
00525         }
00526 
00527         // For histogram statistics
00528         // nextReadBytesTime=0;
00529         // lastSentBytes=lastReceivedBytes=0;
00530 
00531         if ( endThreads )
00532         {
00533         //      lastUserUpdateCycle = 0;
00534 
00535                 // Reset the frequency table that we use to save outgoing data
00536                 memset( frequencyTable, 0, sizeof( unsigned int ) * 256 );
00537 
00538                 // Reset the statistical data
00539                 rawBytesSent = rawBytesReceived = compressedBytesSent = compressedBytesReceived = 0;
00540 
00541                 updateCycleIsRunning = false;
00542                 endThreads = false;
00543                 // Create the threads
00544                 threadSleepTimer = _threadSleepTimer;
00545 
00546                 ClearBufferedCommands();
00547                 ClearBufferedPackets();
00548                 ClearSocketQueryOutput();
00549 
00550 
00551                 for (int ipIndex=0; ipIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipIndex++)
00552                 {
00553 #if !defined(_XBOX) && !defined(X360)
00554                         if (ipList[ipIndex][0])
00555                         {
00556                                 mySystemAddress[ipIndex].port = SocketLayer::Instance()->GetLocalPort(socketList[0]->s);
00557 //                              if (socketDescriptors[0].hostAddress==0 || socketDescriptors[0].hostAddress[0]==0)
00558                                 mySystemAddress[ipIndex].binaryAddress = inet_addr( ipList[ ipIndex ] );
00559                                 //                      else
00560                                 //                              mySystemAddress[ipIndex].binaryAddress = inet_addr( socketDescriptors[0].hostAddress );
00561                         }
00562                         else
00563                                 mySystemAddress[ipIndex]=UNASSIGNED_SYSTEM_ADDRESS;
00564 #else
00565                         mySystemAddress[ipIndex]=UNASSIGNED_SYSTEM_ADDRESS;
00566 #endif
00567                 }
00568 
00569                 if ( isMainLoopThreadActive == false )
00570                 {
00571 
00572                         int errorCode = RakNet::RakThread::Create(UpdateNetworkLoop, this, threadPriority);
00573 
00574                         if ( errorCode != 0 )
00575                         {
00576                                 Shutdown( 0, 0 );
00577                                 return false;
00578                         }
00579 
00580                         for (i=0; i<socketDescriptorCount; i++)
00581                         {
00582                                 rpai[i].remotePortRakNetWasStartedOn_PS3=socketDescriptors[i].remotePortRakNetWasStartedOn_PS3;
00583                                 rpai[i].s=socketList[i]->s;
00584                                 rpai[i].rakPeer=this;
00585                                 isRecvFromLoopThreadActive=false;
00586                                 errorCode = RakNet::RakThread::Create(RecvFromLoop, &rpai[i], threadPriority);
00587 
00588                                 if ( errorCode != 0 )
00589                                 {
00590                                         Shutdown( 0, 0 );
00591                                         return false;
00592                                 }
00593 
00594                                 while (  isRecvFromLoopThreadActive == false )
00595                                         RakSleep(10);
00596                         }
00597 
00598                 }
00599 
00600                 // Wait for the threads to activate.  When they are active they will set these variables to true
00601 
00602                 while (  isMainLoopThreadActive == false )
00603                         RakSleep(10);
00604 
00605         }
00606 
00607         for (i=0; i < messageHandlerList.Size(); i++)
00608         {
00609                 messageHandlerList[i]->OnRakPeerStartup();
00610         }
00611 
00612 #ifdef USE_THREADED_SEND
00613         SendToThread::AddRef();
00614 #endif
00615 
00616         return true;
00617 }
00618 
00619 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00620 // Description:
00621 // Must be called while offline
00622 // Secures connections though a combination of SHA1, AES128, SYN Cookies, and RSA to prevent
00623 // connection spoofing, replay attacks, data eavesdropping, packet tampering, and MitM attacks.
00624 // There is a significant amount of processing and a slight amount of bandwidth
00625 // overhead for this feature.
00626 //
00627 // If you accept connections, you must call this or else secure connections will not be enabled
00628 // for incoming connections.
00629 // If you are connecting to another system, you can call this with values for the
00630 // (e and p,q) public keys before connecting to prevent MitM
00631 //
00632 // Parameters:
00633 // pubKeyE, pubKeyN - A pointer to the public keys from the RSACrypt class. See the Encryption sample
00634 // privKeyP, privKeyQ - Private keys generated from the RSACrypt class.  See the Encryption sample
00635 // If the private keys are 0, then a new key will be generated when this function is called
00636 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00637 void RakPeer::InitializeSecurity(const char *pubKeyE, const char *pubKeyN, const char *privKeyP, const char *privKeyQ )
00638 {
00639 #if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
00640         if ( endThreads == false )
00641                 return ;
00642 
00643         // Setting the client key is e,n,
00644         // Setting the server key is p,q
00645         if ( //( privKeyP && privKeyQ && ( pubKeyE || pubKeyN ) ) ||
00646                 //( pubKeyE && pubKeyN && ( privKeyP || privKeyQ ) ) ||
00647                 ( privKeyP && privKeyQ == 0 ) ||
00648                 ( privKeyQ && privKeyP == 0 ) ||
00649                 ( pubKeyE && pubKeyN == 0 ) ||
00650                 ( pubKeyN && pubKeyE == 0 ) )
00651         {
00652                 // Invalid parameters
00653                 RakAssert( 0 );
00654         }
00655 
00656         GenerateSYNCookieRandomNumber();
00657 
00658         usingSecurity = true;
00659 
00660         if ( privKeyP == 0 && privKeyQ == 0 && pubKeyE == 0 && pubKeyN == 0 )
00661         {
00662                 keysLocallyGenerated = true;
00663                 //rsacrypt.generateKeys();
00664                 rsacrypt.generatePrivateKey(RAKNET_RSA_FACTOR_LIMBS);
00665         }
00666 
00667         else
00668         {
00669                 if ( pubKeyE && pubKeyN )
00670                 {
00671                         // Save public keys
00672                         memcpy( ( char* ) & publicKeyE, pubKeyE, sizeof( publicKeyE ) );
00673                         memcpy( publicKeyN, pubKeyN, sizeof( publicKeyN ) );
00674                 }
00675 
00676                 if ( privKeyP && privKeyQ )
00677                 {
00678                         bool b = rsacrypt.setPrivateKey( (const uint32_t*) privKeyP, (const uint32_t*) privKeyQ, RAKNET_RSA_FACTOR_LIMBS/2);
00679                         (void) b;
00680                         RakAssert(b);
00681                 //      BIGHALFSIZE( RSA_BIT_SIZE, p );
00682                 //      BIGHALFSIZE( RSA_BIT_SIZE, q );
00683 
00684 //                      memcpy( p, privKeyP, sizeof( p ) );
00685 //                      memcpy( q, privKeyQ, sizeof( q ) );
00686                         // Save private keys
00687 //                      rsacrypt.setPrivateKey( p, q );
00688                 }
00689 
00690                 keysLocallyGenerated = false;
00691         }
00692 #endif
00693 }
00694 
00695 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00696 // Description
00697 // Must be called while offline
00698 // Disables all security.
00699 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00700 void RakPeer::DisableSecurity( void )
00701 {
00702 #if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
00703         if ( endThreads == false )
00704                 return ;
00705 
00706         usingSecurity = false;
00707 #endif
00708 }
00709 
00710 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00711 void RakPeer::AddToSecurityExceptionList(const char *ip)
00712 {
00713         securityExceptionMutex.Lock();
00714         securityExceptionList.Insert(RakString(ip), __FILE__, __LINE__);
00715         securityExceptionMutex.Unlock();
00716 }
00717 
00718 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00719 void RakPeer::RemoveFromSecurityExceptionList(const char *ip)
00720 {
00721         if (securityExceptionList.Size()==0)
00722                 return;
00723 
00724         if (ip==0)
00725         {
00726                 securityExceptionMutex.Lock();
00727                 securityExceptionList.Clear(false, __FILE__, __LINE__);
00728                 securityExceptionMutex.Unlock();
00729         }
00730         else
00731         {
00732                 unsigned i=0;
00733                 securityExceptionMutex.Lock();
00734                 while (i < securityExceptionList.Size())
00735                 {
00736                         if (securityExceptionList[i].IPAddressMatch(ip))
00737                         {
00738                                 securityExceptionList[i]=securityExceptionList[securityExceptionList.Size()-1];
00739                                 securityExceptionList.RemoveAtIndex(securityExceptionList.Size()-1);
00740                         }
00741                         else
00742                                 i++;
00743                 }
00744                 securityExceptionMutex.Unlock();
00745         }
00746 }
00747 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00748 bool RakPeer::IsInSecurityExceptionList(const char *ip)
00749 {
00750         if (securityExceptionList.Size()==0)
00751                 return false;
00752 
00753         unsigned i=0;
00754         securityExceptionMutex.Lock();
00755         for (; i < securityExceptionList.Size(); i++)
00756         {
00757                 if (securityExceptionList[i].IPAddressMatch(ip))
00758                 {
00759                         securityExceptionMutex.Unlock();
00760                         return true;
00761                 }
00762         }
00763         securityExceptionMutex.Unlock();
00764         return false;
00765 }
00766 
00767 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00768 // Description:
00769 // Sets how many incoming connections are allowed.  If this is less than the number of players currently connected, no
00770 // more players will be allowed to connect.  If this is greater than the maximum number of peers allowed, it will be reduced
00771 // to the maximum number of peers allowed.  Defaults to 0.
00772 //
00773 // Parameters:
00774 // numberAllowed - Maximum number of incoming connections allowed.
00775 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00776 void RakPeer::SetMaximumIncomingConnections( unsigned short numberAllowed )
00777 {
00778         maximumIncomingConnections = numberAllowed;
00779 }
00780 
00781 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00782 // Description:
00783 // Returns the maximum number of incoming connections, which is always <= maxConnections
00784 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00785 unsigned short RakPeer::GetMaximumIncomingConnections( void ) const
00786 {
00787         return maximumIncomingConnections;
00788 }
00789 
00790 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00791 // Returns how many open connections there are at this time
00792 // \return the number of open connections
00793 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00794 unsigned short RakPeer::NumberOfConnections(void) const
00795 {
00796         unsigned short i, count=0;
00797         for (i=0; i < maximumNumberOfPeers; i++)
00798                 if (remoteSystemList[i].isActive)
00799                         count++;
00800         return count;
00801 }
00802 
00803 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00804 // Description:
00805 // Sets the password incoming connections must match in the call to Connect (defaults to none)
00806 // Pass 0 to passwordData to specify no password
00807 //
00808 // Parameters:
00809 // passwordData: A data block that incoming connections must match.  This can be just a password, or can be a stream of data.
00810 // - Specify 0 for no password data
00811 // passwordDataLength: The length in bytes of passwordData
00812 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00813 void RakPeer::SetIncomingPassword( const char* passwordData, int passwordDataLength )
00814 {
00815         //if (passwordDataLength > MAX_OFFLINE_DATA_LENGTH)
00816         //      passwordDataLength=MAX_OFFLINE_DATA_LENGTH;
00817 
00818         if (passwordDataLength > 255)
00819                 passwordDataLength=255;
00820 
00821         if (passwordData==0)
00822                 passwordDataLength=0;
00823 
00824         // Not threadsafe but it's not important enough to lock.  Who is going to change the password a lot during runtime?
00825         // It won't overflow at least because incomingPasswordLength is an unsigned char
00826         if (passwordDataLength>0)
00827                 memcpy(incomingPassword, passwordData, passwordDataLength);
00828         incomingPasswordLength=(unsigned char)passwordDataLength;
00829 }
00830 
00831 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00832 void RakPeer::GetIncomingPassword( char* passwordData, int *passwordDataLength  )
00833 {
00834         if (passwordData==0)
00835         {
00836                 *passwordDataLength=incomingPasswordLength;
00837                 return;
00838         }
00839 
00840         if (*passwordDataLength > incomingPasswordLength)
00841                 *passwordDataLength=incomingPasswordLength;
00842 
00843         if (*passwordDataLength>0)
00844                 memcpy(passwordData, incomingPassword, *passwordDataLength);
00845 }
00846 
00847 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00848 // Description:
00849 // Call this to connect to the specified host (ip or domain name) and server port.
00850 // Calling Connect and not calling SetMaximumIncomingConnections acts as a dedicated client.  Calling both acts as a true peer.
00851 // This is a non-blocking connection.  You know the connection is successful when IsConnected() returns true
00852 // or receive gets a packet with the type identifier ID_CONNECTION_ACCEPTED.  If the connection is not
00853 // successful, such as rejected connection or no response then neither of these things will happen.
00854 // Requires that you first call Initialize
00855 //
00856 // Parameters:
00857 // host: Either a dotted IP address or a domain name
00858 // remotePort: Which port to connect to on the remote machine.
00859 // 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
00860 // passwordDataLength: The length in bytes of passwordData
00861 //
00862 // Returns:
00863 // True on successful initiation. False on incorrect parameters, internal error, or too many existing peers
00864 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00865 bool RakPeer::Connect( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, unsigned connectionSocketIndex, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime )
00866 {
00867         // If endThreads is true here you didn't call Startup() first.
00868         if ( host == 0 || endThreads || connectionSocketIndex>=socketList.Size() )
00869                 return false;
00870 
00871         connectionSocketIndex=GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
00872 
00873         if (passwordDataLength>255)
00874                 passwordDataLength=255;
00875 
00876         if (passwordData==0)
00877                 passwordDataLength=0;
00878 
00879         // Not threadsafe but it's not important enough to lock.  Who is going to change the password a lot during runtime?
00880         // It won't overflow at least because outgoingPasswordLength is an unsigned char
00881 //      if (passwordDataLength>0)
00882 //              memcpy(outgoingPassword, passwordData, passwordDataLength);
00883 //      outgoingPasswordLength=(unsigned char) passwordDataLength;
00884 
00885         if ( NonNumericHostString( host ) )
00886         {
00887                 host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host );
00888 
00889                 if (host==0)
00890                         return false;
00891         }
00892 
00893         // 04/02/09 - Can't remember why I disabled connecting to self, but it seems to work
00894         // Connecting to ourselves in the same instance of the program?
00895 //      if ( ( strcmp( host, "127.0.0.1" ) == 0 || strcmp( host, "0.0.0.0" ) == 0 ) && remotePort == mySystemAddress[0].port )
00896 //              return false;
00897 
00898         return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, connectionSocketIndex, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime);
00899 }
00900 
00901 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00902 
00903 bool RakPeer::ConnectWithSocket(const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, RakNetSmartPtr<RakNetSocket> socket, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime)
00904 {
00905         if ( host == 0 || endThreads || socket.IsNull() )
00906                 return false;
00907 
00908         if (passwordDataLength>255)
00909                 passwordDataLength=255;
00910 
00911         if (passwordData==0)
00912                 passwordDataLength=0;
00913 
00914                 if ( NonNumericHostString( host ) )
00915         {
00916                 host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host );
00917 
00918                 if (host==0)
00919                         return false;
00920         }
00921 
00922                 return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, 0, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime, socket );
00923 
00924 }
00925 
00926 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00927 // Description:
00928 // Stops the network threads and close all connections.  Multiple calls are ok.
00929 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00930 void RakPeer::Shutdown( unsigned int blockDuration, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
00931 {
00932         unsigned i,j;
00933         bool anyActive;
00934         RakNetTime startWaitingTime;
00935 //      SystemAddress systemAddress;
00936         RakNetTime time;
00937         //unsigned short systemListSize = remoteSystemListSize; // This is done for threading reasons
00938         unsigned short systemListSize = maximumNumberOfPeers;
00939 
00940         if ( blockDuration > 0 )
00941         {
00942                 for ( i = 0; i < systemListSize; i++ )
00943                 {
00944                         // remoteSystemList in user thread
00945                         if (remoteSystemList[i].isActive)
00946                                 NotifyAndFlagForShutdown(remoteSystemList[i].systemAddress, false, orderingChannel, disconnectionNotificationPriority);
00947                 }
00948 
00949                 time = RakNet::GetTime();
00950                 startWaitingTime = time;
00951                 while ( time - startWaitingTime < blockDuration )
00952                 {
00953                         anyActive=false;
00954                         for (j=0; j < systemListSize; j++)
00955                         {
00956                                 // remoteSystemList in user thread
00957                                 if (remoteSystemList[j].isActive)
00958                                 {
00959                                         anyActive=true;
00960                                         break;
00961                                 }
00962                         }
00963 
00964                         // If this system is out of packets to send, then stop waiting
00965                         if ( anyActive==false )
00966                                 break;
00967 
00968                         // This will probably cause the update thread to run which will probably
00969                         // send the disconnection notification
00970 
00971                         RakSleep(15);
00972                         time = RakNet::GetTime();
00973                 }
00974         }
00975 
00976         for (i=0; i < messageHandlerList.Size(); i++)
00977         {
00978                 messageHandlerList[i]->OnRakPeerShutdown();
00979         }
00980 
00981         quitAndDataEvents.SetEvent();
00982 
00983         endThreads = true;
00984         // Get recvfrom to unblock
00985         for (i=0; i < socketList.Size(); i++)
00986         {
00987                 if (SocketLayer::Instance()->SendTo(socketList[i]->s, (const char*) &i,1,"127.0.0.1", socketList[i]->boundAddress.port, socketList[i]->remotePortRakNetWasStartedOn_PS3)!=0)
00988                         break;
00989         }
00990         while ( isMainLoopThreadActive )
00991         {
00992                 endThreads = true;
00993                 RakSleep(15);
00994         }
00995 
00996 //      char c=0;
00997 //      unsigned int socketIndex;
00998         // remoteSystemList in Single thread
00999         for ( i = 0; i < systemListSize; i++ )
01000         {
01001                 // Reserve this reliability layer for ourselves
01002                 remoteSystemList[ i ].isActive = false;
01003 
01004                 // Remove any remaining packets
01005                 remoteSystemList[ i ].reliabilityLayer.Reset(false, remoteSystemList[ i ].MTUSize);
01006 
01007                 remoteSystemList[ i ].rakNetSocket.SetNull();
01008         }
01009 
01010 
01011         // Setting maximumNumberOfPeers to 0 allows remoteSystemList to be reallocated in Initialize.
01012         // Setting remoteSystemListSize prevents threads from accessing the reliability layer
01013         maximumNumberOfPeers = 0;
01014         //remoteSystemListSize = 0;
01015 
01016         // Free any packets the user didn't deallocate
01017         packetReturnMutex.Lock();
01018         for (unsigned int i=0; i < packetReturnQueue.Size(); i++)
01019                 DeallocatePacket(packetReturnQueue[i]);
01020         packetReturnQueue.Clear(__FILE__,__LINE__);
01021         packetReturnMutex.Unlock();
01022         packetAllocationPoolMutex.Lock();
01023         packetAllocationPool.Clear(__FILE__,__LINE__);
01024         packetAllocationPoolMutex.Unlock();
01025 
01026         blockOnRPCReply=false;
01027 
01028         RakNetTimeMS timeout = RakNet::GetTimeMS()+1000;
01029         while ( isRecvFromLoopThreadActive && RakNet::GetTimeMS()<timeout )
01030         {
01031                 // Get recvfrom to unblock
01032                 for (i=0; i < socketList.Size(); i++)
01033                 {
01034                         SocketLayer::Instance()->SendTo(socketList[i]->s, (const char*) &i,1,"127.0.0.1", socketList[i]->boundAddress.port, socketList[i]->remotePortRakNetWasStartedOn_PS3);
01035                 }
01036 
01037                 RakSleep(30);
01038         }
01039 
01040         if (isRecvFromLoopThreadActive)
01041         {
01042                 timeout = RakNet::GetTimeMS()+1000;
01043                 while ( isRecvFromLoopThreadActive && RakNet::GetTimeMS()<timeout )
01044                 {
01045                         RakSleep(30);
01046                 }
01047         }
01048 
01049         DerefAllSockets();
01050 
01051         ClearBufferedCommands();
01052         ClearBufferedPackets();
01053         ClearSocketQueryOutput();
01054         bytesSentPerSecond = bytesReceivedPerSecond = 0;
01055 
01056         ClearRequestedConnectionList();
01057 
01058 
01059         // Clear out the reliability layer list in case we want to reallocate it in a successive call to Init.
01060         RemoteSystemStruct * temp = remoteSystemList;
01061         remoteSystemList = 0;
01062         RakNet::OP_DELETE_ARRAY(temp, __FILE__, __LINE__);
01063 
01064         ClearRemoteSystemLookup();
01065 
01066 #ifdef USE_THREADED_SEND
01067         SendToThread::Deref();
01068 #endif
01069 
01070         ResetSendReceipt();
01071 }
01072 
01073 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01074 // Description:
01075 // Returns true if the network threads are running
01076 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01077 inline bool RakPeer::IsActive( void ) const
01078 {
01079         return endThreads == false;
01080 }
01081 
01082 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01083 // Description:
01084 // Fills the array remoteSystems with the systemAddress of all the systems we are connected to
01085 //
01086 // Parameters:
01087 // remoteSystems (out): An array of SystemAddress structures to be filled with the SystemAddresss of the systems we are connected to
01088 // - pass 0 to remoteSystems to only get the number of systems we are connected to
01089 // numberOfSystems (int, out): As input, the size of remoteSystems array.  As output, the number of elements put into the array
01090 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01091 bool RakPeer::GetConnectionList( SystemAddress *remoteSystems, unsigned short *numberOfSystems ) const
01092 {
01093         int count, index;
01094         count=0;
01095 
01096         if ( remoteSystemList == 0 || endThreads == true )
01097         {
01098                 *numberOfSystems = 0;
01099                 return false;
01100         }
01101 
01102         // This is called a lot so I unrolled the loop
01103         if ( remoteSystems )
01104         {
01105                 // remoteSystemList in user thread
01106                 //for ( count = 0, index = 0; index < remoteSystemListSize; ++index )
01107                 for ( count = 0, index = 0; index < maximumNumberOfPeers; ++index )
01108                         if ( remoteSystemList[ index ].isActive && remoteSystemList[ index ].connectMode==RemoteSystemStruct::CONNECTED)
01109                         {
01110                                 if ( count < *numberOfSystems )
01111                                         remoteSystems[ count ] = remoteSystemList[ index ].systemAddress;
01112 
01113                                 ++count;
01114                         }
01115         }
01116         else
01117         {
01118                 // remoteSystemList in user thread
01119                 //for ( count = 0, index = 0; index < remoteSystemListSize; ++index )
01120                 for ( count = 0, index = 0; index < maximumNumberOfPeers; ++index )
01121                         if ( remoteSystemList[ index ].isActive && remoteSystemList[ index ].connectMode==RemoteSystemStruct::CONNECTED)
01122                                 ++count;
01123         }
01124 
01125         *numberOfSystems = ( unsigned short ) count;
01126 
01127         return true;
01128 }
01129 
01130 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01131 uint32_t RakPeer::GetNextSendReceipt(void)
01132 {
01133         sendReceiptSerialMutex.Lock();
01134         uint32_t retVal = sendReceiptSerial;
01135         sendReceiptSerialMutex.Unlock();
01136         return retVal;
01137 }
01138 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01139 uint32_t RakPeer::IncrementNextSendReceipt(void)
01140 {
01141         sendReceiptSerialMutex.Lock();
01142         uint32_t returned = sendReceiptSerial;
01143         if (++sendReceiptSerial==0)
01144                 sendReceiptSerial=1;
01145         sendReceiptSerialMutex.Unlock();
01146         return returned;
01147 }
01148 
01149 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01150 // Description:
01151 // Sends a block of data to the specified system that you are connected to.
01152 // This function only works while the client is connected (Use the Connect function).
01153 // The first byte should be a message identifier starting at ID_USER_PACKET_ENUM
01154 //
01155 // Parameters:
01156 // data: The block of data to send
01157 // length: The size in bytes of the data to send
01158 // bitStream: The bitstream to send
01159 // priority: What priority level to send on.
01160 // reliability: How reliability to send this data
01161 // orderingChannel: When using ordered or sequenced packets, what channel to order these on.
01162 // - Packets are only ordered relative to other packets on the same stream
01163 // systemAddress: Who to send this packet to, or in the case of broadcasting who not to send it to. Use UNASSIGNED_SYSTEM_ADDRESS to specify none
01164 // broadcast: True to send this packet to all connected systems.  If true, then systemAddress specifies who not to send the packet to.
01165 // Returns:
01166 // \return 0 on bad input. Otherwise a number that identifies this message. If \a reliability is a type that returns a receipt, on a later call to Receive() you will get ID_SND_RECEIPT_ACKED or ID_SND_RECEIPT_LOSS with bytes 1-4 inclusive containing this number
01167 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01168 uint32_t RakPeer::Send( const char *data, const int length, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceipt )
01169 {
01170 #ifdef _DEBUG
01171         RakAssert( data && length > 0 );
01172 #endif
01173         RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
01174         RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
01175         RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
01176 
01177         if ( data == 0 || length < 0 )
01178                 return 0;
01179 
01180         if ( remoteSystemList == 0 || endThreads == true )
01181                 return 0;
01182 
01183         if ( broadcast == false && systemIdentifier.IsUndefined())
01184                 return 0;
01185 
01186         uint32_t usedSendReceipt;
01187         if (forceReceipt!=0)
01188                 usedSendReceipt=forceReceipt;
01189         else
01190                 usedSendReceipt=IncrementNextSendReceipt();
01191 
01192         if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
01193         {
01194                 SendLoopback(data,length);
01195 
01196                 if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
01197                 {
01198                         char buff[5];
01199                         buff[0]=ID_SND_RECEIPT_ACKED;
01200                         sendReceiptSerialMutex.Lock();
01201                         memcpy(buff+1, &sendReceiptSerial, 4);
01202                         sendReceiptSerialMutex.Unlock();
01203                         SendLoopback( buff, 5 );
01204                 }
01205 
01206                 return usedSendReceipt;
01207         }
01208 
01209         if (broadcast==false && router && IsConnected(systemIdentifier.systemAddress)==false)
01210         {
01211                 router->Send(data, BYTES_TO_BITS(length), priority, reliability, orderingChannel, systemIdentifier.systemAddress);
01212         }
01213         else
01214         {
01215                 SendBuffered(data, length*8, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
01216         }
01217 
01218         return usedSendReceipt;
01219 }
01220 
01221 void RakPeer::SendLoopback( const char *data, const int length )
01222 {
01223         if ( data == 0 || length < 0 )
01224                 return;
01225 
01226         Packet *packet = AllocPacket(length, __FILE__, __LINE__);
01227         memcpy(packet->data, data, length);
01228         packet->systemAddress = GetLoopbackAddress();
01229         packet->guid=myGuid;
01230         PushBackPacket(packet, false);
01231 }
01232 
01233 uint32_t RakPeer::Send( const RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceipt )
01234 {
01235 #ifdef _DEBUG
01236         RakAssert( bitStream->GetNumberOfBytesUsed() > 0 );
01237 #endif
01238 
01239         RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
01240         RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
01241         RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
01242 
01243         if ( bitStream->GetNumberOfBytesUsed() == 0 )
01244                 return 0;
01245 
01246         if ( remoteSystemList == 0 || endThreads == true )
01247                 return 0;
01248 
01249         if ( broadcast == false && systemIdentifier.IsUndefined() )
01250                 return 0;
01251 
01252         uint32_t usedSendReceipt;
01253         if (forceReceipt!=0)
01254                 usedSendReceipt=forceReceipt;
01255         else
01256                 usedSendReceipt=IncrementNextSendReceipt();
01257 
01258         if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
01259         {
01260                 SendLoopback((const char*) bitStream->GetData(),bitStream->GetNumberOfBytesUsed());
01261                 if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
01262                 {
01263                         char buff[5];
01264                         buff[0]=ID_SND_RECEIPT_ACKED;
01265                         sendReceiptSerialMutex.Lock();
01266                         memcpy(buff+1, &sendReceiptSerial,4);
01267                         sendReceiptSerialMutex.Unlock();
01268                         SendLoopback( buff, 5 );
01269                 }
01270                 return usedSendReceipt;
01271         }
01272 
01273         if (broadcast==false && router && IsConnected(systemIdentifier.systemAddress)==false)
01274         {
01275                 router->Send((const char*)bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier.systemAddress);
01276         }
01277         else
01278         {
01279                 // Sends need to be buffered and processed in the update thread because the systemAddress associated with the reliability layer can change,
01280                 // from that thread, resulting in a send to the wrong player!  While I could mutex the systemAddress, that is much slower than doing this
01281                 SendBuffered((const char*)bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
01282         }
01283 
01284         return usedSendReceipt;
01285 }
01286 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01287 // Sends multiple blocks of data, concatenating them automatically.
01288 //
01289 // This is equivalent to:
01290 // RakNet::BitStream bs;
01291 // bs.WriteAlignedBytes(block1, blockLength1);
01292 // bs.WriteAlignedBytes(block2, blockLength2);
01293 // bs.WriteAlignedBytes(block3, blockLength3);
01294 // Send(&bs, ...)
01295 //
01296 // This function only works while the connected
01297 // \param[in] data An array of pointers to blocks of data
01298 // \param[in] lengths An array of integers indicating the length of each block of data
01299 // \param[in] numParameters Length of the arrays data and lengths
01300 // \param[in] priority What priority level to send on.  See PacketPriority.h
01301 // \param[in] reliability How reliability to send this data.  See PacketPriority.h
01302 // \param[in] orderingChannel When using ordered or sequenced messages, what channel to order these on. Messages are only ordered relative to other messages on the same stream
01303 // \param[in] systemIdentifier Who to send this packet to, or in the case of broadcasting who not to send it to. Pass either a SystemAddress structure or a RakNetGUID structure. Use UNASSIGNED_SYSTEM_ADDRESS or to specify none
01304 // \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to.
01305 // \return False if we are not connected to the specified recipient.  True otherwise
01306 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01307 uint32_t RakPeer::SendList( const char **data, const int *lengths, const int numParameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceipt )
01308 {
01309 #ifdef _DEBUG
01310         RakAssert( data );
01311 #endif
01312 
01313         if ( data == 0 || lengths == 0 )
01314                 return 0;
01315 
01316         if ( remoteSystemList == 0 || endThreads == true )
01317                 return 0;
01318 
01319         if (numParameters==0)
01320                 return 0;
01321 
01322         if (lengths==0)
01323                 return 0;
01324 
01325         if ( broadcast == false && systemIdentifier.IsUndefined() )
01326                 return 0;
01327 
01328         uint32_t usedSendReceipt;
01329         if (forceReceipt!=0)
01330                 usedSendReceipt=forceReceipt;
01331         else
01332                 usedSendReceipt=IncrementNextSendReceipt();
01333 
01334         SendBufferedList(data, lengths, numParameters, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
01335 
01336         return usedSendReceipt;
01337 }
01338 
01339 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01340 // Description:
01341 // Gets a packet from the incoming packet queue. Use DeallocatePacket to deallocate the packet after you are done with it.  Packets must be deallocated in the same order they are received.
01342 // Check the Packet struct at the top of CoreNetworkStructures.h for the format of the struct
01343 //
01344 // Returns:
01345 // 0 if no packets are waiting to be handled, otherwise an allocated packet
01346 // If the client is not active this will also return 0, as all waiting packets are flushed when the client is Disconnected
01347 // This also updates all memory blocks associated with synchronized memory and distributed objects
01348 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01349 Packet* RakPeer::Receive( void )
01350 {
01351         Packet *packet = ReceiveIgnoreRPC();
01352         while (packet && (packet->data[ 0 ] == ID_RPC || (packet->length>sizeof(unsigned char)+sizeof(RakNetTime) && packet->data[0]==ID_TIMESTAMP && packet->data[sizeof(unsigned char)+sizeof(RakNetTime)]==ID_RPC)))
01353         {
01354                 // Do RPC calls from the user thread, not the network update thread
01355                 // If we are currently blocking on an RPC reply, send ID_RPC to the blocker to handle rather than handling RPCs automatically
01356                 HandleRPCPacket( ( char* ) packet->data, packet->length, packet->systemAddress );
01357                 DeallocatePacket( packet );
01358 
01359                 packet = ReceiveIgnoreRPC();
01360         }
01361 
01362     return packet;
01363 }
01364 
01365 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01366 // Internal - Gets a packet without checking for RPCs
01367 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01368 #ifdef _MSC_VER
01369 #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
01370 #endif
01371 Packet* RakPeer::ReceiveIgnoreRPC( void )
01372 {
01373         if ( !( IsActive() ) )
01374                 return 0;
01375 
01376         Packet *packet;
01377 //      Packet **threadPacket;
01378         PluginReceiveResult pluginResult;
01379 
01380         int offset;
01381         unsigned int i;
01382 
01383         for (i=0; i < messageHandlerList.Size(); i++)
01384         {
01385                 messageHandlerList[i]->Update();
01386         }
01387 
01388         do
01389         {
01390                 packetReturnMutex.Lock();
01391                 if (packetReturnQueue.IsEmpty())
01392                         packet=0;
01393                 else
01394                         packet = packetReturnQueue.Pop();
01395                 packetReturnMutex.Unlock();
01396                 if (packet==0)
01397                         return 0;
01398 
01399                 unsigned char msgId;
01400                 if ( ( packet->length >= sizeof(unsigned char) + sizeof( RakNetTime ) ) &&
01401                         ( (unsigned char) packet->data[ 0 ] == ID_TIMESTAMP ) )
01402                 {
01403                         offset = sizeof(unsigned char);
01404                         ShiftIncomingTimestamp( packet->data + offset, packet->systemAddress );
01405                         msgId=packet->data[sizeof(unsigned char) + sizeof( RakNetTime )];
01406                 }
01407                 else
01408                         msgId=packet->data[0];
01409 
01410                 if ( (unsigned char) packet->data[ 0 ] == ID_RPC_REPLY )
01411                 {
01412                         HandleRPCReplyPacket( ( char* ) packet->data, packet->length, packet->systemAddress );
01413                         DeallocatePacket( packet );
01414                         packet=0; // Will do the loop again and get another packet
01415                 }
01416                 else
01417                 {
01418                         for (i=0; i < messageHandlerList.Size(); i++)
01419                         {
01420                                 switch (msgId)
01421                                 {
01422                                         case ID_DISCONNECTION_NOTIFICATION:
01423                                                 messageHandlerList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_DISCONNECTION_NOTIFICATION);
01424                                                 break;
01425                                         case ID_CONNECTION_LOST:
01426                                                 messageHandlerList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_CONNECTION_LOST);
01427                                                 break;
01428                                         case ID_NEW_INCOMING_CONNECTION:
01429                                                 messageHandlerList[i]->OnNewConnection(packet->systemAddress, packet->guid, true);
01430                                                 break;
01431                                         case ID_CONNECTION_REQUEST_ACCEPTED:
01432                                                 messageHandlerList[i]->OnNewConnection(packet->systemAddress, packet->guid, false);
01433                                                 break;
01434                                         case ID_CONNECTION_ATTEMPT_FAILED:
01435                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_ATTEMPT_FAILED);
01436                                                 break;
01437                                         case ID_ALREADY_CONNECTED:
01438                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_ALREADY_CONNECTED);
01439                                                 break;
01440                                         case ID_NO_FREE_INCOMING_CONNECTIONS:
01441                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_NO_FREE_INCOMING_CONNECTIONS);
01442                                                 break;
01443                                         case ID_RSA_PUBLIC_KEY_MISMATCH:
01444                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_RSA_PUBLIC_KEY_MISMATCH);
01445                                                 break;
01446                                         case ID_CONNECTION_BANNED:
01447                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_BANNED);
01448                                                 break;
01449                                         case ID_INVALID_PASSWORD:
01450                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_INVALID_PASSWORD);
01451                                                 break;
01452                                         case ID_INCOMPATIBLE_PROTOCOL_VERSION:
01453                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_INCOMPATIBLE_PROTOCOL);
01454                                                 break;
01455                                         case ID_IP_RECENTLY_CONNECTED:
01456                                                 messageHandlerList[i]->OnFailedConnectionAttempt(packet, FCAR_IP_RECENTLY_CONNECTED);
01457                                                 break;
01458                                 }
01459 
01460 
01461                                 pluginResult=messageHandlerList[i]->OnReceive(packet);
01462                                 if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
01463                                 {
01464                                         DeallocatePacket( packet );
01465                                         packet=0; // Will do the loop again and get another packet
01466                                         break; // break out of the enclosing for
01467                                 }
01468                                 else if (pluginResult==RR_STOP_PROCESSING)
01469                                 {
01470                                         packet=0;
01471                                         break;
01472                                 }
01473                         }
01474                 }
01475 
01476         } while(packet==0);
01477 
01478 #ifdef _DEBUG
01479         RakAssert( packet->data );
01480 #endif
01481 
01482         return packet;
01483 }
01484 
01485 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01486 // Description:
01487 // Call this to deallocate a packet returned by Receive
01488 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01489 void RakPeer::DeallocatePacket( Packet *packet )
01490 {
01491         if ( packet == 0 )
01492                 return;
01493 
01494         if (packet->deleteData)
01495         {
01496                 rakFree_Ex(packet->data, __FILE__, __LINE__ );
01497                 packet->~Packet();
01498                 packetAllocationPoolMutex.Lock();
01499                 packetAllocationPool.Release(packet,__FILE__,__LINE__);
01500                 packetAllocationPoolMutex.Unlock();
01501         }
01502         else
01503         {
01504                 rakFree_Ex(packet, __FILE__, __LINE__ );
01505         }
01506 }
01507 
01508 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01509 // Description:
01510 // Return the total number of connections we are allowed
01511 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01512 unsigned short RakPeer::GetMaximumNumberOfPeers( void ) const
01513 {
01514         return maximumNumberOfPeers;
01515 }
01516 
01517 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01518 // Description:
01519 // Register a C function as available for calling as a remote procedure call
01520 //
01521 // Parameters:
01522 // uniqueID: A string of only letters to identify this procedure.  Recommended you use the macro CLASS_MEMBER_ID for class member functions
01523 // functionName(...): The name of the C function or C++ singleton to be used as a function pointer
01524 // This can be called whether the client is active or not, and registered functions stay registered unless unregistered with
01525 // UnregisterAsRemoteProcedureCall
01526 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01527 void RakPeer::RegisterAsRemoteProcedureCall( const char* uniqueID, void ( *functionPointer ) ( RPCParameters *rpcParms ) )
01528 {
01529         if ( uniqueID == 0 || uniqueID[ 0 ] == 0 || functionPointer == 0 )
01530                 return;
01531 
01532         rpcMap.AddIdentifierWithFunction(uniqueID, (void*)functionPointer, false);
01533 
01534         /*
01535         char uppercaseUniqueID[ 256 ];
01536 
01537         int counter = 0;
01538 
01539         while ( uniqueID[ counter ] )
01540         {
01541                 uppercaseUniqueID[ counter ] = ( char ) toupper( uniqueID[ counter ] );
01542                 counter++;
01543         }
01544 
01545         uppercaseUniqueID[ counter ] = 0;
01546 
01547         // Each id must be unique
01548 //#ifdef _DEBUG
01549 //      RakAssert( rpcTree.IsIn( RPCNode( uppercaseUniqueID, functionName ) ) == false );
01550 //#endif
01551 
01552         if (rpcTree.IsIn( RPCNode( uppercaseUniqueID, functionName ) ))
01553                 return;
01554 
01555         rpcTree.Add( RPCNode( uppercaseUniqueID, functionName ) );
01556         */
01557 }
01558 
01559 void RakPeer::RegisterClassMemberRPC( const char* uniqueID, void *functionPointer )
01560 {
01561         if ( uniqueID == 0 || uniqueID[ 0 ] == 0 || functionPointer == 0 )
01562                 return;
01563 
01564         rpcMap.AddIdentifierWithFunction(uniqueID, functionPointer, true);
01565 }
01566 
01567 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01568 // Description:
01569 // Unregisters a C function as available for calling as a remote procedure call that was formerly registered
01570 // with RegisterAsRemoteProcedureCall
01571 //
01572 // Parameters:
01573 // uniqueID: A null terminated string to identify this procedure.  Must match the parameter
01574 // passed to RegisterAsRemoteProcedureCall
01575 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01576 void RakPeer::UnregisterAsRemoteProcedureCall( const char* uniqueID )
01577 {
01578         if ( uniqueID == 0 || uniqueID[ 0 ] == 0 )
01579                 return;
01580 
01581 // Don't call this while running because if you remove RPCs and add them they will not match the indices on the other systems anymore
01582 #ifdef _DEBUG
01583         RakAssert(IsActive()==false);
01584         //RakAssert( strlen( uniqueID ) < 256 );
01585 #endif
01586 
01587         rpcMap.RemoveNode(uniqueID);
01588 
01589         /*
01590         char uppercaseUniqueID[ 256 ];
01591 
01592         strcpy( uppercaseUniqueID, uniqueID );
01593 
01594         int counter = 0;
01595 
01596         while ( uniqueID[ counter ] )
01597         {
01598                 uppercaseUniqueID[ counter ] = ( char ) toupper( uniqueID[ counter ] );
01599                 counter++;
01600         }
01601 
01602         uppercaseUniqueID[ counter ] = 0;
01603 
01604         // Unique ID must exist
01605 #ifdef _DEBUG
01606         RakAssert( rpcTree.IsIn( RPCNode( uppercaseUniqueID, 0 ) ) == true );
01607 #endif
01608 
01609         rpcTree.Del( RPCNode( uppercaseUniqueID, 0 ) );
01610         */
01611 }
01612 
01613 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01614 void RakPeer::SetNetworkIDManager( NetworkIDManager *manager )
01615 {
01616         networkIDManager=manager;
01617         if (manager)
01618                 manager->SetGuid(myGuid);
01619 }
01620 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01621 NetworkIDManager *RakPeer::GetNetworkIDManager(void) const
01622 {
01623         return networkIDManager;
01624 }
01625 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01626 bool RakPeer::RPC( const char* uniqueID, const char *data, BitSize_t bitLength, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RakNetTime *includedTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget )
01627 {
01628 #ifdef _DEBUG
01629         RakAssert( uniqueID && uniqueID[ 0 ] );
01630         RakAssert(orderingChannel >=0 && orderingChannel < 32);
01631 #endif
01632 
01633         if ( uniqueID == 0 )
01634                 return false;
01635 
01636         if ( strlen( uniqueID ) > 256 )
01637         {
01638 #ifdef _DEBUG
01639                 RakAssert( 0 );
01640 #endif
01641                 return false; // Unique ID is too long
01642         }
01643         if (replyFromTarget && blockOnRPCReply==true)
01644         {
01645                 // TODO - this should be fixed eventually
01646                 // Prevent a bug where function A calls B (blocking) which calls C back on the sender, which calls D, and C is blocking.
01647                 // blockOnRPCReply is a shared variable so making it unset would unset both blocks, rather than the lowest on the callstack
01648                 // Fix by tracking which function the reply is for.
01649                 return false;
01650         }
01651 
01652         unsigned *sendList;
01653 //      bool callerAllocationDataUsed;
01654         unsigned sendListSize;
01655 
01656         // All this code modifies bcs->data and bcs->numberOfBitsToSend in order to transform an RPC request into an actual packet for SendImmediate
01657         RPCIndex rpcIndex; // Index into the list of RPC calls so we know what number to encode in the packet
01658 //      char *userData; // RPC ID (the name of it) and a pointer to the data sent by the user
01659 //      int extraBuffer; // How many data bytes were allocated to hold the RPC header
01660         unsigned remoteSystemIndex, sendListIndex; // Iterates into the list of remote systems
01661 //      int dataBlockAllocationLength; // Total number of bytes to allocate for the packet
01662 //      char *writeTarget; // Used to hold either a block of allocated data or the externally allocated data
01663 
01664         sendListSize=0;
01665         bool routeSend;
01666         routeSend=false;
01667 
01668         if (broadcast==false)
01669         {
01670 #if !defined(_XBOX) && !defined(X360)
01671                 sendList=(unsigned *)alloca(sizeof(unsigned));
01672 #else
01673                 sendList = (unsigned int*) rakMalloc_Ex(sizeof(unsigned), __FILE__, __LINE__);
01674 #endif
01675                 remoteSystemIndex=GetIndexFromSystemAddress( systemIdentifier.systemAddress, false );
01676                 if (remoteSystemIndex!=(unsigned)-1 &&
01677                         remoteSystemList[remoteSystemIndex].isActive &&
01678                         remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP &&
01679                         remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY &&
01680                         remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
01681                 {
01682                         sendList[0]=remoteSystemIndex;
01683                         sendListSize=1;
01684                 }
01685                 else if (router)
01686                         routeSend=true;
01687         }
01688         else
01689         {
01690 #if !defined(_XBOX) && !defined(X360)
01691                 sendList=(unsigned *)alloca(sizeof(unsigned)*maximumNumberOfPeers);
01692 #else
01693                 sendList = (unsigned int*) rakMalloc_Ex(sizeof(unsigned)*maximumNumberOfPeers, __FILE__, __LINE__);
01694 #endif
01695 
01696                 for ( remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; remoteSystemIndex++ )
01697                 {
01698                         if ( remoteSystemList[ remoteSystemIndex ].isActive && remoteSystemList[ remoteSystemIndex ].systemAddress != systemIdentifier.systemAddress )
01699                                 sendList[sendListSize++]=remoteSystemIndex;
01700                 }
01701         }
01702 
01703         if (sendListSize==0 && routeSend==false)
01704         {
01705 #if defined(_XBOX) || defined(X360)
01706                                             
01707 #endif
01708 
01709                 return false;
01710         }
01711         if (routeSend)
01712                 sendListSize=1;
01713 
01714         RakNet::BitStream outgoingBitStream;
01715         // remoteSystemList in network thread
01716         for (sendListIndex=0; sendListIndex < (unsigned)sendListSize; sendListIndex++)
01717         {
01718                 outgoingBitStream.ResetWritePointer(); // Let us write at the start of the data block, rather than at the end
01719 
01720                 if (includedTimestamp)
01721                 {
01722                         outgoingBitStream.Write((MessageID)ID_TIMESTAMP);
01723                         outgoingBitStream.Write(*includedTimestamp);
01724                 }
01725                 outgoingBitStream.Write((MessageID)ID_RPC);
01726                 if (routeSend)
01727                         rpcIndex=UNDEFINED_RPC_INDEX;
01728                 else
01729                         rpcIndex=remoteSystemList[sendList[sendListIndex]].rpcMap.GetIndexFromFunctionName(uniqueID); // Lots of trouble but we can only use remoteSystem->[whatever] in this thread so that is why this command was buffered
01730                 if (rpcIndex!=UNDEFINED_RPC_INDEX)
01731                 {
01732                         // We have an RPC name to an index mapping, so write the index
01733                         outgoingBitStream.Write(false);
01734                         outgoingBitStream.WriteCompressed(rpcIndex);
01735                 }
01736                 else
01737                 {
01738                         // No mapping, so write the encoded RPC name
01739                         outgoingBitStream.Write(true);
01740                         stringCompressor->EncodeString(uniqueID, 256, &outgoingBitStream);
01741                 }
01742                 outgoingBitStream.Write((bool) ((replyFromTarget!=0)==true));
01743                 outgoingBitStream.WriteCompressed( bitLength );
01744                 if (networkID==UNASSIGNED_NETWORK_ID)
01745                 {
01746                         // No object ID
01747                         outgoingBitStream.Write(false);
01748                 }
01749                 else
01750                 {
01751                         // Encode an object ID.  This will use pointer to class member RPC
01752                         outgoingBitStream.Write(true);
01753                         outgoingBitStream.Write(networkID);
01754                 }
01755 
01756 
01757                 if ( bitLength > 0 )
01758                         outgoingBitStream.WriteBits( (const unsigned char *) data, bitLength, false ); // Last param is false to write the raw data originally from another bitstream, rather than shifting from user data
01759                 else
01760                         outgoingBitStream.WriteCompressed( ( unsigned int ) 0 );
01761 
01762                 if (routeSend)
01763                         router->Send((const char*)outgoingBitStream.GetData(), outgoingBitStream.GetNumberOfBitsUsed(), priority,reliability,orderingChannel,systemIdentifier.systemAddress);
01764                 else
01765                         Send(&outgoingBitStream, priority, reliability, orderingChannel, remoteSystemList[sendList[sendListIndex]].systemAddress, false);
01766         }
01767 
01768 #if defined(_XBOX) || defined(X360)
01769                                                        
01770 #endif
01771 
01772         if (replyFromTarget)
01773         {
01774                 blockOnRPCReply=true;
01775                 // 04/20/06 Just do this transparently.
01776                 // We have to be able to read blocking packets out of order.  Otherwise, if two systems were to send blocking RPC calls to each other at the same time,
01777                 // and they also had ordered packets waiting before the block, it would be impossible to unblock.
01778                 // RakAssert(reliability==RELIABLE || reliability==UNRELIABLE);
01779                 replyFromTargetBS=replyFromTarget;
01780                 replyFromTargetPlayer=systemIdentifier.systemAddress;
01781                 replyFromTargetBroadcast=broadcast;
01782         }
01783 
01784         // Do not enter this loop on blockOnRPCReply because it is a global which could be set to true by an RPC higher on the callstack, where one RPC was called while waiting for another RPC
01785         if (replyFromTarget)
01786 //      if (blockOnRPCReply)
01787         {
01788 //              Packet *p;
01789                 RakNetTime stopWaitingTime=RakNet::GetTime()+30000;
01790 //              RPCIndex arrivedRPCIndex;
01791 //              char uniqueIdentifier[256];
01792                 if (reliability==UNRELIABLE)
01793                         if (systemIdentifier.systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
01794                                 stopWaitingTime=RakNet::GetTime()+1500; // Lets guess the ave. ping is 500.  Not important to be very accurate
01795                         else
01796                                 stopWaitingTime=RakNet::GetTime()+GetAveragePing(systemIdentifier.systemAddress)*3;
01797 
01798                 // For reliable messages, block until we get a reply or the connection is lost
01799                 // For unreliable messages, block until we get a reply, the connection is lost, or 3X the ping passes
01800                 while (blockOnRPCReply &&
01801                         ((
01802                         reliability==RELIABLE ||
01803                         reliability==RELIABLE_ORDERED ||
01804                         reliability==RELIABLE_SEQUENCED ||
01805                         reliability==RELIABLE_WITH_ACK_RECEIPT ||
01806                         reliability==RELIABLE_ORDERED_WITH_ACK_RECEIPT
01807 //                      ||
01808 //                      reliability==RELIABLE_SEQUENCED_WITH_ACK_RECEIPT
01809                         ) ||
01810                         RakNet::GetTime() < stopWaitingTime))
01811                 {
01812 
01813                         RakSleep(30);
01814 
01815                         if (routeSend==false && ValidSendTarget(systemIdentifier.systemAddress, broadcast)==false)
01816                                 return false;
01817 
01818                         unsigned i;
01819                         i=0;
01820 
01821 
01822                         packetReturnMutex.Lock();
01823                         while (i < packetReturnQueue.Size())
01824                         {
01825                                 if ((unsigned char) packetReturnQueue[i]->data[ 0 ] == ID_RPC_REPLY )
01826                                 {
01827                                         HandleRPCReplyPacket( ( char* ) packetReturnQueue[i]->data, packetReturnQueue[i]->length, packetReturnQueue[i]->systemAddress );
01828                                         DeallocatePacket( packetReturnQueue[i] );
01829                                         packetReturnQueue.RemoveAtIndex(i);
01830                                 }
01831                                 else
01832                                         i++;
01833                         }
01834                         packetReturnMutex.Unlock();
01835 
01836                         /*
01837                         // Scan for RPC reply packets to break out of this loop
01838                         while (i < packetPool.Size())
01839                         {
01840                                 if ((unsigned char) packetPool[i]->data[ 0 ] == ID_RPC_REPLY )
01841                                 {
01842                                         HandleRPCReplyPacket( ( char* ) packetPool[i]->data, packetPool[i]->length, packetPool[i]->systemAddress );
01843                                         DeallocatePacket( packetPool[i] );
01844                                         packetPool.RemoveAtIndex(i);
01845                                 }
01846                                 else
01847                                         i++;
01848                         }
01849 #ifdef _RAKNET_THREADSAFE
01850                                 rakPeerMutexes[packetPool_Mutex].Unlock();
01851 #endif
01852                                 */
01853 
01854                         PushBackPacket(ReceiveIgnoreRPC(), false);
01855 
01856 
01857                         // I might not support processing other RPCs while blocking on one due to complexities I can't control
01858                         // Problem is FuncA calls FuncB which calls back to the sender FuncC. Sometimes it is desirable to call FuncC before returning a return value
01859                         // from FuncB - sometimes not.  There is also a problem with recursion where FuncA calls FuncB which calls FuncA - sometimes valid if
01860                         // a different control path is taken in FuncA. (This can take many different forms)
01861                         /*
01862                         // Same as Receive, but doesn't automatically do RPCs
01863                         p = ReceiveIgnoreRPC();
01864                         if (p)
01865                         {
01866                                 // Process all RPC calls except for those calling the function we are currently blocking in (to prevent recursion).
01867                                 if ( p->data[ 0 ] == ID_RPC )
01868                                 {
01869                                         RakNet::BitStream temp((unsigned char *) p->data, p->length, false);
01870                                         RPCNode *rpcNode;
01871                                         temp.IgnoreBits(8);
01872                                         bool nameIsEncoded;
01873                                         temp.Read(nameIsEncoded);
01874                                         if (nameIsEncoded)
01875                                         {
01876                                                 stringCompressor->DecodeString((char*)uniqueIdentifier, 256, &temp);
01877                                         }
01878                                         else
01879                                         {
01880                                                 temp.ReadCompressed( arrivedRPCIndex );
01881                                                 rpcNode=rpcMap.GetNodeFromIndex( arrivedRPCIndex );
01882                                                 if (rpcNode==0)
01883                                                 {
01884                                                         // Invalid RPC format
01885 #ifdef _DEBUG
01886                                                         RakAssert(0);
01887 #endif
01888                                                         DeallocatePacket(p);
01889                                                         continue;
01890                                                 }
01891                                                 else
01892                                                         strcpy(uniqueIdentifier, rpcNode->uniqueIdentifier);
01893                                         }
01894 
01895                                         if (strcmp(uniqueIdentifier, uniqueID)!=0)
01896                                         {
01897                                                 HandleRPCPacket( ( char* ) p->data, p->length, p->systemAddress );
01898                                                 DeallocatePacket(p);
01899                                         }
01900                                         else
01901                                         {
01902                                                 PushBackPacket(p, false);
01903                                         }
01904                                 }
01905                                 else
01906                                 {
01907                                         PushBackPacket(p, false);
01908                                 }
01909                         }
01910                         */
01911                 }
01912 
01913                 blockOnRPCReply=false;
01914         }
01915 
01916         return true;
01917 }
01918 
01919 
01920 #ifdef _MSC_VER
01921 #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
01922 #endif
01923 bool RakPeer::RPC( const char* uniqueID, const RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RakNetTime *includedTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget )
01924 {
01925         if (bitStream)
01926                 return RPC(uniqueID, (const char*) bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier.systemAddress, broadcast, includedTimestamp, networkID, replyFromTarget);
01927         else
01928                 return RPC(uniqueID, 0,0, priority, reliability, orderingChannel, systemIdentifier.systemAddress, broadcast, includedTimestamp, networkID, replyFromTarget);
01929 }
01930 
01931 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01932 // Description:
01933 // Close the connection to another host (if we initiated the connection it will disconnect, if they did it will kick them out).
01934 //
01935 // Parameters:
01936 // target: Which connection to close
01937 // sendDisconnectionNotification: True to send ID_DISCONNECTION_NOTIFICATION to the recipient. False to close it silently.
01938 // channel: If blockDuration > 0, the disconnect packet will be sent on this channel
01939 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01940 void RakPeer::CloseConnection( const SystemAddress target, bool sendDisconnectionNotification, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
01941 {
01942         // This only be called from the user thread, for the user shutting down.
01943         // From the network thread, this should occur because of ID_DISCONNECTION_NOTIFICATION and ID_CONNECTION_LOST
01944         unsigned j;
01945         for (j=0; j < messageHandlerList.Size(); j++)
01946         {
01947                 messageHandlerList[j]->OnClosedConnection(target, GetGuidFromSystemAddress(target), LCR_CLOSED_BY_USER);
01948         }
01949 
01950         CloseConnectionInternal(target, sendDisconnectionNotification, false, orderingChannel, disconnectionNotificationPriority);
01951 
01952         // 12/14/09 Return ID_CONNECTION_LOST when calling CloseConnection with sendDisconnectionNotification==false, elsewise it is never returned
01953         if (sendDisconnectionNotification==false && IsConnected(target,false,false))
01954         {
01955                 Packet *packet=AllocPacket(sizeof( char ), __FILE__, __LINE__);
01956                 packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
01957                 packet->guid = GetGuidFromSystemAddress(target);
01958                 packet->systemAddress = target;
01959                 packet->systemAddress.systemIndex = (SystemIndex) GetIndexFromSystemAddress(target,false);
01960                 packet->guid.systemIndex=packet->systemAddress.systemIndex;
01961                 AddPacketToProducer(packet);
01962         }
01963 }
01964 
01965 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01966 // Cancel a pending connection attempt
01967 // If we are already connected, the connection stays open
01968 // \param[in] target Which system to cancel
01969 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01970 void RakPeer::CancelConnectionAttempt( const SystemAddress target )
01971 {
01972         unsigned int i;
01973 
01974         // Cancel pending connection attempt, if there is one
01975         i=0;
01976         requestedConnectionQueueMutex.Lock();
01977         while (i < requestedConnectionQueue.Size())
01978         {
01979                 if (requestedConnectionQueue[i]->systemAddress==target)
01980                 {
01981                         RakNet::OP_DELETE(requestedConnectionQueue[i], __FILE__, __LINE__ );
01982                         requestedConnectionQueue.RemoveAtIndex(i);
01983                         break;
01984                 }
01985                 else
01986                         i++;
01987         }
01988         requestedConnectionQueueMutex.Unlock();
01989 
01990 }
01991 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01992 bool RakPeer::IsConnectionAttemptPending( const SystemAddress systemAddress )
01993 {
01994         unsigned int i=0;
01995         requestedConnectionQueueMutex.Lock();
01996         for (; i < requestedConnectionQueue.Size(); i++)
01997         {
01998                 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
01999                 {
02000                         requestedConnectionQueueMutex.Unlock();
02001                         return true;
02002                 }
02003         }
02004         requestedConnectionQueueMutex.Unlock();
02005 
02006         int index = GetIndexFromSystemAddress(systemAddress, false);
02007         return index!=-1 && remoteSystemList[index].isActive &&
02008                 (((remoteSystemList[index].connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
02009                 remoteSystemList[index].connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
02010                 remoteSystemList[index].connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
02011                 remoteSystemList[index].connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET))
02012                 )
02013                 ;
02014 }
02015 
02016 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02017 // Returns if a particular systemAddress is connected to us
02018 // \param[in] systemAddress The SystemAddress we are referring to
02019 // \return True if this system is connected and active, false otherwise.
02020 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02021 bool RakPeer::IsConnected( const AddressOrGUID systemIdentifier, bool includeInProgress, bool includeDisconnecting )
02022 {
02023         if (includeInProgress && systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
02024         {
02025                 unsigned int i=0;
02026                 requestedConnectionQueueMutex.Lock();
02027                 for (; i < requestedConnectionQueue.Size(); i++)
02028                 {
02029                         if (requestedConnectionQueue[i]->systemAddress==systemIdentifier.systemAddress)
02030                         {
02031                                 requestedConnectionQueueMutex.Unlock();
02032                                 return true;
02033                         }
02034                 }
02035                 requestedConnectionQueueMutex.Unlock();
02036         }
02037 
02038 
02039         int index;
02040         if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
02041         {
02042                 if (IsLoopbackAddress(systemIdentifier.systemAddress,true))
02043                         return true;
02044                 index = GetIndexFromSystemAddress(systemIdentifier.systemAddress, false);
02045                 return index!=-1 && remoteSystemList[index].isActive &&
02046                         (((includeInProgress && (remoteSystemList[index].connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
02047                         remoteSystemList[index].connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
02048                         remoteSystemList[index].connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
02049                         remoteSystemList[index].connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET))
02050                         ||
02051                         (includeDisconnecting && (
02052                         remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP ||
02053                         remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY ||
02054                         remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK))
02055                         ||
02056                         remoteSystemList[index].connectMode==RemoteSystemStruct::CONNECTED))
02057                         ;
02058         }
02059         else
02060         {
02061                 index = GetIndexFromGuid(systemIdentifier.rakNetGuid);
02062                 return index!=-1 && remoteSystemList[index].isActive &&
02063                         (((includeInProgress && (remoteSystemList[index].connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
02064                         remoteSystemList[index].connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
02065                         remoteSystemList[index].connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
02066                         remoteSystemList[index].connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET))
02067                         ||
02068                         (includeDisconnecting && (
02069                         remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP ||
02070                         remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY ||
02071                         remoteSystemList[index].connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK))
02072                         ||
02073                         remoteSystemList[index].connectMode==RemoteSystemStruct::CONNECTED))
02074                         ;
02075         }
02076 }
02077 
02078 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02079 // Description:
02080 // Given a systemAddress, returns an index from 0 to the maximum number of players allowed - 1.
02081 //
02082 // Parameters
02083 // systemAddress - The systemAddress to search for
02084 //
02085 // Returns
02086 // An integer from 0 to the maximum number of peers -1, or -1 if that player is not found
02087 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02088 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress ) const
02089 {
02090         return GetIndexFromSystemAddress(systemAddress, false);
02091 }
02092 
02093 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02094 // Description:
02095 // This function is only useful for looping through all players.
02096 //
02097 // Parameters
02098 // index - an integer between 0 and the maximum number of players allowed - 1.
02099 //
02100 // Returns
02101 // A valid systemAddress or UNASSIGNED_SYSTEM_ADDRESS if no such player at that index
02102 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02103 SystemAddress RakPeer::GetSystemAddressFromIndex( int index )
02104 {
02105         // remoteSystemList in user thread
02106         //if ( index >= 0 && index < remoteSystemListSize )
02107         if ( index >= 0 && index < maximumNumberOfPeers )
02108                 if (remoteSystemList[index].isActive && remoteSystemList[ index ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED) // Don't give the user players that aren't fully connected, since sends will fail
02109                         return remoteSystemList[ index ].systemAddress;
02110 
02111         return UNASSIGNED_SYSTEM_ADDRESS;
02112 }
02113 
02114 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02115 // Same as GetSystemAddressFromIndex but returns RakNetGUID
02116 // \param[in] index Index should range between 0 and the maximum number of players allowed - 1.
02117 // \return The RakNetGUID
02118 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02119 RakNetGUID RakPeer::GetGUIDFromIndex( int index )
02120 {
02121         // remoteSystemList in user thread
02122         //if ( index >= 0 && index < remoteSystemListSize )
02123         if ( index >= 0 && index < maximumNumberOfPeers )
02124                 if (remoteSystemList[index].isActive && remoteSystemList[ index ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED) // Don't give the user players that aren't fully connected, since sends will fail
02125                         return remoteSystemList[ index ].guid;
02126 
02127         return UNASSIGNED_RAKNET_GUID;
02128 }
02129 
02130 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02131 // Same as calling GetSystemAddressFromIndex and GetGUIDFromIndex for all systems, but more efficient
02132 // Indices match each other, so \a addresses[0] and \a guids[0] refer to the same system
02133 // \param[out] addresses All system addresses. Size of the list is the number of connections. Size of the list will match the size of the \a guids list.
02134 // \param[out] guids All guids. Size of the list is the number of connections. Size of the list will match the size of the \a addresses list.
02135 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02136 void RakPeer::GetSystemList(DataStructures::List<SystemAddress> &addresses, DataStructures::List<RakNetGUID> &guids)
02137 {
02138         addresses.Clear(false, __FILE__, __LINE__);
02139         guids.Clear(false, __FILE__, __LINE__);
02140         int index;
02141         for (index=0; index < maximumNumberOfPeers; index++)
02142         {
02143                  // Don't give the user players that aren't fully connected, since sends will fail
02144                 if (remoteSystemList[index].isActive && remoteSystemList[ index ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED)
02145                 {
02146                         addresses.Push(remoteSystemList[index].systemAddress, __FILE__, __LINE__ );
02147                         guids.Push(remoteSystemList[index].guid, __FILE__, __LINE__ );
02148                 }
02149         }
02150 }
02151 
02152 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02153 // Description:
02154 // Bans an IP from connecting. Banned IPs persist between connections.
02155 //
02156 // Parameters
02157 // IP - Dotted IP address.  Can use * as a wildcard, such as 128.0.0.* will ban
02158 // All IP addresses starting with 128.0.0
02159 // milliseconds - how many ms for a temporary ban.  Use 0 for a permanent ban
02160 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02161 void RakPeer::AddToBanList( const char *IP, RakNetTime milliseconds )
02162 {
02163         unsigned index;
02164         RakNetTime time = RakNet::GetTime();
02165 
02166         if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
02167                 return ;
02168 
02169         // If this guy is already in the ban list, do nothing
02170         index = 0;
02171 
02172         banListMutex.Lock();
02173 
02174         for ( ; index < banList.Size(); index++ )
02175         {
02176                 if ( strcmp( IP, banList[ index ]->IP ) == 0 )
02177                 {
02178                         // Already in the ban list.  Just update the time
02179                         if (milliseconds==0)
02180                                 banList[ index ]->timeout=0; // Infinite
02181                         else
02182                                 banList[ index ]->timeout=time+milliseconds;
02183                         banListMutex.Unlock();
02184                         return;
02185                 }
02186         }
02187 
02188         banListMutex.Unlock();
02189 
02190         BanStruct *banStruct = RakNet::OP_NEW<BanStruct>( __FILE__, __LINE__ );
02191         banStruct->IP = (char*) rakMalloc_Ex( 16, __FILE__, __LINE__ );
02192         if (milliseconds==0)
02193                 banStruct->timeout=0; // Infinite
02194         else
02195                 banStruct->timeout=time+milliseconds;
02196         strcpy( banStruct->IP, IP );
02197         banListMutex.Lock();
02198         banList.Insert( banStruct, __FILE__, __LINE__ );
02199         banListMutex.Unlock();
02200 }
02201 
02202 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02203 // Description:
02204 // Allows a previously banned IP to connect.
02205 //
02206 // Parameters
02207 // IP - Dotted IP address.  Can use * as a wildcard, such as 128.0.0.* will ban
02208 // All IP addresses starting with 128.0.0
02209 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02210 void RakPeer::RemoveFromBanList( const char *IP )
02211 {
02212         unsigned index;
02213         BanStruct *temp;
02214 
02215         if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
02216                 return ;
02217 
02218         index = 0;
02219         temp=0;
02220 
02221         banListMutex.Lock();
02222 
02223         for ( ; index < banList.Size(); index++ )
02224         {
02225                 if ( strcmp( IP, banList[ index ]->IP ) == 0 )
02226                 {
02227                         temp = banList[ index ];
02228                         banList[ index ] = banList[ banList.Size() - 1 ];
02229                         banList.RemoveAtIndex( banList.Size() - 1 );
02230                         break;
02231                 }
02232         }
02233 
02234         banListMutex.Unlock();
02235 
02236         if (temp)
02237         {
02238                 rakFree_Ex(temp->IP, __FILE__, __LINE__ );
02239                 RakNet::OP_DELETE(temp, __FILE__, __LINE__);
02240         }
02241 
02242 }
02243 
02244 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02245 // Description:
02246 // Allows all previously banned IPs to connect.
02247 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02248 void RakPeer::ClearBanList( void )
02249 {
02250         unsigned index;
02251         index = 0;
02252         banListMutex.Lock();
02253 
02254         for ( ; index < banList.Size(); index++ )
02255         {
02256                 rakFree_Ex(banList[ index ]->IP, __FILE__, __LINE__ );
02257                 RakNet::OP_DELETE(banList[ index ], __FILE__, __LINE__);
02258         }
02259 
02260         banList.Clear(false, __FILE__, __LINE__);
02261 
02262         banListMutex.Unlock();
02263 }
02264 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02265 void RakPeer::SetLimitIPConnectionFrequency(bool b)
02266 {
02267         limitConnectionFrequencyFromTheSameIP=b;
02268 }
02269 
02270 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02271 // Description:
02272 // Determines if a particular IP is banned.
02273 //
02274 // Parameters
02275 // IP - Complete dotted IP address
02276 //
02277 // Returns
02278 // True if IP matches any IPs in the ban list, accounting for any wildcards.
02279 // False otherwise.
02280 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02281 bool RakPeer::IsBanned( const char *IP )
02282 {
02283         unsigned banListIndex, characterIndex;
02284         RakNetTime time;
02285         BanStruct *temp;
02286 
02287         if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
02288                 return false;
02289 
02290         banListIndex = 0;
02291 
02292         if ( banList.Size() == 0 )
02293                 return false; // Skip the mutex if possible
02294 
02295         time = RakNet::GetTime();
02296 
02297         banListMutex.Lock();
02298 
02299         while ( banListIndex < banList.Size() )
02300         {
02301                 if (banList[ banListIndex ]->timeout>0 && banList[ banListIndex ]->timeout<time)
02302                 {
02303                         // Delete expired ban
02304                         temp = banList[ banListIndex ];
02305                         banList[ banListIndex ] = banList[ banList.Size() - 1 ];
02306                         banList.RemoveAtIndex( banList.Size() - 1 );
02307                         rakFree_Ex(temp->IP, __FILE__, __LINE__ );
02308                         RakNet::OP_DELETE(temp, __FILE__, __LINE__);
02309                 }
02310                 else
02311                 {
02312                         characterIndex = 0;
02313 
02314 #ifdef _MSC_VER
02315 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
02316 #endif
02317                         while ( true )
02318                         {
02319                                 if ( banList[ banListIndex ]->IP[ characterIndex ] == IP[ characterIndex ] )
02320                                 {
02321                                         // Equal characters
02322 
02323                                         if ( IP[ characterIndex ] == 0 )
02324                                         {
02325                                                 banListMutex.Unlock();
02326                                                 // End of the string and the strings match
02327 
02328                                                 return true;
02329                                         }
02330 
02331                                         characterIndex++;
02332                                 }
02333 
02334                                 else
02335                                 {
02336                                         if ( banList[ banListIndex ]->IP[ characterIndex ] == 0 || IP[ characterIndex ] == 0 )
02337                                         {
02338                                                 // End of one of the strings
02339                                                 break;
02340                                         }
02341 
02342                                         // Characters do not match
02343                                         if ( banList[ banListIndex ]->IP[ characterIndex ] == '*' )
02344                                         {
02345                                                 banListMutex.Unlock();
02346 
02347                                                 // Domain is banned.
02348                                                 return true;
02349                                         }
02350 
02351                                         // Characters do not match and it is not a *
02352                                         break;
02353                                 }
02354                         }
02355 
02356                         banListIndex++;
02357                 }
02358         }
02359 
02360         banListMutex.Unlock();
02361 
02362         // No match found.
02363         return false;
02364 }
02365 
02366 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02367 // Description:
02368 // Send a ping to the specified connected system.
02369 //
02370 // Parameters:
02371 // target - who to ping
02372 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02373 void RakPeer::Ping( const SystemAddress target )
02374 {
02375         PingInternal(target, false, UNRELIABLE);
02376 }
02377 
02378 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02379 // Description:
02380 // Send a ping to the specified unconnected system.
02381 // The remote system, if it is Initialized, will respond with ID_PONG.
02382 // The final ping time will be encoded in the following sizeof(RakNetTime) bytes.  (Default is 4 bytes - See __GET_TIME_64BIT in RakNetTypes.h
02383 //
02384 // Parameters:
02385 // host: Either a dotted IP address or a domain name.  Can be 255.255.255.255 for LAN broadcast.
02386 // remotePort: Which port to connect to on the remote machine.
02387 // onlyReplyOnAcceptingConnections: Only request a reply if the remote system has open connections
02388 // connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on.
02389 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02390 bool RakPeer::Ping( const char* host, unsigned short remotePort, bool onlyReplyOnAcceptingConnections, unsigned connectionSocketIndex )
02391 {
02392         if ( host == 0 )
02393                 return false;
02394 
02395         // If this assert hits then Startup wasn't called or the call failed.
02396         RakAssert(connectionSocketIndex < socketList.Size());
02397 
02398 //      if ( IsActive() == false )
02399 //              return;
02400 
02401         if ( NonNumericHostString( host ) )
02402         {
02403                 host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host );
02404                 if (host==0)
02405                         return false;
02406         }
02407 
02408         SystemAddress systemAddress;
02409         systemAddress.SetBinaryAddress(host);
02410         systemAddress.port=remotePort;
02411 
02412         RakNet::BitStream bitStream( sizeof(unsigned char) + sizeof(RakNetTime) );
02413         if ( onlyReplyOnAcceptingConnections )
02414                 bitStream.Write((MessageID)ID_PING_OPEN_CONNECTIONS);
02415         else
02416                 bitStream.Write((MessageID)ID_PING);
02417 
02418         bitStream.Write(RakNet::GetTime());
02419 
02420         bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
02421 
02422         unsigned i;
02423         for (i=0; i < messageHandlerList.Size(); i++)
02424                 messageHandlerList[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
02425         // No timestamp for 255.255.255.255
02426         unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
02427         SocketLayer::Instance()->SendTo( socketList[realIndex]->s, (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), ( char* ) host, remotePort, socketList[realIndex]->remotePortRakNetWasStartedOn_PS3 );
02428 
02429         return true;
02430 }
02431 
02432 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02433 // Description:
02434 // Returns the average of all ping times read for a specified target
02435 //
02436 // Parameters:
02437 // target - whose time to read
02438 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02439 int RakPeer::GetAveragePing( const AddressOrGUID systemIdentifier )
02440 {
02441         int sum, quantity;
02442         RemoteSystemStruct *remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
02443 
02444         if ( remoteSystem == 0 )
02445                 return -1;
02446 
02447         for ( sum = 0, quantity = 0; quantity < PING_TIMES_ARRAY_SIZE; quantity++ )
02448         {
02449                 if ( remoteSystem->pingAndClockDifferential[ quantity ].pingTime == 65535 )
02450                         break;
02451                 else
02452                         sum += remoteSystem->pingAndClockDifferential[ quantity ].pingTime;
02453         }
02454 
02455         if ( quantity > 0 )
02456                 return sum / quantity;
02457         else
02458                 return -1;
02459 }
02460 
02461 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02462 // Description:
02463 // Returns the last ping time read for the specific player or -1 if none read yet
02464 //
02465 // Parameters:
02466 // target - whose time to read
02467 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02468 int RakPeer::GetLastPing( const AddressOrGUID systemIdentifier ) const
02469 {
02470         RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
02471 
02472         if ( remoteSystem == 0 )
02473                 return -1;
02474 
02475 //      return (int)(remoteSystem->reliabilityLayer.GetAckPing()/(RakNetTimeUS)1000);
02476 
02477         if ( remoteSystem->pingAndClockDifferentialWriteIndex == 0 )
02478                 return remoteSystem->pingAndClockDifferential[ PING_TIMES_ARRAY_SIZE - 1 ].pingTime;
02479         else
02480                 return remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex - 1 ].pingTime;
02481 }
02482 
02483 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02484 // Description:
02485 // Returns the lowest ping time read or -1 if none read yet
02486 //
02487 // Parameters:
02488 // target - whose time to read
02489 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02490 int RakPeer::GetLowestPing( const AddressOrGUID systemIdentifier ) const
02491 {
02492         RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
02493 
02494         if ( remoteSystem == 0 )
02495                 return -1;
02496 
02497         return remoteSystem->lowestPing;
02498 }
02499 
02500 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02501 // Description:
02502 // Ping the remote systems every so often.  This is off by default
02503 // This will work anytime
02504 //
02505 // Parameters:
02506 // doPing - True to start occasional pings.  False to stop them.
02507 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02508 void RakPeer::SetOccasionalPing( bool doPing )
02509 {
02510         occasionalPing = doPing;
02511 }
02512 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02513 // Description:
02514 // Length should be under 400 bytes, as a security measure against flood attacks
02515 // Sets the data to send with an  (LAN server discovery) /(offline ping) response
02516 // See the Ping sample project for how this is used.
02517 // data: a block of data to store, or 0 for none
02518 // length: The length of data in bytes, or 0 for none
02519 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02520 void RakPeer::SetOfflinePingResponse( const char *data, const unsigned int length )
02521 {
02522         RakAssert(length < 400);
02523 
02524         rakPeerMutexes[ offlinePingResponse_Mutex ].Lock();
02525         offlinePingResponse.Reset();
02526 
02527         if ( data && length > 0 )
02528                 offlinePingResponse.Write( data, length );
02529 
02530         rakPeerMutexes[ offlinePingResponse_Mutex ].Unlock();
02531 }
02532 
02533 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02534 // Returns pointers to a copy of the data passed to SetOfflinePingResponse
02535 // \param[out] data A pointer to a copy of the data passed to \a SetOfflinePingResponse()
02536 // \param[out] length A pointer filled in with the length parameter passed to SetOfflinePingResponse()
02537 // \sa SetOfflinePingResponse
02538 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02539 void RakPeer::GetOfflinePingResponse( char **data, unsigned int *length )
02540 {
02541         rakPeerMutexes[ offlinePingResponse_Mutex ].Lock();
02542         *data = (char*) offlinePingResponse.GetData();
02543         *length = (int) offlinePingResponse.GetNumberOfBytesUsed();
02544         rakPeerMutexes[ offlinePingResponse_Mutex ].Unlock();
02545 }
02546 
02547 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02548 // Description:
02549 // Return the unique SystemAddress that represents you on the the network
02550 // Note that unlike in previous versions, this is a struct and is not sequential
02551 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02552 SystemAddress RakPeer::GetInternalID( const SystemAddress systemAddress, const int index ) const
02553 {
02554         if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
02555         {
02556                 return mySystemAddress[index];
02557         }
02558         else
02559         {
02560 #if !defined(_XBOX) && !defined(X360)
02561 //              SystemAddress returnValue;
02562                 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, false, true );
02563                 if (remoteSystem==0)
02564                         return UNASSIGNED_SYSTEM_ADDRESS;
02565 
02566                 return remoteSystem->theirInternalSystemAddress[index];
02567                 /*
02568                 sockaddr_in sa;
02569                 socklen_t len = sizeof(sa);
02570                 if (getsockname(connectionSockets[remoteSystem->connectionSocketIndex], (sockaddr*)&sa, &len)!=0)
02571                         return UNASSIGNED_SYSTEM_ADDRESS;
02572                 returnValue.port=ntohs(sa.sin_port);
02573                 returnValue.binaryAddress=sa.sin_addr.s_addr;
02574                 return returnValue;
02575 */
02576 #else
02577                 return UNASSIGNED_SYSTEM_ADDRESS;
02578 #endif
02579         }
02580 }
02581 
02582 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02583 // Description:
02584 // Return the unique address identifier that represents you on the the network and is based on your external
02585 // IP / port (the IP / port the specified player uses to communicate with you)
02586 // Note that unlike in previous versions, this is a struct and is not sequential
02587 //
02588 // Parameters:
02589 // target: Which remote system you are referring to for your external ID
02590 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02591 SystemAddress RakPeer::GetExternalID( const SystemAddress target ) const
02592 {
02593         unsigned i;
02594         SystemAddress inactiveExternalId;
02595 
02596         inactiveExternalId=UNASSIGNED_SYSTEM_ADDRESS;
02597 
02598         if (target==UNASSIGNED_SYSTEM_ADDRESS)
02599                 return firstExternalID;
02600 
02601         // First check for active connection with this systemAddress
02602         for ( i = 0; i < maximumNumberOfPeers; i++ )
02603         {
02604                 if (remoteSystemList[ i ].systemAddress == target )
02605                 {
02606                         if ( remoteSystemList[ i ].isActive )
02607                                 return remoteSystemList[ i ].myExternalSystemAddress;
02608                         else if (remoteSystemList[ i ].myExternalSystemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
02609                                 inactiveExternalId=remoteSystemList[ i ].myExternalSystemAddress;
02610                 }
02611         }
02612 
02613         return inactiveExternalId;
02614 }
02615 
02616 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02617 
02618 const RakNetGUID& RakPeer::GetGuidFromSystemAddress( const SystemAddress input ) const
02619 {
02620         if (input==UNASSIGNED_SYSTEM_ADDRESS)
02621                 return myGuid;
02622 
02623         if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].systemAddress == input)
02624                 return remoteSystemList[ input.systemIndex ].guid;
02625 
02626         unsigned int i;
02627         for ( i = 0; i < maximumNumberOfPeers; i++ )
02628         {
02629                 if (remoteSystemList[ i ].systemAddress == input )
02630                 {
02631                         return remoteSystemList[ i ].guid;
02632                 }
02633         }
02634 
02635         return UNASSIGNED_RAKNET_GUID;
02636 }
02637 
02638 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02639 
02640 unsigned int RakPeer::GetSystemIndexFromGuid( const RakNetGUID input ) const
02641 {
02642         if (input==UNASSIGNED_RAKNET_GUID)
02643                 return (unsigned int) -1;
02644 
02645         if (input==myGuid)
02646                 return (unsigned int) -1;
02647 
02648         if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
02649                 return input.systemIndex;
02650 
02651         unsigned int i;
02652         for ( i = 0; i < maximumNumberOfPeers; i++ )
02653         {
02654                 if (remoteSystemList[ i ].guid == input )
02655                 {
02656                         return i;
02657                 }
02658         }
02659 
02660         return (unsigned int) -1;
02661 }
02662 
02663 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02664 
02665 SystemAddress RakPeer::GetSystemAddressFromGuid( const RakNetGUID input ) const
02666 {
02667         if (input==UNASSIGNED_RAKNET_GUID)
02668                 return UNASSIGNED_SYSTEM_ADDRESS;
02669 
02670         if (input==myGuid)
02671                 return GetInternalID(UNASSIGNED_SYSTEM_ADDRESS);
02672 
02673         if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
02674                 return remoteSystemList[ input.systemIndex ].systemAddress;
02675 
02676         unsigned int i;
02677         for ( i = 0; i < maximumNumberOfPeers; i++ )
02678         {
02679                 if (remoteSystemList[ i ].guid == input )
02680                 {
02681                         return remoteSystemList[ i ].systemAddress;
02682                 }
02683         }
02684 
02685         return UNASSIGNED_SYSTEM_ADDRESS;
02686 }
02687 
02688 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02689 // Set the time, in MS, to use before considering ourselves disconnected after not being able to deliver a reliable packet
02690 // \param[in] time Time, in MS
02691 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02692 void RakPeer::SetTimeoutTime( RakNetTime timeMS, const SystemAddress target )
02693 {
02694         if (target==UNASSIGNED_SYSTEM_ADDRESS)
02695         {
02696                 defaultTimeoutTime=timeMS;
02697 
02698                 unsigned i;
02699                 for ( i = 0; i < maximumNumberOfPeers; i++ )
02700                 {
02701                         if (remoteSystemList[ i ].isActive)
02702                         {
02703                                 if ( remoteSystemList[ i ].isActive )
02704                                         remoteSystemList[ i ].reliabilityLayer.SetTimeoutTime(timeMS);
02705                         }
02706                 }
02707         }
02708         else
02709         {
02710                 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
02711 
02712                 if ( remoteSystem != 0 )
02713                         remoteSystem->reliabilityLayer.SetTimeoutTime(timeMS);
02714         }
02715 }
02716 
02717 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02718 
02719 RakNetTime RakPeer::GetTimeoutTime( const SystemAddress target )
02720 {
02721         if (target==UNASSIGNED_SYSTEM_ADDRESS)
02722         {
02723                 return defaultTimeoutTime;
02724         }
02725         else
02726         {
02727                 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
02728 
02729                 if ( remoteSystem != 0 )
02730                         remoteSystem->reliabilityLayer.GetTimeoutTime();
02731         }
02732         return defaultTimeoutTime;
02733 }
02734 
02735 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02736 // Description:
02737 // Change the MTU size in order to improve performance when sending large packets
02738 // This can only be called when not connected.
02739 // A too high of value will cause packets not to arrive at worst and be fragmented at best.
02740 // A too low of value will split packets unnecessarily.
02741 //
02742 // Parameters:
02743 // size: Set according to the following table:
02744 // 1500. The largest Ethernet packet size
02745 // This is the typical setting for non-PPPoE, non-VPN connections. The default value for NETGEAR routers, adapters and switches.
02746 // 1492. The size PPPoE prefers.
02747 // 1472. Maximum size to use for pinging. (Bigger packets are fragmented.)
02748 // 1468. The size DHCP prefers.
02749 // 1460. Usable by AOL if you don't have large email attachments, etc.
02750 // 1430. The size VPN and PPTP prefer.
02751 // 1400. Maximum size for AOL DSL.
02752 // 576. Typical value to connect to dial-up ISPs. (Default)
02753 //
02754 // Returns:
02755 // False on failure (we are connected).  True on success.  Maximum allowed size is MAXIMUM_MTU_SIZE
02756 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02757 /*
02758 bool RakPeer::SetMTUSize( int size, const SystemAddress target )
02759 {
02760         if ( IsActive() )
02761                 return false;
02762 
02763         if ( size < 512 )
02764                 size = 512;
02765         else if ( size > MAXIMUM_MTU_SIZE )
02766                 size = MAXIMUM_MTU_SIZE;
02767 
02768         if (target==UNASSIGNED_SYSTEM_ADDRESS)
02769         {
02770                 defaultMTUSize = size;
02771 
02772                 int i;
02773                 // Active connections take priority.  But if there are no active connections, return the first systemAddress match found
02774                 for ( i = 0; i < maximumNumberOfPeers; i++ )
02775                 {
02776                         remoteSystemList[i].MTUSize=size;
02777                 }
02778         }
02779         else
02780         {
02781                 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(target, false, true);
02782                 if (rss)
02783                         rss->MTUSize=size;
02784         }
02785 
02786         return true;
02787         }
02788 */
02789 
02790 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02791 // Description:
02792 // Returns the current MTU size
02793 //
02794 // Returns:
02795 // The MTU sized specified in SetMTUSize
02796 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02797 int RakPeer::GetMTUSize( const SystemAddress target ) const
02798 {
02799         if (target!=UNASSIGNED_SYSTEM_ADDRESS)
02800         {
02801                 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(target, false, true);
02802                 if (rss)
02803                         return rss->MTUSize;
02804         }
02805         return defaultMTUSize;
02806 }
02807 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02808 // Description:
02809 // Returns the number of IP addresses we have
02810 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02811 unsigned int RakPeer::GetNumberOfAddresses( void )
02812 {
02813 #if !defined(_XBOX) && !defined(X360)
02814         int i = 0;
02815 
02816         while ( ipList[ i ][ 0 ] )
02817                 i++;
02818 
02819         return i;
02820 #else
02821         RakAssert(0);
02822         return 0;
02823 #endif
02824 }
02825 
02826 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02827 // Returns an IP address at index 0 to GetNumberOfAddresses-1
02828 // \param[in] index index into the list of IP addresses
02829 // \return The local IP address at this index
02830 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02831 const char* RakPeer::GetLocalIP( unsigned int index )
02832 {
02833         if (IsActive()==false)
02834         {
02835         // Fill out ipList structure
02836 #if !defined(_XBOX) && !defined(X360)
02837         memset( ipList, 0, sizeof( char ) * 16 * MAXIMUM_NUMBER_OF_INTERNAL_IDS );
02838         SocketLayer::Instance()->GetMyIP( ipList,binaryAddresses );
02839 #endif
02840         }
02841 
02842 #if !defined(_XBOX) && !defined(X360)
02843         return ipList[ index ];
02844 #else
02845         RakAssert(0);
02846         return 0;
02847 #endif
02848 }
02849 
02850 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02851 // Is this a local IP?
02852 // \param[in] An IP address to check
02853 // \return True if this is one of the IP addresses returned by GetLocalIP
02854 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02855 bool RakPeer::IsLocalIP( const char *ip )
02856 {
02857         if (ip==0 || ip[0]==0)
02858                 return false;
02859 
02860 #if !defined(_XBOX) && !defined(X360)
02861         if (strcmp(ip, "127.0.0.1")==0)
02862                 return true;
02863 
02864         int num = GetNumberOfAddresses();
02865         int i;
02866         for (i=0; i < num; i++)
02867         {
02868                 if (strcmp(ip, GetLocalIP(i))==0)
02869                         return true;
02870         }
02871 #else
02872         if (strcmp(ip, "2130706433")==0) // 127.0.0.1 big endian
02873                 return true;
02874 #endif
02875         return false;
02876 }
02877 
02878 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02879 // Description:
02880 // Allow or disallow connection responses from any IP. Normally this should be false, but may be necessary
02881 // when connection to servers with multiple IP addresses
02882 //
02883 // Parameters:
02884 // allow - True to allow this behavior, false to not allow.  Defaults to false.  Value persists between connections
02885 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02886 void RakPeer::AllowConnectionResponseIPMigration( bool allow )
02887 {
02888         allowConnectionResponseIPMigration = allow;
02889 }
02890 
02891 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02892 // Description:
02893 // Sends a message ID_ADVERTISE_SYSTEM to the remote unconnected system.
02894 // This will tell the remote system our external IP outside the LAN, and can be used for NAT punch through
02895 //
02896 // Requires:
02897 // The sender and recipient must already be started via a successful call to Initialize
02898 //
02899 // host: Either a dotted IP address or a domain name
02900 // remotePort: Which port to connect to on the remote machine.
02901 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02902 bool RakPeer::AdvertiseSystem( const char *host, unsigned short remotePort, const char *data, int dataLength, unsigned connectionSocketIndex )
02903 {
02904         RakNet::BitStream bs;
02905         bs.Write((MessageID)ID_ADVERTISE_SYSTEM);
02906         bs.WriteAlignedBytes((const unsigned char*) data,dataLength);
02907         return SendOutOfBand(host, remotePort, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), connectionSocketIndex );
02908 }
02909 
02910 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02911 // Controls how often to return ID_DOWNLOAD_PROGRESS for large message downloads.
02912 // ID_DOWNLOAD_PROGRESS is returned to indicate a new partial message chunk, roughly the MTU size, has arrived
02913 // As it can be slow or cumbersome to get this notification for every chunk, you can set the interval at which it is returned.
02914 // Defaults to 0 (never return this notification)
02915 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02916 void RakPeer::SetSplitMessageProgressInterval(int interval)
02917 {
02918         RakAssert(interval>=0);
02919         splitMessageProgressInterval=interval;
02920         for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
02921                 remoteSystemList[ i ].reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval);
02922 }
02923 
02924 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02925 // Returns what was passed to SetSplitMessageProgressInterval()
02926 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02927 int RakPeer::GetSplitMessageProgressInterval(void) const
02928 {
02929         return splitMessageProgressInterval;
02930 }
02931 
02932 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02933 // Set how long to wait before giving up on sending an unreliable message
02934 // Useful if the network is clogged up.
02935 // Set to 0 or less to never timeout.  Defaults to 0.
02936 // timeoutMS How many ms to wait before simply not sending an unreliable message.
02937 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02938 void RakPeer::SetUnreliableTimeout(RakNetTime timeoutMS)
02939 {
02940         unreliableTimeout=timeoutMS;
02941         for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
02942                 remoteSystemList[ i ].reliabilityLayer.SetUnreliableTimeout(unreliableTimeout);
02943 }
02944 
02945 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02946 // Send a message to host, with the IP socket option TTL set to 3
02947 // This message will not reach the host, but will open the router.
02948 // Used for NAT-Punchthrough
02949 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02950 void RakPeer::SendTTL( const char* host, unsigned short remotePort, int ttl, unsigned connectionSocketIndex )
02951 {
02952         char fakeData[2];
02953         fakeData[0]=0;
02954         fakeData[1]=1;
02955         unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
02956         SocketLayer::Instance()->SendToTTL( socketList[realIndex]->s, (char*)fakeData, 2, (char*) host, remotePort, ttl );
02957 }
02958 
02959 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02960 // Description:
02961 // Enables or disables our tracking of bytes input to and output from the network.
02962 // This is required to get a frequency table, which is used to generate a new compression layer.
02963 // You can call this at any time - however you SHOULD only call it when disconnected.  Otherwise you will only track
02964 // part of the values sent over the network.
02965 // This value persists between connect calls and defaults to false (no frequency tracking)
02966 //
02967 // Parameters:
02968 // doCompile - true to track bytes.  Defaults to false
02969 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02970 void RakPeer::SetCompileFrequencyTable( bool doCompile )
02971 {
02972         trackFrequencyTable = doCompile;
02973 }
02974 
02975 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02976 // Description:
02977 // Returns the frequency of outgoing bytes into outputFrequencyTable
02978 // The purpose is to save to file as either a master frequency table from a sample game session for passing to
02979 // GenerateCompressionLayer(false)
02980 // You should only call this when disconnected.
02981 // Requires that you first enable data frequency tracking by calling SetCompileFrequencyTable(true)
02982 //
02983 // Parameters:
02984 // outputFrequencyTable (out): The frequency of each corresponding byte
02985 //
02986 // Returns:
02987 // Ffalse (failure) if connected or if frequency table tracking is not enabled.  Otherwise true (success)
02988 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
02989 bool RakPeer::GetOutgoingFrequencyTable( unsigned int outputFrequencyTable[ 256 ] )
02990 {
02991         if ( IsActive() )
02992                 return false;
02993 
02994         if ( trackFrequencyTable == false )
02995                 return false;
02996 
02997         memcpy( outputFrequencyTable, frequencyTable, sizeof( unsigned int ) * 256 );
02998 
02999         return true;
03000 }
03001 
03002 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03003 // Description:
03004 // Generates the compression layer from the input frequency table.
03005 // You should call this twice - once with inputLayer as true and once as false.
03006 // The frequency table passed here with inputLayer=true should match the frequency table on the recipient with inputLayer=false.
03007 // Likewise, the frequency table passed here with inputLayer=false should match the frequency table on the recipient with inputLayer=true
03008 // Calling this function when there is an existing layer will overwrite the old layer
03009 // You should only call this when disconnected
03010 //
03011 // Parameters:
03012 // inputFrequencyTable: The frequency table returned from GetSendFrequencyTable(...)
03013 // inputLayer - Whether inputFrequencyTable represents incoming data from other systems (true) or outgoing data from this system (false)
03014 //
03015 // Returns:
03016 // False on failure (we are connected).  True otherwise
03017 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03018 bool RakPeer::GenerateCompressionLayer( unsigned int inputFrequencyTable[ 256 ], bool inputLayer )
03019 {
03020         if ( IsActive() )
03021                 return false;
03022 
03023         DeleteCompressionLayer( inputLayer );
03024 
03025         if ( inputLayer )
03026         {
03027                 inputTree = RakNet::OP_NEW<HuffmanEncodingTree>( __FILE__, __LINE__ );
03028                 inputTree->GenerateFromFrequencyTable( inputFrequencyTable );
03029         }
03030 
03031         else
03032         {
03033                 outputTree = RakNet::OP_NEW<HuffmanEncodingTree>( __FILE__, __LINE__ );
03034                 outputTree->GenerateFromFrequencyTable( inputFrequencyTable );
03035         }
03036 
03037         return true;
03038 }
03039 
03040 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03041 // Description:
03042 // Deletes the output or input layer as specified.  This is not necessary to call and is only valuable for freeing memory
03043 // You should only call this when disconnected
03044 //
03045 // Parameters:
03046 // inputLayer - Specifies the corresponding compression layer generated by GenerateCompressionLayer.
03047 //
03048 // Returns:
03049 // False on failure (we are connected).  True otherwise
03050 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03051 bool RakPeer::DeleteCompressionLayer( bool inputLayer )
03052 {
03053         if ( IsActive() )
03054                 return false;
03055 
03056         if ( inputLayer )
03057         {
03058                 if ( inputTree )
03059                 {
03060                         RakNet::OP_DELETE(inputTree, __FILE__, __LINE__);
03061                         inputTree = 0;
03062                 }
03063         }
03064 
03065         else
03066         {
03067                 if ( outputTree )
03068                 {
03069                         RakNet::OP_DELETE(outputTree, __FILE__, __LINE__);
03070                         outputTree = 0;
03071                 }
03072         }
03073 
03074         return true;
03075 }
03076 
03077 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03078 // Returns:
03079 // The compression ratio.  A low compression ratio is good.  Compression is for outgoing data
03080 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03081 float RakPeer::GetCompressionRatio( void ) const
03082 {
03083         if ( rawBytesSent > 0 )
03084         {
03085                 return ( float ) compressedBytesSent / ( float ) rawBytesSent;
03086         }
03087 
03088         else
03089                 return 0.0f;
03090 }
03091 
03092 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03093 // Returns:
03094 // The decompression ratio.  A high decompression ratio is good.  Decompression is for incoming data
03095 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03096 float RakPeer::GetDecompressionRatio( void ) const
03097 {
03098         if ( rawBytesReceived > 0 )
03099         {
03100                 return ( float ) compressedBytesReceived / ( float ) rawBytesReceived;
03101         }
03102 
03103         else
03104                 return 0.0f;
03105 }
03106 
03107 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03108 // Attatches a Plugin interface to run code automatically on message receipt in the Receive call
03109 //
03110 // \param messageHandler Pointer to a plugin to attach
03111 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03112 void RakPeer::AttachPlugin( PluginInterface2 *plugin )
03113 {
03114         if (messageHandlerList.GetIndexOf(plugin)==MAX_UNSIGNED_LONG)
03115         {
03116                 plugin->SetRakPeerInterface(this);
03117                 plugin->OnAttach();
03118                 messageHandlerList.Insert(plugin, __FILE__, __LINE__);
03119         }
03120 }
03121 
03122 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03123 // Detaches a Plugin interface to run code automatically on message receipt
03124 //
03125 // \param messageHandler Pointer to a plugin to detach
03126 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03127 void RakPeer::DetachPlugin( PluginInterface2 *plugin )
03128 {
03129         if (plugin==0)
03130                 return;
03131 
03132         unsigned int index;
03133         index = messageHandlerList.GetIndexOf(plugin);
03134         if (index!=MAX_UNSIGNED_LONG)
03135         {
03136                 // Unordered list so delete from end for speed
03137                 messageHandlerList[index]=messageHandlerList[messageHandlerList.Size()-1];
03138                 messageHandlerList.RemoveFromEnd();
03139                 plugin->OnDetach();
03140                 plugin->SetRakPeerInterface(0);
03141         }
03142 }
03143 
03144 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03145 // Put a packet back at the end of the receive queue in case you don't want to deal with it immediately
03146 //
03147 // packet The packet you want to push back.
03148 // pushAtHead True to push the packet so that the next receive call returns it.  False to push it at the end of the queue (obviously pushing it at the end makes the packets out of order)
03149 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03150 void RakPeer::PushBackPacket( Packet *packet, bool pushAtHead)
03151 {
03152         if (packet==0)
03153                 return;
03154 
03155         unsigned i;
03156         for (i=0; i < messageHandlerList.Size(); i++)
03157                 messageHandlerList[i]->OnPushBackPacket((const char*) packet->data, packet->bitSize, packet->systemAddress);
03158 
03159         packetReturnMutex.Lock();
03160         if (pushAtHead)
03161                 packetReturnQueue.PushAtHead(packet,0,__FILE__,__LINE__);
03162         else
03163                 packetReturnQueue.Push(packet,__FILE__,__LINE__);
03164         packetReturnMutex.Unlock();
03165 }
03166 
03167 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03168 void RakPeer::SetRouterInterface( RouterInterface *routerInterface )
03169 {
03170         router=routerInterface;
03171 }
03172 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03173 void RakPeer::RemoveRouterInterface( RouterInterface *routerInterface )
03174 {
03175         if (router==routerInterface)
03176                 router=0;
03177 }
03178 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03179 void RakPeer::ChangeSystemAddress(RakNetGUID guid, SystemAddress systemAddress)
03180 {
03181         BufferedCommandStruct *bcs;
03182 
03183 #ifdef _RAKNET_THREADSAFE
03184         bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
03185 #else
03186         bcs=bufferedCommands.WriteLock();
03187 #endif
03188         bcs->data = 0;
03189         bcs->systemIdentifier.systemAddress=systemAddress;
03190         bcs->systemIdentifier.rakNetGuid=guid;
03191         bcs->command=BufferedCommandStruct::BCS_CHANGE_SYSTEM_ADDRESS;
03192 #ifdef _RAKNET_THREADSAFE
03193         bufferedCommands.Push(bcs);
03194 #else
03195         bufferedCommands.WriteUnlock();
03196 #endif
03197 }
03198 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03199 Packet* RakPeer::AllocatePacket(unsigned dataSize)
03200 {
03201         return AllocPacket(dataSize, __FILE__, __LINE__);
03202 }
03203 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03204 RakNetSmartPtr<RakNetSocket> RakPeer::GetSocket( const SystemAddress target )
03205 {
03206         // Send a query to the thread to get the socket, and return when we got it
03207         BufferedCommandStruct *bcs;
03208 #ifdef _RAKNET_THREADSAFE
03209         bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
03210         bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
03211         bcs->systemIdentifier=target;
03212         bcs->data=0;
03213         bufferedCommands.Push(bcs);
03214 #else
03215         bcs=bufferedCommands.WriteLock();
03216         bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
03217         bcs->systemIdentifier=target;
03218         bcs->data=0;
03219         bufferedCommands.WriteUnlock();
03220 #endif
03221 
03222         // Block up to one second to get the socket, although it should actually take virtually no time
03223         SocketQueryOutput *sqo;
03224         RakNetTime stopWaiting = RakNet::GetTime()+1000;
03225         DataStructures::List<RakNetSmartPtr<RakNetSocket> > output;
03226         while (RakNet::GetTime() < stopWaiting)
03227         {
03228                 if (isMainLoopThreadActive==false)
03229                         return RakNetSmartPtr<RakNetSocket>();
03230 
03231                 RakSleep(0);
03232 
03233 #ifdef _RAKNET_THREADSAFE
03234                 sqo = socketQueryOutput.Pop();
03235                 if (sqo)
03236                 {
03237                         output=sqo->sockets;
03238                         sqo->sockets.Clear(false, __FILE__, __LINE__);
03239                         socketQueryOutput.Deallocate(sqo, __FILE__,__LINE__);
03240                         if (output.Size())
03241                                 return output[0];
03242                         break;
03243                 }
03244 #else
03245                 sqo = socketQueryOutput.ReadLock();
03246                 if (sqo)
03247                 {
03248                         output=sqo->sockets;
03249                         sqo->sockets.Clear(false, __FILE__, __LINE__);
03250                         socketQueryOutput.ReadUnlock();
03251                         if (output.Size())
03252                                 return output[0];
03253                         break;
03254                 }
03255 #endif          
03256         }
03257         return RakNetSmartPtr<RakNetSocket>();
03258 }
03259 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03260 void RakPeer::GetSockets( DataStructures::List<RakNetSmartPtr<RakNetSocket> > &sockets )
03261 {
03262         sockets.Clear(false, __FILE__, __LINE__);
03263 
03264         // Send a query to the thread to get the socket, and return when we got it
03265         BufferedCommandStruct *bcs;
03266 
03267 #ifdef _RAKNET_THREADSAFE
03268         bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
03269         bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
03270         bcs->systemIdentifier=UNASSIGNED_SYSTEM_ADDRESS;
03271         bcs->data=0;
03272         bufferedCommands.Push(bcs);
03273 #else
03274         bcs=bufferedCommands.WriteLock();
03275         bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
03276         bcs->systemIdentifier=UNASSIGNED_SYSTEM_ADDRESS;
03277         bcs->data=0;
03278         bufferedCommands.WriteUnlock();
03279 #endif
03280 
03281         // Block up to one second to get the socket, although it should actually take virtually no time
03282         SocketQueryOutput *sqo;
03283         RakNetTime stopWaiting = RakNet::GetTime()+1000;
03284         RakNetSmartPtr<RakNetSocket> output;
03285         while (RakNet::GetTime() < stopWaiting)
03286         {
03287                 if (isMainLoopThreadActive==false)
03288                         return;
03289 
03290                 RakSleep(0);
03291 
03292 #ifdef _RAKNET_THREADSAFE
03293                 sqo = socketQueryOutput.Pop();
03294                 if (sqo)
03295                 {
03296                         sockets=sqo->sockets;
03297                         sqo->sockets.Clear(false, __FILE__, __LINE__);
03298                         socketQueryOutput.Deallocate(sqo, __FILE__,__LINE__);
03299                         return;
03300                 }
03301 #else
03302                 sqo = socketQueryOutput.ReadLock();
03303                 if (sqo)
03304                 {
03305                         sockets=sqo->sockets;
03306                         sqo->sockets.Clear(false, __FILE__, __LINE__);
03307                         socketQueryOutput.ReadUnlock();
03308                         return;
03309                 }
03310 #endif  
03311         }
03312         return;
03313 }
03314 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03315 // Adds simulated ping and packet loss to the outgoing data flow.
03316 // To simulate bi-directional ping and packet loss, you should call this on both the sender and the recipient, with half the total ping and maxSendBPS value on each.
03317 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03318 void RakPeer::ApplyNetworkSimulator( float packetloss, unsigned short minExtraPing, unsigned short extraPingVariance)
03319 {
03320 #ifdef _DEBUG
03321         if (remoteSystemList)
03322         {
03323                 unsigned short i;
03324                 for (i=0; i < maximumNumberOfPeers; i++)
03325                 //for (i=0; i < remoteSystemListSize; i++)
03326                         remoteSystemList[i].reliabilityLayer.ApplyNetworkSimulator(packetloss, minExtraPing, extraPingVariance);
03327         }
03328 
03329         _packetloss=packetloss;
03330         _minExtraPing=minExtraPing;
03331         _extraPingVariance=extraPingVariance;
03332 #endif
03333 }
03334 
03335 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03336 
03337 void RakPeer::SetPerConnectionOutgoingBandwidthLimit( unsigned maxBitsPerSecond )
03338 {
03339         maxOutgoingBPS=maxBitsPerSecond;
03340 }
03341 
03342 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03343 // Returns if you previously called ApplyNetworkSimulator
03344 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03345 bool RakPeer::IsNetworkSimulatorActive( void )
03346 {
03347 #ifdef _DEBUG
03348         return _packetloss>0 || _minExtraPing>0 || _extraPingVariance>0;
03349 #else
03350         return false;
03351 #endif
03352 }
03353 /*
03354 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03355 // Have RakNet use a socket you created yourself
03356 // The socket should not be in use - it is up to you to either shutdown or close the connections using it. Otherwise existing connections on that socket will eventually disconnect
03357 // This socket will be forgotten after calling Shutdown(), so rebind again if you need to.
03358 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03359 void RakPeer::UseUserSocket( int socket, bool haveRakNetCloseSocket, unsigned connectionSocketIndex)
03360 {
03361         BufferedCommandStruct *bcs;
03362 #ifdef _RAKNET_THREADSAFE
03363         rakPeerMutexes[bufferedCommands_Mutex].Lock();
03364 #endif
03365         bcs=bufferedCommands.WriteLock();
03366         bcs->command=BufferedCommandStruct::BCS_USE_USER_SOCKET;
03367         bcs->data=0;
03368         bcs->socket=socket;
03369         bcs->haveRakNetCloseSocket=haveRakNetCloseSocket;
03370         bcs->connectionSocketIndex=connectionSocketIndex;
03371         bufferedCommands.WriteUnlock();
03372 #ifdef _RAKNET_THREADSAFE
03373         rakPeerMutexes[bufferedCommands_Mutex].Unlock();
03374 #endif
03375 }
03376 
03377 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03378 // Have RakNet recreate a socket using a different port.
03379 // The socket should not be in use - it is up to you to either shutdown or close the connections using it. Otherwise existing connections on that socket will eventually disconnect
03380 // \param[in] connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on.
03381 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03382 void RakPeer::RebindSocketAddress(unsigned connectionSocketIndex, SocketDescriptor &sd)
03383 {
03384         BufferedCommandStruct *bcs;
03385 #ifdef _RAKNET_THREADSAFE
03386         rakPeerMutexes[bufferedCommands_Mutex].Lock();
03387 #endif
03388         bcs=bufferedCommands.WriteLock();
03389         bcs->command=BufferedCommandStruct::BCS_REBIND_SOCKET_ADDRESS;
03390         bcs->data=(char*) rakMalloc_Ex(sizeof(sd.hostAddress), __FILE__, __LINE__);
03391         memcpy(bcs->data, sd.hostAddress, sizeof(sd.hostAddress));
03392         bcs->port=sd.port;
03393         bcs->connectionSocketIndex=connectionSocketIndex;
03394         bcs->socketType=sd.socketType;
03395         bufferedCommands.WriteUnlock();
03396 #ifdef _RAKNET_THREADSAFE
03397         rakPeerMutexes[bufferedCommands_Mutex].Unlock();
03398 #endif
03399 }
03400 */
03401 
03402 
03403 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03404 // For internal use
03405 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03406 char *RakPeer::GetRPCString( const char *data, const BitSize_t bitSize, const SystemAddress systemAddress)
03407 {
03408         bool nameIsEncoded=false;
03409         static char uniqueIdentifier[256];
03410         RPCIndex rpcIndex;
03411         RPCMap *_rpcMap;
03412         RakNet::BitStream rpcDecode((unsigned char*) data, BITS_TO_BYTES(bitSize), false);
03413         rpcDecode.IgnoreBits(8);
03414         if (data[0]==ID_TIMESTAMP)
03415                 rpcDecode.IgnoreBits(sizeof(unsigned char)+sizeof(RakNetTime));
03416         rpcDecode.Read(nameIsEncoded);
03417         if (nameIsEncoded)
03418         {
03419                 stringCompressor->DecodeString((char*)uniqueIdentifier, 256, &rpcDecode);
03420         }
03421         else
03422         {
03423                 rpcDecode.ReadCompressed( rpcIndex );
03424                 RPCNode *rpcNode;
03425 
03426                 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
03427                         _rpcMap=&rpcMap;
03428                 else
03429                 {
03430                         RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(systemAddress, false, true);
03431                         if (rss)
03432                                 _rpcMap=&(rss->rpcMap);
03433                         else
03434                                 _rpcMap=0;
03435                 }
03436 
03437                 if (_rpcMap)
03438                         rpcNode = _rpcMap->GetNodeFromIndex(rpcIndex);
03439                 else
03440                         rpcNode=0;
03441 
03442                 if (_rpcMap && rpcNode)
03443                         strcpy((char*)uniqueIdentifier, rpcNode->uniqueIdentifier);
03444                 else
03445                         strcpy((char*)uniqueIdentifier, "[UNKNOWN]");
03446         }
03447 
03448         return uniqueIdentifier;
03449 }
03450 
03451 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03452 void RakPeer::WriteOutOfBandHeader(RakNet::BitStream *bitStream)
03453 {
03454         bitStream->Write((MessageID)ID_OUT_OF_BAND_INTERNAL);
03455         bitStream->Write(myGuid);
03456         bitStream->WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
03457 }
03458 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03459 void RakPeer::SetUserUpdateThread(void (*_userUpdateThreadPtr)(RakPeerInterface *, void *), void *_userUpdateThreadData)
03460 {
03461         userUpdateThreadPtr=_userUpdateThreadPtr;
03462         userUpdateThreadData=_userUpdateThreadData;
03463 }
03464 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03465 bool RakPeer::SendOutOfBand(const char *host, unsigned short remotePort, const char *data, BitSize_t dataLength, unsigned connectionSocketIndex )
03466 {
03467         if ( IsActive() == false )
03468                 return false;
03469 
03470         if (host==0  || host[0]==0)
03471                 return false;
03472 
03473         // If this assert hits then Startup wasn't called or the call failed.
03474         RakAssert(connectionSocketIndex < socketList.Size());
03475 
03476         // This is a security measure.  Don't send data longer than this value
03477         RakAssert(dataLength <= MAX_OFFLINE_DATA_LENGTH);
03478 
03479         if ( NonNumericHostString( host ) )
03480         {
03481                 host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host );
03482 
03483                 if (host==0)
03484                         return false;
03485         }
03486 
03487         if (host==0)
03488                 return false;
03489 
03490         SystemAddress systemAddress;
03491         systemAddress.SetBinaryAddress(host);
03492         systemAddress.port=remotePort;
03493 
03494         // 34 bytes
03495         RakNet::BitStream bitStream;
03496         WriteOutOfBandHeader(&bitStream);
03497         
03498         if (dataLength>0)
03499         {
03500                 bitStream.Write(data, dataLength);
03501         }
03502         unsigned i;
03503         for (i=0; i < messageHandlerList.Size(); i++)
03504                 messageHandlerList[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
03505         unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
03506         SocketLayer::Instance()->SendTo( socketList[realIndex]->s, (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), ( char* ) host, remotePort, socketList[realIndex]->remotePortRakNetWasStartedOn_PS3 );
03507 
03508         return true;
03509 }
03510 
03511 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03512 RakNetStatistics * const RakPeer::GetStatistics( const SystemAddress systemAddress, RakNetStatistics *rns )
03513 {
03514         static RakNetStatistics staticStatistics;
03515         RakNetStatistics *systemStats;
03516         if (rns==0)
03517                 systemStats=&staticStatistics;
03518         else
03519                 systemStats=rns;
03520 
03521         if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
03522         {
03523                 bool firstWrite=false;
03524                 // Return a crude sum
03525                 for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
03526                 {
03527                         if (remoteSystemList[ i ].isActive)
03528                         {
03529                                 RakNetStatistics rnsTemp;
03530                                 remoteSystemList[ i ].reliabilityLayer.GetStatistics(&rnsTemp);
03531 
03532                                 if (firstWrite==false)
03533                                 {
03534                                         memcpy(systemStats, &rnsTemp, sizeof(RakNetStatistics));
03535                                         firstWrite=true;
03536                                 }
03537                                 else
03538                                         (*systemStats)+=rnsTemp;
03539                         }
03540                 }
03541                 return systemStats;
03542         }
03543         else
03544         {
03545                 RemoteSystemStruct * rss;
03546                 rss = GetRemoteSystemFromSystemAddress( systemAddress, false, false );
03547                 if ( rss && endThreads==false )
03548                 {
03549                         rss->reliabilityLayer.GetStatistics(systemStats);
03550                         return systemStats;
03551                 }
03552         }
03553 
03554         return 0;
03555 }
03556 
03557 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03558 bool RakPeer::GetStatistics( const int index, RakNetStatistics *rns )
03559 {
03560         if (index < maximumNumberOfPeers && remoteSystemList[ index ].isActive)
03561         {
03562                 remoteSystemList[ index ].reliabilityLayer.GetStatistics(rns);
03563                 return true;
03564         }
03565         return false;
03566 }
03567 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03568 unsigned int RakPeer::GetReceiveBufferSize(void)
03569 {
03570         unsigned int size;
03571         packetReturnMutex.Lock();
03572         size=packetReturnQueue.Size();
03573         packetReturnMutex.Unlock();
03574         return size;
03575 }
03576 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03577 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread ) const
03578 {
03579         unsigned i;
03580 
03581         if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
03582                 return -1;
03583 
03584         if (systemAddress.systemIndex!=(SystemIndex)-1 && systemAddress.systemIndex < maximumNumberOfPeers && remoteSystemList[systemAddress.systemIndex].systemAddress==systemAddress && remoteSystemList[ systemAddress.systemIndex ].isActive)
03585                 return systemAddress.systemIndex;
03586         
03587         if (calledFromNetworkThread)
03588         {
03589                 return GetRemoteSystemIndex(systemAddress);
03590         }
03591         else
03592         {
03593                 // remoteSystemList in user and network thread
03594                 for ( i = 0; i < maximumNumberOfPeers; i++ )
03595                         if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].systemAddress == systemAddress )
03596                                 return i;
03597 
03598                 // If no active results found, try previously active results.
03599                 for ( i = 0; i < maximumNumberOfPeers; i++ )
03600                         if ( remoteSystemList[ i ].systemAddress == systemAddress )
03601                                 return i;
03602         }
03603 
03604         return -1;
03605 }
03606 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03607 int RakPeer::GetIndexFromGuid( const RakNetGUID guid )
03608 {
03609         unsigned i;
03610 
03611         if ( guid == UNASSIGNED_RAKNET_GUID )
03612                 return -1;
03613 
03614         if (guid.systemIndex!=(SystemIndex)-1 && guid.systemIndex < maximumNumberOfPeers && remoteSystemList[guid.systemIndex].guid==guid && remoteSystemList[ guid.systemIndex ].isActive)
03615                 return guid.systemIndex;
03616 
03617         // remoteSystemList in user and network thread
03618         for ( i = 0; i < maximumNumberOfPeers; i++ )
03619                 if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].guid == guid )
03620                         return i;
03621 
03622         // If no active results found, try previously active results.
03623         for ( i = 0; i < maximumNumberOfPeers; i++ )
03624                 if ( remoteSystemList[ i ].guid == guid )
03625                         return i;
03626 
03627         return -1;
03628 }
03629 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03630 bool RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime )
03631 {
03632         RakAssert(passwordDataLength <= 256);
03633         RakAssert(remotePort!=0);
03634         SystemAddress systemAddress;
03635         systemAddress.SetBinaryAddress(host);
03636         systemAddress.port=remotePort;
03637 
03638         // Already connected?
03639         if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
03640                 return false;
03641 
03642         //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), __FILE__, __LINE__);
03643         RequestedConnectionStruct *rcs = RakNet::OP_NEW<RequestedConnectionStruct>(__FILE__,__LINE__);
03644 
03645         rcs->systemAddress=systemAddress;
03646         rcs->nextRequestTime=RakNet::GetTime();
03647         rcs->requestsMade=0;
03648         rcs->data=0;
03649         rcs->extraData=extraData;
03650         rcs->socketIndex=connectionSocketIndex;
03651         rcs->actionToTake=RequestedConnectionStruct::CONNECT;
03652         rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
03653         rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
03654         memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
03655         rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
03656         rcs->timeoutTime=timeoutTime;
03657 
03658         // Return false if already pending, else push on queue
03659         unsigned int i=0;
03660         requestedConnectionQueueMutex.Lock();
03661         for (; i < requestedConnectionQueue.Size(); i++)
03662         {
03663                 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
03664                 {
03665                         requestedConnectionQueueMutex.Unlock();
03666                         RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
03667                         return false;
03668                 }
03669         }
03670         requestedConnectionQueue.Push(rcs, __FILE__, __LINE__ );
03671         requestedConnectionQueueMutex.Unlock();
03672 
03673         return true;
03674 }
03675 bool RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, RakNetTime timeoutTime, RakNetSmartPtr<RakNetSocket> socket )
03676 {
03677         RakAssert(passwordDataLength <= 256);
03678         SystemAddress systemAddress;
03679         systemAddress.SetBinaryAddress(host);
03680         systemAddress.port=remotePort;
03681 
03682         // Already connected?
03683         if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
03684                 return false;
03685 
03686         //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), __FILE__, __LINE__);
03687         RequestedConnectionStruct *rcs = RakNet::OP_NEW<RequestedConnectionStruct>(__FILE__,__LINE__);
03688 
03689         rcs->systemAddress=systemAddress;
03690         rcs->nextRequestTime=RakNet::GetTime();
03691         rcs->requestsMade=0;
03692         rcs->data=0;
03693         rcs->extraData=extraData;
03694         rcs->socketIndex=connectionSocketIndex;
03695         rcs->actionToTake=RequestedConnectionStruct::CONNECT;
03696         rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
03697         rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
03698         memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
03699         rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
03700         rcs->timeoutTime=timeoutTime;
03701         rcs->socket=socket;
03702 
03703         // Return false if already pending, else push on queue
03704         unsigned int i=0;
03705         requestedConnectionQueueMutex.Lock();
03706         for (; i < requestedConnectionQueue.Size(); i++)
03707         {
03708                 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
03709                 {
03710                         requestedConnectionQueueMutex.Unlock();
03711                         RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
03712                         return false;
03713                 }
03714         }
03715         requestedConnectionQueue.Push(rcs, __FILE__, __LINE__ );
03716         requestedConnectionQueueMutex.Unlock();
03717 
03718         return true;
03719 }
03720 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03721 void RakPeer::ValidateRemoteSystemLookup(void) const
03722 {
03723 }
03724 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03725 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystem( const AddressOrGUID systemIdentifier, bool calledFromNetworkThread, bool onlyActive ) const
03726 {
03727         if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
03728                 return GetRemoteSystemFromGUID(systemIdentifier.rakNetGuid, onlyActive);
03729         else
03730                 return GetRemoteSystemFromSystemAddress(systemIdentifier.systemAddress, calledFromNetworkThread, onlyActive);
03731 }
03732 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03733 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread, bool onlyActive ) const
03734 {
03735         unsigned i;
03736 
03737         if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
03738                 return 0;
03739 
03740         if (calledFromNetworkThread)
03741         {
03742                 unsigned int index = GetRemoteSystemIndex(systemAddress);
03743                 if (index!=(unsigned int) -1)
03744                 {
03745                         if (onlyActive==false || remoteSystemList[ index ].isActive==true )
03746                         {
03747                                 RakAssert(remoteSystemList[index].systemAddress==systemAddress);
03748                                 return remoteSystemList + index;
03749                         }
03750                 }
03751         }
03752         else
03753         {
03754                 int deadConnectionIndex=-1;
03755 
03756                 // Active connections take priority.  But if there are no active connections, return the first systemAddress match found
03757                 for ( i = 0; i < maximumNumberOfPeers; i++ )
03758                 {
03759                         if (remoteSystemList[ i ].systemAddress == systemAddress)
03760                         {
03761                                 if ( remoteSystemList[ i ].isActive )
03762                                         return remoteSystemList + i;
03763                                 else if (deadConnectionIndex==-1)
03764                                         deadConnectionIndex=i;
03765                         }
03766                 }
03767 
03768                 if (deadConnectionIndex!=-1 && onlyActive==false)
03769                         return remoteSystemList + deadConnectionIndex;
03770         }
03771 
03772         return 0;
03773 }
03774 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03775 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromGUID( const RakNetGUID guid, bool onlyActive ) const
03776 {
03777         if (guid==UNASSIGNED_RAKNET_GUID)
03778                 return 0;
03779         
03780         unsigned i;
03781         for ( i = 0; i < maximumNumberOfPeers; i++ )
03782         {
03783                 if (remoteSystemList[ i ].guid == guid && (onlyActive==false || remoteSystemList[ i ].isActive))
03784                 {
03785                         return remoteSystemList + i;
03786                 }
03787         }
03788         return 0;
03789 }
03790 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03791 void RakPeer::ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, SystemAddress systemAddress, const char *data, int byteSize )
03792 {
03793         RakNet::BitStream bs((unsigned char*) data,byteSize,false);
03794         bs.IgnoreBytes(sizeof(MessageID));
03795         bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
03796         RakNetGUID guid;
03797         bs.Read(guid);
03798         RakNetTime incomingTimestamp;
03799         bs.Read(incomingTimestamp);
03800 
03801         // If we are full tell the sender.
03802         // Not needed
03803         if ( 0 ) 
03804         {
03805                 RakNet::BitStream bs;
03806                 bs.Write((MessageID)ID_NO_FREE_INCOMING_CONNECTIONS);
03807                 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
03808                 bs.Write(GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
03809                 SendImmediate((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0);
03810                 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
03811         }
03812         else
03813         {
03814                 const char *password = data + sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID) + sizeof(RakNetTime);
03815                 int passwordLength = byteSize - (int) (sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID) + sizeof(RakNetTime));
03816 
03817                 if ( incomingPasswordLength == passwordLength &&
03818                         memcmp( password, incomingPassword, incomingPasswordLength ) == 0 )
03819                 {
03820                         remoteSystem->connectMode=RemoteSystemStruct::HANDLING_CONNECTION_REQUEST;
03821 
03822 #if !defined(_XBOX) && !defined(X360)
03823                         char str1[64];
03824                         systemAddress.ToString(false, str1);
03825                         if ( usingSecurity == false ||
03826                                 IsInSecurityExceptionList(str1))
03827 #endif
03828                         {
03829 #ifdef _TEST_AES
03830                                 unsigned char AESKey[ 16 ];
03831                                 // Save the AES key
03832                                 for ( i = 0; i < 16; i++ )
03833                                         AESKey[ i ] = i;
03834 
03835                                 OnConnectionRequest( remoteSystem, AESKey, true );
03836 #else
03837                                 // Connect this player assuming we have open slots
03838                                 OnConnectionRequest( remoteSystem, 0, false, incomingTimestamp );
03839 #endif
03840                         }
03841 #if !defined(_XBOX) && !defined(X360)
03842                         else
03843                                 SecuredConnectionResponse( systemAddress );
03844 #endif
03845                 }
03846                 else
03847                 {
03848                         // This one we only send once since we don't care if it arrives.
03849                         RakNet::BitStream bitStream;
03850                         bitStream.Write((MessageID)ID_INVALID_PASSWORD);
03851                         bitStream.Write(GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
03852                         SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0);
03853                         remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
03854                 }
03855         }
03856 }
03857 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03858 void RakPeer::OnConnectionRequest( RakPeer::RemoteSystemStruct *remoteSystem, unsigned char *AESKey, bool setAESKey, RakNetTime incomingTimestamp )
03859 {
03860         // Already handled by caller
03861         //if ( AllowIncomingConnections() )
03862         {
03863                 SendConnectionRequestAccepted(remoteSystem, incomingTimestamp);
03864 
03865                 // Don't set secure connections immediately because we need the ack from the remote system to know ID_CONNECTION_REQUEST_ACCEPTED
03866                 // As soon as a 16 byte packet arrives, we will turn on AES.  This works because all encrypted packets are multiples of 16 and the
03867                 // packets I happen to be sending are less than 16 bytes
03868                 remoteSystem->setAESKey=setAESKey;
03869                 if ( setAESKey )
03870                 {
03871                         memcpy(remoteSystem->AESKey, AESKey, 16);
03872                         remoteSystem->connectMode=RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET;
03873                 }
03874         }
03875         /*
03876         else
03877         {
03878                 unsigned char c = ID_NO_FREE_INCOMING_CONNECTIONS;
03879                 //SocketLayer::Instance()->SendTo( connectionSocket, ( char* ) & c, sizeof( char ), systemAddress.binaryAddress, systemAddress.port );
03880 
03881                 SendImmediate((char*)&c, sizeof(c)*8, IMMEDIATE_PRIORITY, RELIABLE, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS());
03882                 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
03883         }
03884         */
03885 }
03886 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03887 void RakPeer::SendConnectionRequestAccepted(RakPeer::RemoteSystemStruct *remoteSystem, RakNetTime incomingTimestamp)
03888 {
03889         RakNet::BitStream bitStream;
03890         bitStream.Write((MessageID)ID_CONNECTION_REQUEST_ACCEPTED);
03891         bitStream.Write(remoteSystem->systemAddress);
03892         SystemIndex systemIndex = (SystemIndex) GetIndexFromSystemAddress( remoteSystem->systemAddress, true );
03893         RakAssert(systemIndex!=65535);
03894         bitStream.Write(systemIndex);
03895         for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
03896                 bitStream.Write(mySystemAddress[i]);
03897         bitStream.Write(incomingTimestamp);
03898         bitStream.Write(RakNet::GetTime());
03899 
03900         SendImmediate((char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS(), 0);
03901 }
03902 
03903 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03904 void RakPeer::NotifyAndFlagForShutdown( const SystemAddress systemAddress, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
03905 {
03906         RakNet::BitStream temp( sizeof(unsigned char) );
03907         temp.Write( (MessageID)ID_DISCONNECTION_NOTIFICATION );
03908         if (performImmediate)
03909         {
03910                 SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, false, RakNet::GetTimeNS(), 0);
03911                 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(systemAddress, true, true);
03912                 rss->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
03913         }
03914         else
03915         {
03916                 SendBuffered((const char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, RemoteSystemStruct::DISCONNECT_ASAP, 0);
03917         }
03918 }
03919 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03920 unsigned short RakPeer::GetNumberOfRemoteInitiatedConnections( void ) const
03921 {
03922         unsigned short i, numberOfIncomingConnections;
03923 
03924         if ( remoteSystemList == 0 || endThreads == true )
03925                 return 0;
03926 
03927         numberOfIncomingConnections = 0;
03928 
03929         // remoteSystemList in network thread
03930         for ( i = 0; i < maximumNumberOfPeers; i++ )
03931         //for ( i = 0; i < remoteSystemListSize; i++ )
03932         {
03933                 if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].weInitiatedTheConnection == false && remoteSystemList[i].connectMode==RemoteSystemStruct::CONNECTED)
03934                         numberOfIncomingConnections++;
03935         }
03936 
03937         return numberOfIncomingConnections;
03938 }
03939 
03940 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03941 RakPeer::RemoteSystemStruct * RakPeer::AssignSystemAddressToRemoteSystemList( const SystemAddress systemAddress, RemoteSystemStruct::ConnectMode connectionMode, RakNetSmartPtr<RakNetSocket> incomingRakNetSocket, bool *thisIPConnectedRecently, SystemAddress bindingAddress, int incomingMTU, RakNetGUID guid )
03942 {
03943         RemoteSystemStruct * remoteSystem;
03944         unsigned i,j,assignedIndex;
03945         RakNetTime time = RakNet::GetTime();
03946 #ifdef _DEBUG
03947         RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
03948 #endif
03949 
03950         if (limitConnectionFrequencyFromTheSameIP)
03951         {
03952                 if (IsLoopbackAddress(systemAddress,false)==false)
03953                 {
03954                         for ( i = 0; i < maximumNumberOfPeers; i++ )
03955                         {
03956                                 if ( remoteSystemList[ i ].isActive==true &&
03957                                         remoteSystemList[ i ].systemAddress.binaryAddress==systemAddress.binaryAddress &&
03958                                         time >= remoteSystemList[ i ].connectionTime &&
03959                                         time - remoteSystemList[ i ].connectionTime < 100
03960                                         )
03961                                 {
03962                                         // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
03963                                         // Ignore connection attempts if this IP address connected within the last 100 milliseconds
03964                                         *thisIPConnectedRecently=true;
03965                                         ValidateRemoteSystemLookup();
03966                                         return 0;
03967                                 }
03968                         }
03969                 }
03970         }
03971 
03972         // Don't use a different port than what we received on
03973         bindingAddress.port=incomingRakNetSocket->boundAddress.port;
03974 
03975         *thisIPConnectedRecently=false;
03976         for ( assignedIndex = 0; assignedIndex < maximumNumberOfPeers; assignedIndex++ )
03977         {
03978                 if ( remoteSystemList[ assignedIndex ].isActive==false )
03979                 {
03980                         remoteSystem=remoteSystemList+assignedIndex;
03981                         remoteSystem->rpcMap.Clear();
03982                         ReferenceRemoteSystem(systemAddress, assignedIndex);
03983                         remoteSystem->MTUSize=defaultMTUSize;
03984                         remoteSystem->guid=guid;
03985                         remoteSystem->isActive = true; // This one line causes future incoming packets to go through the reliability layer
03986                         // Reserve this reliability layer for ourselves.
03987                         if (incomingMTU > remoteSystem->MTUSize)
03988                                 remoteSystem->MTUSize=incomingMTU;
03989                         remoteSystem->reliabilityLayer.Reset(true, remoteSystem->MTUSize);
03990                         remoteSystem->reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval);
03991                         remoteSystem->reliabilityLayer.SetUnreliableTimeout(unreliableTimeout);
03992                         remoteSystem->reliabilityLayer.SetTimeoutTime(defaultTimeoutTime);
03993                         remoteSystem->reliabilityLayer.SetEncryptionKey( 0 );
03994                         if (incomingRakNetSocket->boundAddress==bindingAddress)
03995                         {
03996                                 remoteSystem->rakNetSocket=incomingRakNetSocket;
03997                         }
03998                         else
03999                         {
04000                                 char str[256];
04001                                 bindingAddress.ToString(true,str);
04002                                 // See if this is an internal IP address.
04003                                 // If so, force binding on it so we reply on the same IP address as they sent to.
04004                                 unsigned int ipListIndex, foundIndex=(unsigned int)-1;
04005 
04006                                 for (ipListIndex=0; ipListIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipListIndex++)
04007                                 {
04008                                         if (ipList[ipListIndex][0]==0)
04009                                                 break;
04010                                         if (bindingAddress.binaryAddress==binaryAddresses[ipListIndex])
04011                                         {
04012                                                 foundIndex=ipListIndex;
04013                                                 break;
04014                                         }
04015                                 }
04016 
04017                                 // 06/26/09 Unconfirmed report that Vista firewall blocks the reply if we force a binding
04018                                 // For now use the incoming socket only
04019                                 // Originally this code was to force a machine with multiple IP addresses to reply back on the IP
04020                                 // that the datagram came in on
04021                                 if (1 || foundIndex==(unsigned int)-1)
04022                                 {
04023                                         // Must not be an internal LAN address. Just use whatever socket it came in on
04024                                         remoteSystem->rakNetSocket=incomingRakNetSocket;
04025                                 }
04026                                 else
04027                                 {
04028                                         // Force binding
04029                                         unsigned int socketListIndex;
04030                                         for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
04031                                         {
04032                                                 if (socketList[socketListIndex]->boundAddress==bindingAddress)
04033                                                 {
04034                                                         // Force binding with existing socket
04035                                                         remoteSystem->rakNetSocket=socketList[socketListIndex];
04036                                                         break;
04037                                                 }
04038                                         }
04039 
04040                                         if (socketListIndex==socketList.Size())
04041                                         {
04042                                                 // Force binding with new socket
04043                                                 RakNetSmartPtr<RakNetSocket> rns(RakNet::OP_NEW<RakNetSocket>(__FILE__,__LINE__));
04044                                                 if (incomingRakNetSocket->remotePortRakNetWasStartedOn_PS3==0)
04045                                                         rns->s = (unsigned int) SocketLayer::Instance()->CreateBoundSocket( bindingAddress.port, true, ipList[foundIndex], 0 );
04046                                                 else
04047                                                         rns->s = (unsigned int) SocketLayer::Instance()->CreateBoundSocket_PS3Lobby( bindingAddress.port, true, ipList[foundIndex] );
04048                                                 if ((SOCKET)rns->s==(SOCKET)-1)
04049                                                 {
04050                                                         // Can't bind. Just use whatever socket it came in on
04051                                                         remoteSystem->rakNetSocket=incomingRakNetSocket;
04052                                                 }
04053                                                 else
04054                                                 {
04055                                                         rns->boundAddress=bindingAddress;
04056                                                         rns->remotePortRakNetWasStartedOn_PS3=incomingRakNetSocket->remotePortRakNetWasStartedOn_PS3;
04057                                                         rns->userConnectionSocketIndex=(unsigned int)-1;
04058                                                         socketList.Push(rns, __FILE__, __LINE__ );
04059                                                         remoteSystem->rakNetSocket=rns;
04060 
04061                                                         RakPeerAndIndex rpai;
04062                                                         rpai.remotePortRakNetWasStartedOn_PS3=rns->remotePortRakNetWasStartedOn_PS3;
04063                                                         rpai.s=rns->s;
04064                                                         rpai.rakPeer=this;
04065 #ifdef _WIN32
04066                                                         int highPriority=THREAD_PRIORITY_ABOVE_NORMAL;
04067 #else
04068                                                         int highPriority=-10;
04069 #endif
04070 
04071 //#if !defined(_XBOX) && !defined(X360)
04072                                                         highPriority=0;
04073 //#endif
04074                                                         isRecvFromLoopThreadActive=false;
04075                                                         int errorCode = RakNet::RakThread::Create(RecvFromLoop, &rpai, highPriority);
04076                                                         RakAssert(errorCode!=0);
04077                                                         while (  isRecvFromLoopThreadActive == false )
04078                                                                 RakSleep(10);
04079 
04080 
04081                                                         /*
04082 #if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
04083                                                         if (threadSleepTimer>0)
04084                                                         {
04085                                                                 rns->recvEvent=CreateEvent(0,FALSE,FALSE,0);
04086                                                                 WSAEventSelect(rns->s,rns->recvEvent,FD_READ);
04087                                                         }
04088 #endif
04089                                                         */
04090                                                 }
04091                                         }
04092                                 }
04093                         }
04094 
04095                         for ( j = 0; j < (unsigned) PING_TIMES_ARRAY_SIZE; j++ )
04096                         {
04097                                 remoteSystem->pingAndClockDifferential[ j ].pingTime = 65535;
04098                                 remoteSystem->pingAndClockDifferential[ j ].clockDifferential = 0;
04099                         }
04100 
04101                         remoteSystem->connectMode=connectionMode;
04102                         remoteSystem->pingAndClockDifferentialWriteIndex = 0;
04103                         remoteSystem->lowestPing = 65535;
04104                         remoteSystem->nextPingTime = 0; // Ping immediately
04105                         remoteSystem->weInitiatedTheConnection = false;
04106                         remoteSystem->connectionTime = time;
04107                         remoteSystem->myExternalSystemAddress = UNASSIGNED_SYSTEM_ADDRESS;
04108                         remoteSystem->setAESKey=false;
04109                         remoteSystem->lastReliableSend=time;
04110 
04111 #ifdef _DEBUG
04112                         int indexLoopupCheck=GetIndexFromSystemAddress( systemAddress, true );
04113                         if (indexLoopupCheck!=assignedIndex)
04114                         {
04115                                 RakAssert(indexLoopupCheck==assignedIndex);
04116                         }
04117 #endif
04118 
04119                         return remoteSystem;
04120                 }
04121         }
04122 
04123         return 0;
04124 }
04125 
04126 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04127 // Adjust the first four bytes (treated as unsigned int) of the pointer
04128 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04129 void RakPeer::ShiftIncomingTimestamp( unsigned char *data, SystemAddress systemAddress ) const
04130 {
04131 #ifdef _DEBUG
04132         RakAssert( IsActive() );
04133         RakAssert( data );
04134 #endif
04135 
04136         RakNet::BitStream timeBS( data, sizeof(RakNetTime), false);
04137         RakNetTime encodedTimestamp;
04138         timeBS.Read(encodedTimestamp);
04139 
04140         encodedTimestamp = encodedTimestamp - GetBestClockDifferential( systemAddress );
04141         timeBS.SetWriteOffset(0);
04142         timeBS.Write(encodedTimestamp);
04143 }
04144 
04145 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04146 // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
04147 RakNetTime RakPeer::GetBestClockDifferential( const SystemAddress systemAddress ) const
04148 {
04149         int counter, lowestPingSoFar;
04150         RakNetTime clockDifferential;
04151         RemoteSystemStruct *remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, true, true );
04152 
04153         if ( remoteSystem == 0 )
04154                 return 0;
04155 
04156         lowestPingSoFar = 65535;
04157 
04158         clockDifferential = 0;
04159 
04160         for ( counter = 0; counter < PING_TIMES_ARRAY_SIZE; counter++ )
04161         {
04162                 if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime == 65535 )
04163                         break;
04164 
04165                 if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime < lowestPingSoFar )
04166                 {
04167                         clockDifferential = remoteSystem->pingAndClockDifferential[ counter ].clockDifferential;
04168                         lowestPingSoFar = remoteSystem->pingAndClockDifferential[ counter ].pingTime;
04169                 }
04170         }
04171 
04172         return clockDifferential;
04173 }
04174 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04175 unsigned int RakPeer::RemoteSystemLookupHashIndex(SystemAddress sa) const
04176 {
04177         unsigned int lastHash = SuperFastHashIncremental ((const char*) & sa.binaryAddress, 4, 4 );
04178         lastHash = SuperFastHashIncremental ((const char*) & sa.port, 2, lastHash );
04179         return lastHash % ((unsigned int) maximumNumberOfPeers * REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE);
04180 }
04181 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04182 void RakPeer::ReferenceRemoteSystem(SystemAddress sa, unsigned int remoteSystemListIndex)
04183 {
04184 // #ifdef _DEBUG
04185 //      for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
04186 //      {
04187 //              if (remoteSystemList[remoteSystemIndex].isActive )
04188 //              {
04189 //                      unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
04190 //                      RakAssert(hashIndex==remoteSystemIndex);
04191 //              }
04192 //      }
04193 // #endif
04194 
04195 
04196         SystemAddress oldAddress = remoteSystemList[remoteSystemListIndex].systemAddress;
04197         if (oldAddress!=UNASSIGNED_SYSTEM_ADDRESS)
04198         {
04199                 // The system might be active if rerouting
04200 //              RakAssert(remoteSystemList[remoteSystemListIndex].isActive==false);
04201                 
04202                 // Remove the reference if the reference is pointing to this inactive system
04203                 if (GetRemoteSystem(oldAddress)==&remoteSystemList[remoteSystemListIndex])
04204                         DereferenceRemoteSystem(oldAddress);
04205         }
04206         DereferenceRemoteSystem(sa);
04207 
04208 // #ifdef _DEBUG
04209 //      for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
04210 //      {
04211 //              if (remoteSystemList[remoteSystemIndex].isActive )
04212 //              {
04213 //                      unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
04214 //                      if (hashIndex!=remoteSystemIndex)
04215 //                      {
04216 //                              RakAssert(hashIndex==remoteSystemIndex);
04217 //                      }
04218 //              }
04219 //      }
04220 // #endif
04221 
04222 
04223         remoteSystemList[remoteSystemListIndex].systemAddress=sa;
04224 
04225         unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
04226         RemoteSystemIndex *rsi;
04227         rsi = remoteSystemIndexPool.Allocate(__FILE__,__LINE__);
04228         if (remoteSystemLookup[hashIndex]==0)
04229         {
04230                 rsi->next=0;
04231                 rsi->index=remoteSystemListIndex;
04232                 remoteSystemLookup[hashIndex]=rsi;
04233         }
04234         else
04235         {
04236                 RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
04237                 while (cur->next!=0)
04238                 {
04239                         cur=cur->next;
04240                 }
04241 
04242                 rsi = remoteSystemIndexPool.Allocate(__FILE__,__LINE__);
04243                 rsi->next=0;
04244                 rsi->index=remoteSystemListIndex;
04245                 cur->next=rsi;
04246         }
04247 
04248 // #ifdef _DEBUG
04249 //      for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
04250 //      {
04251 //              if (remoteSystemList[remoteSystemIndex].isActive )
04252 //              {
04253 //                      unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
04254 //                      RakAssert(hashIndex==remoteSystemIndex);
04255 //              }
04256 //      }
04257 // #endif
04258 
04259 
04260         RakAssert(GetRemoteSystemIndex(sa)==remoteSystemListIndex);     
04261 }
04262 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04263 void RakPeer::DereferenceRemoteSystem(SystemAddress sa)
04264 {
04265         unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
04266         RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
04267         RemoteSystemIndex *last = 0;
04268         while (cur!=0)
04269         {
04270                 if (remoteSystemList[cur->index].systemAddress==sa)
04271                 {
04272                         if (last==0)
04273                         {
04274                                 remoteSystemLookup[hashIndex]=cur->next;
04275                         }
04276                         else
04277                         {
04278                                 last->next=cur->next;
04279                         }
04280                         remoteSystemIndexPool.Release(cur,__FILE__,__LINE__);
04281                         break;
04282                 }
04283                 last=cur;
04284                 cur=cur->next;
04285         }
04286 }
04287 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04288 unsigned int RakPeer::GetRemoteSystemIndex(SystemAddress sa) const
04289 {
04290         unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
04291         RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
04292         while (cur!=0)
04293         {
04294                 if (remoteSystemList[cur->index].systemAddress==sa)
04295                         return cur->index;
04296                 cur=cur->next;
04297         }
04298         return (unsigned int) -1;
04299 }
04300 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04301 RakPeer::RemoteSystemStruct* RakPeer::GetRemoteSystem(SystemAddress sa) const
04302 {
04303         unsigned int remoteSystemIndex = GetRemoteSystemIndex(sa);
04304         if (remoteSystemIndex==(unsigned int)-1)
04305                 return 0;
04306         return remoteSystemList + remoteSystemIndex;
04307 }
04308 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04309 void RakPeer::ClearRemoteSystemLookup(void)
04310 {
04311         remoteSystemIndexPool.Clear(__FILE__,__LINE__);
04312         RakNet::OP_DELETE_ARRAY(remoteSystemLookup,__FILE__,__LINE__);
04313         remoteSystemLookup=0;
04314 }
04315 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04316 /*
04317 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04318 unsigned int RakPeer::LookupIndexUsingHashIndex(SystemAddress sa) const
04319 {
04320         unsigned int scanCount=0;
04321         unsigned int index = RemoteSystemLookupHashIndex(sa);
04322         if (remoteSystemLookup[index].index==(unsigned int)-1)
04323                 return (unsigned int) -1;
04324         while (remoteSystemList[remoteSystemLookup[index].index].systemAddress!=sa)
04325         {
04326                 if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
04327                         index=0;
04328                 if (++scanCount>(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
04329                         return (unsigned int) -1;
04330                 if (remoteSystemLookup[index].index==-1)
04331                         return (unsigned int) -1;
04332         }
04333         return index;
04334 }
04335 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04336 unsigned int RakPeer::RemoteSystemListIndexUsingHashIndex(SystemAddress sa) const
04337 {
04338         unsigned int index = LookupIndexUsingHashIndex(sa);
04339         if (index!=(unsigned int) -1)
04340         {
04341                 return remoteSystemLookup[index].index;
04342         }
04343         return (unsigned int) -1;
04344 }
04345 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04346 unsigned int RakPeer::FirstFreeRemoteSystemLookupIndex(SystemAddress sa) const
04347 {
04348 //      unsigned int collisionCount=0;
04349         unsigned int index = RemoteSystemLookupHashIndex(sa);
04350         while (remoteSystemLookup[index].index!=(unsigned int)-1)
04351         {
04352                 if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
04353                         index=0;
04354 //              collisionCount++;
04355         }
04356 //      printf("%i collisions. Using index %i\n", collisionCount, index);
04357         return index;
04358 }
04359 */
04360 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04361 // Description:
04362 // Handles an RPC packet.  If you get a packet with the ID ID_RPC you should pass it to this function
04363 //
04364 // Parameters:
04365 // packet - A packet returned from Receive with the ID ID_RPC
04366 //
04367 // Returns:
04368 // true on success, false on a bad packet or an unregistered function
04369 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04370 #ifdef _MSC_VER
04371 #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
04372 #endif
04373 bool RakPeer::HandleRPCPacket( const char *data, int length, SystemAddress systemAddress )
04374 {
04375         // RPC BitStream format is
04376         // ID_RPC - unsigned char
04377         // Unique identifier string length - unsigned char
04378         // The unique ID  - string with each letter in upper case, subtracted by 'A' and written in 5 bits.
04379         // Number of bits of the data (int)
04380         // The data
04381 
04382         RakNet::BitStream incomingBitStream( (unsigned char *) data, length, false );
04383         char uniqueIdentifier[ 256 ];
04384 //      BitSize_t bitLength;
04385         unsigned char *userData;
04386         //bool hasTimestamp;
04387         bool nameIsEncoded, networkIDIsEncoded;
04388         RPCIndex rpcIndex;
04389         RPCNode *node;
04390         RPCParameters rpcParms;
04391         NetworkID networkID;
04392         bool blockingCommand;
04393         RakNet::BitStream replyToSender;
04394         rpcParms.replyToSender=&replyToSender;
04395 
04396         rpcParms.recipient=this;
04397         rpcParms.sender=systemAddress;
04398 
04399         // Note to self - if I change this format then I have to change the PacketLogger class too
04400         incomingBitStream.IgnoreBits(8);
04401         if (data[0]==ID_TIMESTAMP)
04402         {
04403                 incomingBitStream.IgnoreBits(8*(sizeof(RakNetTime)+sizeof(MessageID)));
04404                 memcpy(&rpcParms.remoteTimestamp, data+sizeof(MessageID), sizeof(RakNetTime));
04405         }
04406         else
04407                 rpcParms.remoteTimestamp=0;
04408         if ( incomingBitStream.Read( nameIsEncoded ) == false )
04409         {
04410 #ifdef _DEBUG
04411                 RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04412 #endif
04413                 return false;
04414         }
04415 
04416         if (nameIsEncoded)
04417         {
04418                 if ( stringCompressor->DecodeString(uniqueIdentifier, 256, &incomingBitStream) == false )
04419                 {
04420 #ifdef _DEBUG
04421                         RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04422 #endif
04423                         return false;
04424                 }
04425 
04426                 rpcIndex = rpcMap.GetIndexFromFunctionName(uniqueIdentifier);
04427         }
04428         else
04429         {
04430                 if ( incomingBitStream.ReadCompressed( rpcIndex ) == false )
04431                 {
04432 #ifdef _DEBUG
04433                         RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04434 #endif
04435                         return false;
04436                 }
04437         }
04438         if ( incomingBitStream.Read( blockingCommand ) == false )
04439         {
04440 #ifdef _DEBUG
04441                 RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04442 #endif
04443                 return false;
04444         }
04445 
04446         /*
04447         if ( incomingBitStream.Read( rpcParms.hasTimestamp ) == false )
04448         {
04449 #ifdef _DEBUG
04450                 RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04451 #endif
04452                 return false;
04453         }
04454         */
04455 
04456         if ( incomingBitStream.ReadCompressed( rpcParms.numberOfBitsOfData ) == false )
04457         {
04458 #ifdef _DEBUG
04459                 RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04460 #endif
04461                 return false;
04462         }
04463 
04464         if ( incomingBitStream.Read( networkIDIsEncoded ) == false )
04465         {
04466 #ifdef _DEBUG
04467                 RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04468 #endif
04469                 return false;
04470         }
04471 
04472         if (networkIDIsEncoded)
04473         {
04474                 if ( incomingBitStream.Read( networkID ) == false )
04475                 {
04476 #ifdef _DEBUG
04477                         RakAssert( 0 ); // bitstream was not long enough.  Some kind of internal error
04478 #endif
04479                         return false;
04480                 }
04481         }
04482 
04483         if (rpcIndex==UNDEFINED_RPC_INDEX)
04484         {
04485                 // Unregistered function
04486                 RakAssert(0);
04487                 return false;
04488         }
04489 
04490         node = rpcMap.GetNodeFromIndex(rpcIndex);
04491         if (node==0)
04492         {
04493 #ifdef _DEBUG
04494                 RakAssert( 0 ); // Should never happen except perhaps from threading errors?  No harm in checking anyway
04495 #endif
04496                 return false;
04497         }
04498 
04499         // Make sure the call type matches - if this is a pointer to a class member then networkID must be defined.  Otherwise it must not be defined
04500         if (node->isPointerToMember==true && networkIDIsEncoded==false)
04501         {
04502                 // If this hits then this pointer was registered as a class member function but the packet does not have an NetworkID.
04503                 // Most likely this means this system registered a function with REGISTER_CLASS_MEMBER_RPC and the remote system called it
04504                 // using the unique ID for a function registered with REGISTER_STATIC_RPC.
04505                 RakAssert(0);
04506                 return false;
04507         }
04508 
04509         if (node->isPointerToMember==false && networkIDIsEncoded==true)
04510         {
04511                 // If this hits then this pointer was not registered as a class member function but the packet does have an NetworkID.
04512                 // Most likely this means this system registered a function with REGISTER_STATIC_RPC and the remote system called it
04513                 // using the unique ID for a function registered with REGISTER_CLASS_MEMBER_RPC.
04514                 RakAssert(0);
04515                 return false;
04516         }
04517 
04518         if (nameIsEncoded && GetRemoteSystemFromSystemAddress(systemAddress, false, true))
04519         {
04520                 // Send ID_RPC_MAPPING to the sender so they know what index to use next time
04521                 RakNet::BitStream rpcMapBitStream;
04522                 rpcMapBitStream.Write((MessageID)ID_RPC_MAPPING);
04523                 stringCompressor->EncodeString(node->uniqueIdentifier, 256, &rpcMapBitStream);
04524         rpcMapBitStream.WriteCompressed(rpcIndex);
04525                 SendBuffered( (const char*)rpcMapBitStream.GetData(), rpcMapBitStream.GetNumberOfBitsUsed(), HIGH_PRIORITY, UNRELIABLE, 0, systemAddress, false, RemoteSystemStruct::NO_ACTION, 0 );
04526         }
04527 
04528         rpcParms.functionName=node->uniqueIdentifier;
04529 
04530         // Call the function
04531         if ( rpcParms.numberOfBitsOfData == 0 )
04532         {
04533                 rpcParms.input=0;
04534                 if (networkIDIsEncoded)
04535                 {
04536                         // If this assert hits, you tried to use object member RPC but didn't call RakPeer::SetNetworkIDManager first as required.
04537                         RakAssert(networkIDManager);
04538                         if (networkIDManager)
04539                         {
04540                                 void *object = networkIDManager->GET_OBJECT_FROM_ID(networkID);
04541                         if (object)
04542                                 (node->memberFunctionPointer(object, &rpcParms));
04543                 }
04544                 }
04545                 else
04546                 {
04547                         node->staticFunctionPointer( &rpcParms );
04548                 }
04549         }
04550         else
04551         {
04552                 if ( incomingBitStream.GetNumberOfUnreadBits() == 0 )
04553                 {
04554 #ifdef _DEBUG
04555                         RakAssert( 0 );
04556 #endif
04557                         return false; // No data was appended!
04558                 }
04559 
04560                 // We have to copy into a new data chunk because the user data might not be byte aligned.
04561                 bool usedAlloca=false;
04562 #if !defined(_XBOX) && !defined(X360)
04563                 if (BITS_TO_BYTES( incomingBitStream.GetNumberOfUnreadBits() ) < MAX_ALLOCA_STACK_ALLOCATION)
04564                 {
04565                         userData = ( unsigned char* ) alloca( (size_t) BITS_TO_BYTES( incomingBitStream.GetNumberOfUnreadBits() ) );
04566                         usedAlloca=true;
04567                 }
04568                 else
04569 #endif
04570                         userData = (unsigned char*) rakMalloc_Ex((size_t) BITS_TO_BYTES(incomingBitStream.GetNumberOfUnreadBits()), __FILE__, __LINE__);
04571 
04572 
04573                 // The false means read out the internal representation of the bitstream data rather than
04574                 // aligning it as we normally would with user data.  This is so the end user can cast the data received
04575                 // into a bitstream for reading
04576                 if ( incomingBitStream.ReadBits( ( unsigned char* ) userData, rpcParms.numberOfBitsOfData, false ) == false )
04577                 {
04578 #ifdef _DEBUG
04579                         RakAssert( 0 );
04580 #endif
04581                         #if defined(_XBOX) || defined(X360)
04582                                              
04583                         #endif
04584 
04585                         return false; // Not enough data to read
04586                 }
04587 
04588 //              if ( rpcParms.hasTimestamp )
04589 //                      ShiftIncomingTimestamp( userData, systemAddress );
04590 
04591                 // Call the function callback
04592                 rpcParms.input=userData;
04593                 if (networkIDIsEncoded)
04594                 {
04595                         // If this assert hits, you tried to use object member RPC but didn't call RakPeer::SetNetworkIDManager first as required.
04596                         RakAssert(networkIDManager);
04597                         if (networkIDManager)
04598                         {
04599                                 void *object = networkIDManager->GET_OBJECT_FROM_ID(networkID);
04600                         if (object)
04601                                 (node->memberFunctionPointer(object, &rpcParms));
04602                 }
04603                 }
04604                 else
04605                 {
04606                         node->staticFunctionPointer( &rpcParms );
04607                 }
04608 
04609 
04610                 if (usedAlloca==false)
04611                         rakFree_Ex(userData, __FILE__, __LINE__ );
04612         }
04613 
04614         if (blockingCommand)
04615         {
04616                 RakNet::BitStream reply;
04617                 reply.Write((MessageID)ID_RPC_REPLY);
04618                 reply.Write((char*)replyToSender.GetData(), replyToSender.GetNumberOfBytesUsed());
04619                 Send(&reply, HIGH_PRIORITY, RELIABLE, 0, systemAddress, false);
04620         }
04621 
04622         return true;
04623 }
04624 
04625 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04635 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04636 void RakPeer::HandleRPCReplyPacket( const char *data, int length, SystemAddress systemAddress )
04637 {
04638         if (blockOnRPCReply)
04639         {
04640                 if ((systemAddress==replyFromTargetPlayer && replyFromTargetBroadcast==false) ||
04641                         (systemAddress!=replyFromTargetPlayer && replyFromTargetBroadcast==true))
04642                 {
04643                         replyFromTargetBS->Write(data+1, length-1);
04644                         blockOnRPCReply=false;
04645                 }
04646         }
04647 }
04648 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04649 bool RakPeer::IsLoopbackAddress(const AddressOrGUID &systemIdentifier, bool matchPort) const
04650 {
04651         if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
04652                 return systemIdentifier.rakNetGuid==myGuid;
04653 
04654         const SystemAddress sa = systemIdentifier.systemAddress;
04655 
04656         // Used to see if we are sending to ourselves
04657         char str[64];
04658         sa.ToString(false,str);
04659 #if !defined(_XBOX) && !defined(X360)
04660         bool isLoopback=strcmp(str,"127.0.0.1")==0;
04661         if (matchPort==false && isLoopback)
04662                 return true;
04663         if (matchPort==false)
04664         {
04665                 for (int ipIndex=0; ipIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipIndex++)
04666                         if (mySystemAddress[ipIndex].binaryAddress==sa.binaryAddress)
04667                                 return true;
04668         }
04669         else
04670         {
04671                 for (int ipIndex=0; ipIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipIndex++)
04672                         if (mySystemAddress[ipIndex]==sa ||
04673                                 (isLoopback && sa.port==mySystemAddress[ipIndex].port))
04674                                 return true;
04675         }
04676 #else
04677         bool isLoopback=strcmp(str,"2130706433")==0;
04678         if (isLoopback)
04679         {
04680                 if (matchPort==false)
04681                 {
04682                         return true;
04683                 }
04684                 else
04685                 {
04686                         for (int ipIndex=0; ipIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipIndex++)
04687                                 if (mySystemAddress[ipIndex]==sa ||
04688                                         (isLoopback && sa.port==mySystemAddress[ipIndex].port))
04689                                         return true;
04690                 }
04691         }
04692 #endif
04693         return sa==firstExternalID;
04694 }
04695 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04696 SystemAddress RakPeer::GetLoopbackAddress(void) const
04697 {
04698 #if !defined(_XBOX) && !defined(X360)
04699         return mySystemAddress[0];
04700 #else
04701         return firstExternalID;
04702 #endif
04703 }
04704 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04705 void RakPeer::GenerateSYNCookieRandomNumber( void )
04706 {
04707 #if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
04708         unsigned int number;
04709         int i;
04710         memcpy( oldRandomNumber, newRandomNumber, sizeof( newRandomNumber ) );
04711 
04712         for ( i = 0; i < (int) sizeof( newRandomNumber ); i += (int) sizeof( number ) )
04713         {
04714                 number = randomMT();
04715                 memcpy( newRandomNumber + i, ( char* ) & number, sizeof( number ) );
04716         }
04717 
04718         randomNumberExpirationTime = RakNet::GetTime() + SYN_COOKIE_OLD_RANDOM_NUMBER_DURATION;
04719 #endif
04720 }
04721 
04722 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04723 void RakPeer::SecuredConnectionResponse( const SystemAddress systemAddress )
04724 {
04725 #if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
04726         CSHA1 sha1;
04727 //      RSA_BIT_SIZE n;
04728 //      big::uint32_t e;
04729 //      unsigned char connectionRequestResponse[ 1 + sizeof( big::uint32_t ) + sizeof( RSA_BIT_SIZE ) + 20 ];
04730         uint32_t modulus[RAKNET_RSA_FACTOR_LIMBS];
04731         uint32_t e;
04732         unsigned char connectionRequestResponse[ 1 + sizeof( e ) + sizeof( modulus ) + 20 ];
04733         connectionRequestResponse[ 0 ] = ID_SECURED_CONNECTION_RESPONSE;
04734 
04735         if ( randomNumberExpirationTime < RakNet::GetTime() )
04736                 GenerateSYNCookieRandomNumber();
04737 
04738         // Hash the SYN-Cookie
04739         // s2c syn-cookie = SHA1_HASH(source ip address + source port + random number)
04740         sha1.Reset();
04741         sha1.Update( ( unsigned char* ) & systemAddress.binaryAddress, sizeof( systemAddress.binaryAddress ) );
04742         sha1.Update( ( unsigned char* ) & systemAddress.port, sizeof( systemAddress.port ) );
04743         sha1.Update( ( unsigned char* ) & ( newRandomNumber ), sizeof(newRandomNumber) );
04744         sha1.Final();
04745 
04746         // Write the cookie (not endian swapped)
04747         memcpy( connectionRequestResponse + 1, sha1.GetHash(), 20 );
04748 
04749         // Write the public keys
04750         e = rsacrypt.getPublicExponent();
04751         //rsacrypt.getPublicModulus(n);
04752         rsacrypt.getPublicModulus(modulus);
04753         //rsacrypt.getPublicKey( e, n );
04754 
04755         if (RakNet::BitStream::DoEndianSwap())
04756         {
04757                 RakNet::BitStream::ReverseBytesInPlace(( unsigned char* ) & e, sizeof(e));
04758                 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
04759                         RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &modulus[i], sizeof(modulus[i]));
04760         }
04761 
04762         memcpy( connectionRequestResponse + 1 + 20, ( char* ) & e, sizeof( e ) );
04763         memcpy( connectionRequestResponse + 1 + 20 + sizeof( e ), modulus, sizeof( modulus ) );
04764 
04765         /*
04766 #ifdef HOST_ENDIAN_IS_BIG
04767         // Mangle the keys on a Big-endian machine before sending
04768         BSWAPCPY( (unsigned char *)(connectionRequestResponse + 1 + 20),
04769                 (unsigned char *)&e, sizeof( big::uint32_t ) );
04770         BSWAPCPY( (unsigned char *)(connectionRequestResponse + 1 + 20 + sizeof( big::uint32_t ) ),
04771                 (unsigned char *)n, sizeof( RSA_BIT_SIZE ) );
04772 #else
04773         memcpy( connectionRequestResponse + 1 + 20, ( char* ) & e, sizeof( big::uint32_t ) );
04774         memcpy( connectionRequestResponse + 1 + 20 + sizeof( big::uint32_t ), n, sizeof( RSA_BIT_SIZE ) );
04775 #endif
04776         */
04777 
04778         // s2c public key, syn-cookie
04779         //SocketLayer::Instance()->SendTo( connectionSocket, ( char* ) connectionRequestResponse, 1 + sizeof( big::uint32_t ) + sizeof( RSA_BIT_SIZE ) + 20, systemAddress.binaryAddress, systemAddress.port );
04780         // All secure connection requests are unreliable because the entire process needs to be restarted if any part fails.
04781         // Connection requests are resent periodically
04782         SendImmediate(( char* ) connectionRequestResponse, (1 + sizeof( e ) + sizeof( modulus ) + 20) * 8, IMMEDIATE_PRIORITY, UNRELIABLE, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0);
04783 #endif
04784 }
04785 
04786 void RakPeer::SecuredConnectionConfirmation( RakPeer::RemoteSystemStruct * remoteSystem, char* data )
04787 {
04788 #if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
04789         int i, j;
04790         unsigned char randomNumber[ 20 ];
04791         unsigned int number;
04792         //bool doSend;
04793         Packet *packet;
04794 //      big::uint32_t e;
04795 //      RSA_BIT_SIZE n, message, encryptedMessage;
04796 //      big::RSACrypt<RSA_BIT_SIZE> privKeyPncrypt;
04797         uint32_t e;
04798         uint32_t n[RAKNET_RSA_FACTOR_LIMBS], message[RAKNET_RSA_FACTOR_LIMBS], encryptedMessage[RAKNET_RSA_FACTOR_LIMBS];
04799         RSACrypt privKeyPncrypt;
04800 
04801         // Make sure that we still want to connect
04802         if (remoteSystem->connectMode!=RemoteSystemStruct::REQUESTED_CONNECTION)
04803                 return;
04804 
04805         // Copy out e and n
04806         /*
04807 #ifdef HOST_ENDIAN_IS_BIG
04808         BSWAPCPY( (unsigned char *)&e, (unsigned char *)(data + 1 + 20), sizeof( big::uint32_t ) );
04809         BSWAPCPY( (unsigned char *)n, (unsigned char *)(data + 1 + 20 + sizeof( big::uint32_t )), sizeof( RSA_BIT_SIZE ) );
04810 #else
04811         memcpy( ( char* ) & e, data + 1 + 20, sizeof( big::uint32_t ) );
04812         memcpy( n, data + 1 + 20 + sizeof( big::uint32_t ), sizeof( RSA_BIT_SIZE ) );
04813 #endif
04814         */
04815 
04816         memcpy( ( char* ) & e, data + 1 + 20, sizeof( e ) );
04817         memcpy( n, data + 1 + 20 + sizeof( e ), sizeof( n ) );
04818 
04819         if (RakNet::BitStream::DoEndianSwap())
04820         {
04821                 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &e, sizeof(e));
04822                 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
04823                         RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &n[i], sizeof(n[i]));
04824         }
04825 
04826 
04827         // If we preset a size and it doesn't match, or the keys do not match, then tell the user
04828         if ( usingSecurity == true && keysLocallyGenerated == false )
04829         {
04830                 if ( memcmp( ( char* ) & e, ( char* ) & publicKeyE, sizeof( e ) ) != 0 ||
04831                         memcmp( n, publicKeyN, sizeof( n ) ) != 0 )
04832                 {
04833                         packet=AllocPacket(1, __FILE__, __LINE__);
04834                         packet->data[ 0 ] = ID_RSA_PUBLIC_KEY_MISMATCH;
04835                         packet->bitSize = sizeof( char ) * 8;
04836                         packet->systemAddress = remoteSystem->systemAddress;
04837                         packet->systemAddress.systemIndex = ( SystemIndex ) GetIndexFromSystemAddress( packet->systemAddress, true );
04838                         packet->guid.systemIndex=packet->systemAddress.systemIndex;
04839                         AddPacketToProducer(packet);
04840                         remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
04841                         return;
04842                 }
04843         }
04844 
04845         // Create a random number
04846         for ( i = 0; i < (int) sizeof( randomNumber ); i += (int) sizeof( number ) )
04847         {
04848                 number = randomMT();
04849                 memcpy( randomNumber + i, ( char* ) & number, sizeof( number ) );
04850         }
04851 
04852         memset( message, 0, sizeof( message ) );
04853         RakAssert( sizeof( message ) >= sizeof( randomNumber ) );
04854 
04855 //      if (RakNet::BitStream::DoEndianSwap())
04856 //      {
04857 //              for (int i=0; i < 20; i++)
04858 //                      RakNet::BitStream::ReverseBytesInPlace((unsigned char*) randomNumber[i], sizeof(randomNumber[i]));
04859 //      }
04860 
04861         memcpy( message, randomNumber, sizeof( randomNumber ) );
04862 
04863         /*
04864 
04865 
04866 #ifdef HOST_ENDIAN_IS_BIG
04867         // Scramble the plaintext message (the random number)
04868         BSWAPCPY( (unsigned char *)message, randomNumber, sizeof(randomNumber) );
04869 #else
04870         memcpy( message, randomNumber, sizeof( randomNumber ) );
04871 #endif
04872         */
04873         privKeyPncrypt.setPublicKey( n, RAKNET_RSA_FACTOR_LIMBS, e );
04874 //      privKeyPncrypt.encrypt( message, encryptedMessage );
04875 
04876 //      printf("message[0]=%i,%i\n", message[0], message[19]);
04877 
04878         privKeyPncrypt.encrypt( encryptedMessage, message );
04879 
04880 //      printf("enc1[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
04881 
04882         // A big-endian machine needs to scramble the byte order of an outgoing (encrypted) message
04883         if (RakNet::BitStream::DoEndianSwap())
04884         {
04885                 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
04886                         RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &encryptedMessage[i], sizeof(encryptedMessage[i]));
04887         }
04888 
04889 //      printf("enc2[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
04890 
04891 
04892         /*
04893 #ifdef HOST_ENDIAN_IS_BIG
04894         // A big-endian machine needs to scramble the byte order of an outgoing (encrypted) message
04895         BSWAPSELF( (unsigned char *)encryptedMessage, sizeof( RSA_BIT_SIZE ) );
04896 #endif
04897         */
04898 
04899         /*
04900         rakPeerMutexes[ RakPeer::requestedConnections_MUTEX ].Lock();
04901         for ( i = 0; i < ( int ) requestedConnectionsList.Size(); i++ )
04902         {
04903                 if ( requestedConnectionsList[ i ]->systemAddress == systemAddress )
04904                 {
04905                         doSend = true;
04906                         // Generate the AES key
04907 
04908                         for ( j = 0; j < 16; j++ )
04909                                 requestedConnectionsList[ i ]->AESKey[ j ] = data[ 1 + j ] ^ randomNumber[ j ];
04910 
04911                         requestedConnectionsList[ i ]->setAESKey = true;
04912 
04913                         break;
04914                 }
04915         }
04916         rakPeerMutexes[ RakPeer::requestedConnections_MUTEX ].Unlock();
04917         */
04918 
04919         // Take the remote system's AESKey (SynCookie) and XOR with our random number.
04920                 for ( j = 0; j < 16; j++ )
04921                         remoteSystem->AESKey[ j ] = data[ 1 + j ] ^ randomNumber[ j ];
04922         remoteSystem->setAESKey = true;
04923 
04924         /*
04925 //      if ( doSend )
04926 //      {
04927                 char reply[ 1 + 20 + sizeof( RSA_BIT_SIZE ) ];
04928                 // c2s RSA(random number), same syn-cookie
04929                 reply[ 0 ] = ID_SECURED_CONNECTION_CONFIRMATION;
04930                 memcpy( reply + 1, data + 1, 20 );  // Copy the syn-cookie
04931                 memcpy( reply + 1 + 20, encryptedMessage, sizeof( RSA_BIT_SIZE ) ); // Copy the encoded random number
04932 
04933                 //SocketLayer::Instance()->SendTo( connectionSocket, reply, 1 + 20 + sizeof( RSA_BIT_SIZE ), systemAddress.binaryAddress, systemAddress.port );
04934                 // All secure connection requests are unreliable because the entire process needs to be restarted if any part fails.
04935                 // Connection requests are resent periodically
04936                 SendImmediate((char*)reply, (1 + 20 + sizeof( RSA_BIT_SIZE )) * 8, IMMEDIATE_PRIORITY, UNRELIABLE, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS());
04937 //      }
04938 */
04939 
04940         char reply[ 1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS + sizeof(RakNetTime) ];
04941         // c2s RSA(random number), same syn-cookie
04942         reply[ 0 ] = ID_SECURED_CONNECTION_CONFIRMATION;
04943         memcpy( reply + 1, data + 1, 20 );  // Copy the syn-cookie
04944         memcpy( reply + 1 + 20, encryptedMessage, sizeof( encryptedMessage ) ); // Copy the encoded random number
04945         RakNet::BitStream bsTimestamp;
04946         bsTimestamp.Write(RakNet::GetTime());
04947         memcpy( reply + 1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS, bsTimestamp.GetData(), bsTimestamp.GetNumberOfBytesUsed() );
04948 
04949         // All secure connection requests are unreliable because the entire process needs to be restarted if any part fails.
04950         // Connection requests are resent periodically
04951         SendImmediate((char*)reply, (1 + 20 + sizeof(uint32_t) * RAKNET_RSA_FACTOR_LIMBS + sizeof(RakNetTime) ) * 8 , IMMEDIATE_PRIORITY, UNRELIABLE, 0, remoteSystem->systemAddress, false, false, RakNet::GetTimeNS(), 0);
04952 
04953 #endif
04954 }
04955 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04956 bool RakPeer::AllowIncomingConnections(void) const
04957 {
04958         return GetNumberOfRemoteInitiatedConnections() < GetMaximumIncomingConnections();
04959 }
04960 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04961 void RakPeer::PingInternal( const SystemAddress target, bool performImmediate, PacketReliability reliability )
04962 {
04963         if ( IsActive() == false )
04964                 return ;
04965 
04966         RakNet::BitStream bitStream(sizeof(unsigned char)+sizeof(RakNetTime));
04967         bitStream.Write((MessageID)ID_INTERNAL_PING);
04968         RakNetTimeUS currentTimeNS = RakNet::GetTimeNS();
04969         RakNetTime currentTime = RakNet::GetTime();
04970         bitStream.Write(currentTime);
04971         if (performImmediate)
04972                 SendImmediate( (char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, reliability, 0, target, false, false, currentTimeNS, 0 );
04973         else
04974                 Send( &bitStream, IMMEDIATE_PRIORITY, reliability, 0, target, false );
04975 }
04976 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04977 void RakPeer::CloseConnectionInternal( const AddressOrGUID& systemIdentifier, bool sendDisconnectionNotification, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
04978 {
04979 #ifdef _DEBUG
04980         RakAssert(orderingChannel < 32);
04981 #endif
04982 
04983         if (systemIdentifier.IsUndefined())
04984                 return;
04985 
04986         if ( remoteSystemList == 0 || endThreads == true )
04987                 return;
04988 
04989         SystemAddress target;
04990         if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
04991         {
04992                 target=systemIdentifier.systemAddress;
04993         }
04994         else
04995         {
04996                 target=GetSystemAddressFromGuid(systemIdentifier.rakNetGuid);
04997         }
04998 
04999         if (sendDisconnectionNotification)
05000         {
05001                 NotifyAndFlagForShutdown(target, performImmediate, orderingChannel, disconnectionNotificationPriority);
05002         }
05003         else
05004         {
05005                 if (performImmediate)
05006                 {
05007                         unsigned int index = GetRemoteSystemIndex(target);
05008                         if (index!=(unsigned int) -1)
05009                         {
05010                                 if ( remoteSystemList[index].isActive )
05011                                 {
05012                                         // Found the index to stop
05013                                         remoteSystemList[index].isActive = false;
05014 
05015                                         remoteSystemList[index].guid=UNASSIGNED_RAKNET_GUID;
05016 
05017                                         // Reserve this reliability layer for ourselves
05018                                         //remoteSystemList[ remoteSystemLookup[index].index ].systemAddress = UNASSIGNED_SYSTEM_ADDRESS;
05019 
05020                                         // Clear any remaining messages
05021                                         remoteSystemList[index].reliabilityLayer.Reset(false, remoteSystemList[index].MTUSize);
05022 
05023                                         // Not using this socket
05024                                         remoteSystemList[index].rakNetSocket.SetNull();
05025                                 }
05026                         }
05027                 }
05028                 else
05029                 {
05030                         BufferedCommandStruct *bcs;
05031 #ifdef _RAKNET_THREADSAFE
05032                         bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
05033                         bcs->command=BufferedCommandStruct::BCS_CLOSE_CONNECTION;
05034                         bcs->systemIdentifier=target;
05035                         bcs->data=0;
05036                         bcs->orderingChannel=orderingChannel;
05037                         bcs->priority=disconnectionNotificationPriority;
05038                         bufferedCommands.Push(bcs);
05039 #else
05040                         bcs=bufferedCommands.WriteLock();
05041                         bcs->command=BufferedCommandStruct::BCS_CLOSE_CONNECTION;
05042                         bcs->systemIdentifier=target;
05043                         bcs->data=0;
05044                         bcs->orderingChannel=orderingChannel;
05045                         bcs->priority=disconnectionNotificationPriority;
05046                         bufferedCommands.WriteUnlock();
05047 #endif
05048                 }
05049         }
05050 }
05051 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05052 bool RakPeer::ValidSendTarget(SystemAddress systemAddress, bool broadcast)
05053 {
05054         unsigned remoteSystemIndex;
05055 
05056         // remoteSystemList in user thread.  This is slow so only do it in debug
05057         for ( remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; remoteSystemIndex++ )
05058         //for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; remoteSystemIndex++ )
05059         {
05060                 if ( remoteSystemList[ remoteSystemIndex ].isActive &&
05061                         remoteSystemList[ remoteSystemIndex ].connectMode==RakPeer::RemoteSystemStruct::CONNECTED && // Not fully connected players are not valid user-send targets because the reliability layer wasn't reset yet
05062                         ( ( broadcast == false && remoteSystemList[ remoteSystemIndex ].systemAddress == systemAddress ) ||
05063                         ( broadcast == true && remoteSystemList[ remoteSystemIndex ].systemAddress != systemAddress ) )
05064                         )
05065                         return true;
05066         }
05067 
05068         return false;
05069 }
05070 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05071 void RakPeer::SendBuffered( const char *data, BitSize_t numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RemoteSystemStruct::ConnectMode connectionMode, uint32_t receipt )
05072 {
05073         BufferedCommandStruct *bcs;
05074 
05075 #ifdef _RAKNET_THREADSAFE
05076         bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
05077 #else
05078         bcs=bufferedCommands.WriteLock();
05079 #endif
05080         bcs->data = (char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES(numberOfBitsToSend), __FILE__, __LINE__ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
05081         if (bcs->data==0)
05082         {
05083                 notifyOutOfMemory(__FILE__, __LINE__);
05084 #ifdef _RAKNET_THREADSAFE
05085                 bufferedCommands.Deallocate(bcs, __FILE__,__LINE__);
05086 #else
05087                 bufferedCommands.WriteUnlock();
05088 #endif
05089                 return;
05090         }
05091         memcpy(bcs->data, data, (size_t) BITS_TO_BYTES(numberOfBitsToSend));
05092         bcs->numberOfBitsToSend=numberOfBitsToSend;
05093         bcs->priority=priority;
05094         bcs->reliability=reliability;
05095         bcs->orderingChannel=orderingChannel;
05096         bcs->systemIdentifier=systemIdentifier;
05097         bcs->broadcast=broadcast;
05098         bcs->connectionMode=connectionMode;
05099         bcs->receipt=receipt;
05100         bcs->command=BufferedCommandStruct::BCS_SEND;
05101 #ifdef _RAKNET_THREADSAFE
05102         bufferedCommands.Push(bcs);
05103 #else
05104         bufferedCommands.WriteUnlock();
05105 #endif
05106 
05107         if (priority==IMMEDIATE_PRIORITY)
05108         {
05109                 // Forces pending sends to go out now, rather than waiting to the next update interval
05110                 quitAndDataEvents.SetEvent();
05111         }
05112 }
05113 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05114 void RakPeer::SendBufferedList( const char **data, const int *lengths, const int numParameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, RemoteSystemStruct::ConnectMode connectionMode, uint32_t receipt )
05115 {
05116         BufferedCommandStruct *bcs;
05117         unsigned int totalLength=0;
05118         unsigned int lengthOffset;
05119         int i;
05120         for (i=0; i < numParameters; i++)
05121         {
05122                 if (lengths[i]>0)
05123                         totalLength+=lengths[i];
05124         }
05125         if (totalLength==0)
05126                 return;
05127 
05128         char *dataAggregate;
05129         dataAggregate = (char*) rakMalloc_Ex( (size_t) totalLength, __FILE__, __LINE__ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
05130         if (dataAggregate==0)
05131         {
05132                 notifyOutOfMemory(__FILE__, __LINE__);
05133                 return;
05134         }
05135         for (i=0, lengthOffset=0; i < numParameters; i++)
05136         {
05137                 if (lengths[i]>0)
05138                 {
05139                         memcpy(dataAggregate+lengthOffset, data[i], lengths[i]);
05140                         lengthOffset+=lengths[i];
05141                 }
05142         }
05143 
05144         if (broadcast==false && IsLoopbackAddress(systemIdentifier.systemAddress,true))
05145         {
05146                 SendLoopback(dataAggregate,totalLength);
05147                 rakFree_Ex(dataAggregate,__FILE__,__LINE__);
05148                 return;
05149         }
05150 
05151 #ifdef _RAKNET_THREADSAFE
05152         bcs=bufferedCommands.Allocate( __FILE__, __LINE__ );
05153 #else
05154         bcs=bufferedCommands.WriteLock();
05155 #endif
05156         bcs->data = dataAggregate;
05157         bcs->numberOfBitsToSend=BYTES_TO_BITS(totalLength);
05158         bcs->priority=priority;
05159         bcs->reliability=reliability;
05160         bcs->orderingChannel=orderingChannel;
05161         bcs->systemIdentifier=systemIdentifier;
05162         bcs->broadcast=broadcast;
05163         bcs->connectionMode=connectionMode;
05164         bcs->receipt=receipt;
05165         bcs->command=BufferedCommandStruct::BCS_SEND;
05166 #ifdef _RAKNET_THREADSAFE
05167         bufferedCommands.Push(bcs);
05168 #else
05169         bufferedCommands.WriteUnlock();
05170 #endif
05171 
05172         if (priority==IMMEDIATE_PRIORITY)
05173         {
05174                 // Forces pending sends to go out now, rather than waiting to the next update interval
05175                 quitAndDataEvents.SetEvent();
05176         }
05177 }
05178 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05179 bool RakPeer::SendImmediate( char *data, BitSize_t numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, bool useCallerDataAllocation, RakNetTimeUS currentTime, uint32_t receipt )
05180 {
05181         unsigned *sendList;
05182         unsigned sendListSize;
05183         bool callerDataAllocationUsed;
05184         unsigned int remoteSystemIndex, sendListIndex; // Iterates into the list of remote systems
05185         unsigned numberOfBytesUsed = (unsigned) BITS_TO_BYTES(numberOfBitsToSend);
05186         callerDataAllocationUsed=false;
05187 
05188         sendListSize=0;
05189 
05190         if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
05191                 remoteSystemIndex=GetIndexFromSystemAddress( systemIdentifier.systemAddress, true );
05192         else if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
05193                 remoteSystemIndex=GetSystemIndexFromGuid(systemIdentifier.rakNetGuid);
05194         else
05195                 remoteSystemIndex=(unsigned int) -1;
05196 
05197         // 03/06/06 - If broadcast is false, use the optimized version of GetIndexFromSystemAddress
05198         if (broadcast==false)
05199         {
05200                 if (remoteSystemIndex==(unsigned int) -1)
05201                 {
05202 #ifdef _DEBUG
05203 //                      int debugIndex = GetRemoteSystemIndex(systemIdentifier.systemAddress);
05204 #endif
05205                         return false;
05206                 }
05207 
05208 #if !defined(_XBOX) && !defined(X360)
05209                 sendList=(unsigned *)alloca(sizeof(unsigned));
05210 #else
05211                 sendList = (unsigned *) rakMalloc_Ex(sizeof(unsigned), __FILE__, __LINE__);
05212 #endif
05213 
05214                 if (remoteSystemList[remoteSystemIndex].isActive &&
05215                         remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP &&
05216                         remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY &&
05217                         remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
05218                 {
05219                         sendList[0]=remoteSystemIndex;
05220                         sendListSize=1;
05221                 }
05222         }
05223         else
05224         {
05225 #if !defined(_XBOX) && !defined(X360)
05226         //sendList=(unsigned *)alloca(sizeof(unsigned)*remoteSystemListSize);
05227                 sendList=(unsigned *)alloca(sizeof(unsigned)*maximumNumberOfPeers);
05228 #else
05229         //sendList = RakNet::OP_NEW<unsigned[remoteSystemListSize]>( __FILE__, __LINE__ );
05230                 sendList = (unsigned *) rakMalloc_Ex(sizeof(unsigned)*maximumNumberOfPeers, __FILE__, __LINE__);
05231 #endif
05232 
05233                 // remoteSystemList in network thread
05234                 unsigned int idx;
05235                 for ( idx = 0; idx < maximumNumberOfPeers; idx++ )
05236                 {
05237                         if (remoteSystemIndex!=(unsigned int) -1 && idx==remoteSystemIndex)
05238                                 continue;
05239 
05240                         if ( remoteSystemList[ idx ].isActive && remoteSystemList[ idx ].systemAddress != UNASSIGNED_SYSTEM_ADDRESS )
05241                                 sendList[sendListSize++]=idx;
05242                 }
05243         }
05244 
05245         if (sendListSize==0)
05246         {
05247 #if defined(_XBOX) && !defined(X360)
05248                                             
05249 #endif
05250                 return false;
05251         }
05252 
05253         for (sendListIndex=0; sendListIndex < sendListSize; sendListIndex++)
05254         {
05255                 if ( trackFrequencyTable )
05256                 {
05257                         unsigned i;
05258                         // Store output frequency
05259                         for (i=0 ; i < numberOfBytesUsed; i++ )
05260                                 frequencyTable[ (unsigned char)(data[i]) ]++;
05261                 }
05262 
05263                 if ( outputTree )
05264                 {
05265                         RakNet::BitStream bitStreamCopy( numberOfBytesUsed );
05266                         outputTree->EncodeArray( (unsigned char*) data, numberOfBytesUsed, &bitStreamCopy );
05267                         rawBytesSent += numberOfBytesUsed;
05268                         compressedBytesSent += (unsigned int) bitStreamCopy.GetNumberOfBytesUsed();
05269                         remoteSystemList[sendList[sendListIndex]].reliabilityLayer.Send( (char*) bitStreamCopy.GetData(), bitStreamCopy.GetNumberOfBitsUsed(), priority, reliability, orderingChannel, true, remoteSystemList[sendList[sendListIndex]].MTUSize, currentTime, receipt );
05270                 }
05271                 else
05272                 {
05273                         // Send may split the packet and thus deallocate data.  Don't assume data is valid if we use the callerAllocationData
05274                         bool useData = useCallerDataAllocation && callerDataAllocationUsed==false && sendListIndex+1==sendListSize;
05275                         remoteSystemList[sendList[sendListIndex]].reliabilityLayer.Send( data, numberOfBitsToSend, priority, reliability, orderingChannel, useData==false, remoteSystemList[sendList[sendListIndex]].MTUSize, currentTime, receipt );
05276                         if (useData)
05277                                 callerDataAllocationUsed=true;
05278                 }
05279 
05280                 if (reliability==RELIABLE ||
05281                         reliability==RELIABLE_ORDERED ||
05282                         reliability==RELIABLE_SEQUENCED ||
05283                         reliability==RELIABLE_WITH_ACK_RECEIPT ||
05284                         reliability==RELIABLE_ORDERED_WITH_ACK_RECEIPT
05285 //                      ||
05286 //                      reliability==RELIABLE_SEQUENCED_WITH_ACK_RECEIPT
05287                         )
05288                         remoteSystemList[sendList[sendListIndex]].lastReliableSend=(RakNetTime)(currentTime/(RakNetTimeUS)1000);
05289         }
05290 
05291 #if defined(_XBOX) && !defined(X360)
05292                                            
05293 #endif
05294 
05295         // 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
05296         return callerDataAllocationUsed;
05297 }
05298 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05299 void RakPeer::ResetSendReceipt(void)
05300 {
05301         sendReceiptSerialMutex.Lock();
05302         sendReceiptSerial=1;
05303         sendReceiptSerialMutex.Unlock();
05304 }
05305 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05306 void RakPeer::OnConnectedPong(RakNetTime sendPingTime, RakNetTime sendPongTime, RemoteSystemStruct *remoteSystem)
05307 {
05308         RakNetTime ping, lastPing;
05309         RakNetTimeUS timeNS = RakNet::GetTimeNS(); // Update the time value to be accurate
05310         RakNetTimeMS timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
05311         if (timeMS > sendPingTime)
05312                 ping = timeMS - sendPingTime;
05313         else
05314                 ping=0;
05315         lastPing = remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime;
05316 
05317         // Ignore super high spikes in the average
05318         if ( lastPing <= 0 || ( ( ping < ( lastPing * 3 ) ) && ping < 1200 ) )
05319         {
05320                 remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime = ( unsigned short ) ping;
05321                 // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
05322                 // Divide each integer by 2, rather than the sum by 2, to prevent overflow
05323                 remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].clockDifferential = sendPongTime - ( timeMS/2 + sendPingTime/2 );
05324 
05325                 if ( remoteSystem->lowestPing == (unsigned short)-1 || remoteSystem->lowestPing > (int) ping )
05326                         remoteSystem->lowestPing = (unsigned short) ping;
05327 
05328                 // Reliability layer calculates its own ping
05329                 // Most packets should arrive by the ping time.
05330                 //RakAssert(ping < 10000); // Sanity check - could hit due to negative pings causing the var to overflow
05331                 //remoteSystem->reliabilityLayer.SetPing( (unsigned short) ping );
05332 
05333                 if ( ++( remoteSystem->pingAndClockDifferentialWriteIndex ) == PING_TIMES_ARRAY_SIZE )
05334                         remoteSystem->pingAndClockDifferentialWriteIndex = 0;
05335         }
05336 }
05337 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05338 void RakPeer::ClearBufferedCommands(void)
05339 {
05340         BufferedCommandStruct *bcs;
05341 
05342 #ifdef _RAKNET_THREADSAFE
05343         while ((bcs=bufferedCommands.Pop())!=0)
05344         {
05345                 if (bcs->data)
05346                         rakFree_Ex(bcs->data, __FILE__, __LINE__ );
05347 
05348                 bufferedCommands.Deallocate(bcs, __FILE__,__LINE__);
05349         }
05350         bufferedCommands.Clear(__FILE__, __LINE__);
05351 #else
05352         while ((bcs=bufferedCommands.ReadLock())!=0)
05353         {
05354                 if (bcs->data)
05355                         rakFree_Ex(bcs->data, __FILE__, __LINE__ );
05356 
05357                 bufferedCommands.ReadUnlock();
05358         }
05359         bufferedCommands.Clear(__FILE__, __LINE__);
05360 #endif
05361 }
05362 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05363 void RakPeer::ClearBufferedPackets(void)
05364 {
05365         RecvFromStruct *bcs;
05366 
05367 #ifdef _RAKNET_THREADSAFE
05368         while ((bcs=bufferedPackets.Pop())!=0)
05369         {
05370                 bufferedPackets.Deallocate(bcs, __FILE__,__LINE__);
05371         }
05372         bufferedPackets.Clear(__FILE__, __LINE__);
05373 #else
05374         while ((bcs=bufferedPackets.ReadLock())!=0)
05375         {
05376                 bufferedPackets.ReadUnlock();
05377         }
05378         bufferedPackets.Clear(__FILE__, __LINE__);
05379 #endif
05380 }
05381 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05382 void RakPeer::ClearSocketQueryOutput(void)
05383 {
05384         socketQueryOutput.Clear(__FILE__, __LINE__);
05385 }
05386 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05387 void RakPeer::ClearRequestedConnectionList(void)
05388 {
05389         DataStructures::Queue<RequestedConnectionStruct*> freeQueue;
05390         requestedConnectionQueueMutex.Lock();
05391         while (requestedConnectionQueue.Size())
05392                 freeQueue.Push(requestedConnectionQueue.Pop(), __FILE__, __LINE__ );
05393         requestedConnectionQueueMutex.Unlock();
05394         unsigned i;
05395         for (i=0; i < freeQueue.Size(); i++)
05396                 RakNet::OP_DELETE(freeQueue[i], __FILE__, __LINE__ );
05397 }
05398 inline void RakPeer::AddPacketToProducer(Packet *p)
05399 {
05400         packetReturnMutex.Lock();
05401         packetReturnQueue.Push(p,__FILE__,__LINE__);
05402         packetReturnMutex.Unlock();
05403 }
05404 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05405 void RakPeer::GenerateGUID(void)
05406 {
05407         // Mac address is a poor solution because you can't have multiple connections from the same system
05408 #if defined(_XBOX) || defined(X360)
05409                                                                                                                                                      
05410 #elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
05411                                                                                                                                                      
05412 #elif defined(_WIN32)
05413         myGuid.g=RakNet::GetTimeUS();
05414 
05415         RakNetTimeUS lastTime, thisTime;
05416         int j;
05417         // Sleep a small random time, then use the last 4 bits as a source of randomness
05418         for (j=0; j < 8; j++)
05419         {
05420                 lastTime = RakNet::GetTimeUS();
05421                 RakSleep(1);
05422                 RakSleep(0);
05423                 thisTime = RakNet::GetTimeUS();
05424                 RakNetTimeUS diff = thisTime-lastTime;
05425                 unsigned int diff4Bits = (unsigned int) (diff & 15);
05426                 diff4Bits <<= 32-4;
05427                 diff4Bits >>= j*4;
05428                 ((char*)&myGuid.g)[j] ^= diff4Bits;
05429         }
05430 
05431 #else
05432         struct timeval tv;
05433         gettimeofday(&tv, NULL); 
05434         myGuid.g=tv.tv_usec + tv.tv_sec * 1000000;
05435 #endif
05436 }
05437 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05438 void ProcessPortUnreachable( unsigned int binaryAddress, unsigned short port, RakPeer *rakPeer )
05439 {
05440         (void) binaryAddress;
05441         (void) port;
05442         (void) rakPeer;
05443 
05444 }
05445 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05446 bool ProcessOfflineNetworkPacket( const SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSmartPtr<RakNetSocket> rakNetSocket, bool *isOfflineMessage, RakNetTimeUS timeRead )
05447 {
05448         (void) timeRead;
05449         RakPeer::RemoteSystemStruct *remoteSystem;
05450         Packet *packet;
05451         unsigned i;
05452 
05453 #if !defined(_XBOX) && !defined(X360)
05454         char str1[64];
05455         systemAddress.ToString(false, str1);
05456         if (rakPeer->IsBanned( str1 ))
05457         {
05458                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05459                         rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
05460 
05461                 RakNet::BitStream bs;
05462                 bs.Write((MessageID)ID_CONNECTION_BANNED);
05463                 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05464                 bs.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
05465 
05466                 unsigned i;
05467                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05468                         rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
05469                 SocketLayer::Instance()->SendTo( rakNetSocket->s, (char*) bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05470 
05471                 return true;
05472         }
05473 #endif
05474 
05475 
05476         // The reason for all this is that the reliability layer has no way to tell between offline messages that arrived late for a player that is now connected,
05477         // and a regular encoding. So I insert OFFLINE_MESSAGE_DATA_ID into the stream, the encoding of which is essentially impossible to hit by random chance
05478         if (length <=2)
05479         {
05480                 *isOfflineMessage=true;
05481         }
05482         else if (
05483                 ((unsigned char)data[0] == ID_PING ||
05484                 (unsigned char)data[0] == ID_PING_OPEN_CONNECTIONS) &&
05485                 length == sizeof(unsigned char) + sizeof(RakNetTime) + sizeof(OFFLINE_MESSAGE_DATA_ID))
05486         {
05487                 *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(RakNetTime), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
05488         }
05489         else if ((unsigned char)data[0] == ID_PONG && (size_t) length >= sizeof(unsigned char) + sizeof(RakNetTime) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
05490         {
05491                 *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(RakNetTime) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
05492         }
05493         else if (
05494                 (unsigned char)data[0] == ID_OUT_OF_BAND_INTERNAL       &&
05495                 (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
05496         {
05497                 *isOfflineMessage=memcmp(data+sizeof(MessageID) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
05498         }
05499         else if (
05500                 (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST    &&
05501                 (size_t) length >= sizeof(MessageID)*2 + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
05502         {
05503                 *isOfflineMessage=memcmp(data+sizeof(MessageID)*2 + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
05504         }
05505         else if (
05506                 (
05507                 (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY ||
05508                 (unsigned char)data[0] == ID_CONNECTION_ATTEMPT_FAILED ||
05509                 (unsigned char)data[0] == ID_NO_FREE_INCOMING_CONNECTIONS ||
05510                 (unsigned char)data[0] == ID_CONNECTION_BANNED ||
05511                 (unsigned char)data[0] == ID_ALREADY_CONNECTED ||
05512                 (unsigned char)data[0] == ID_IP_RECENTLY_CONNECTED ||
05513                 (unsigned char)data[0] == ID_CONNECTION_REQUEST) &&
05514                 (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
05515         {
05516                 *isOfflineMessage=memcmp(data+sizeof(MessageID), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
05517         }
05518         else if (((unsigned char)data[0] == ID_INCOMPATIBLE_PROTOCOL_VERSION&&
05519                 (size_t) length == sizeof(MessageID)*2 + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID)))
05520         {
05521                 *isOfflineMessage=memcmp(data+sizeof(MessageID)*2, OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
05522         }
05523         else
05524         {
05525                 *isOfflineMessage=false;
05526         }
05527 
05528         if (*isOfflineMessage)
05529         {
05530                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05531                         rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
05532 
05533                 // These are all messages from unconnected systems.  Messages here can be any size, but are never processed from connected systems.
05534                 if ( ( (unsigned char) data[ 0 ] == ID_PING_OPEN_CONNECTIONS
05535                         || (unsigned char)(data)[0] == ID_PING) && length == sizeof(unsigned char)+sizeof(RakNetTime)+sizeof(OFFLINE_MESSAGE_DATA_ID) )
05536                 {
05537                         if ( (unsigned char)(data)[0] == ID_PING ||
05538                                 rakPeer->AllowIncomingConnections() ) // Open connections with players
05539                         {
05540 // #if !defined(_XBOX) && !defined(X360)
05541                                 RakNet::BitStream inBitStream( (unsigned char *) data, length, false );
05542                                 inBitStream.IgnoreBits(8);
05543                                 RakNetTime sendPingTime;
05544                                 inBitStream.Read(sendPingTime);
05545 
05546                                 RakNet::BitStream outBitStream;
05547                                 outBitStream.Write((MessageID)ID_PONG); // Should be named ID_UNCONNECTED_PONG eventually
05548                                 outBitStream.Write(sendPingTime);
05549                                 outBitStream.Write(rakPeer->myGuid);
05550                                 outBitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05551 
05552                                 rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Lock();
05553                                 // They are connected, so append offline ping data
05554                                 outBitStream.Write( (char*)rakPeer->offlinePingResponse.GetData(), rakPeer->offlinePingResponse.GetNumberOfBytesUsed() );
05555                                 rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Unlock();
05556 
05557                                 unsigned i;
05558                                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05559                                         rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*)outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), systemAddress);
05560 
05561                                 char str1[64];
05562                                 systemAddress.ToString(false, str1);
05563                                 SocketLayer::Instance()->SendTo( rakNetSocket->s, (const char*)outBitStream.GetData(), (unsigned int) outBitStream.GetNumberOfBytesUsed(), str1 , systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05564 
05565                                 packet=rakPeer->AllocPacket(sizeof(MessageID), __FILE__, __LINE__);
05566                                 packet->data[0]=data[0];
05567                                 packet->systemAddress = systemAddress;
05568                                 packet->guid=UNASSIGNED_RAKNET_GUID;
05569                                 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
05570                                 packet->guid.systemIndex=packet->systemAddress.systemIndex;
05571                                 rakPeer->AddPacketToProducer(packet);
05572 // #endif
05573                         }
05574                 }
05575                 // UNCONNECTED MESSAGE Pong with no data.
05576                 else if ((unsigned char) data[ 0 ] == ID_PONG && (size_t) length >= sizeof(unsigned char)+sizeof(RakNetTime)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID) && (size_t) length < sizeof(unsigned char)+sizeof(RakNetTime)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID)+MAX_OFFLINE_DATA_LENGTH)
05577                 {
05578                         packet=rakPeer->AllocPacket((unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()), __FILE__, __LINE__);
05579                         RakNet::BitStream bs((unsigned char*) data, length, false);
05580                         bs.IgnoreBytes(sizeof(unsigned char)+sizeof(RakNetTime));
05581                         bs.Read(packet->guid);
05582                         packet->data[0]=ID_PONG;
05583                         // Don't endian swap the time, so the user can do so when reading out as a bitstream
05584                         memcpy(packet->data+sizeof(unsigned char), data+sizeof(unsigned char), sizeof(RakNetTime));
05585 //                      RakNetTime test1;
05586 //                      memcpy(&test1,data+sizeof(unsigned char), sizeof(RakNetTime));
05587 //                      RakNetTime test2;
05588 //                      test2=RakNet::GetTime();
05589                         memcpy(packet->data+sizeof(unsigned char)+sizeof(RakNetTime), data+sizeof(unsigned char)+sizeof(RakNetTime)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID), length-sizeof(unsigned char)-sizeof(RakNetTime)-RakNetGUID::size()-sizeof(OFFLINE_MESSAGE_DATA_ID));
05590                         packet->bitSize = BYTES_TO_BITS(packet->length);
05591                         packet->systemAddress = systemAddress;
05592                         packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
05593                         packet->guid.systemIndex=packet->systemAddress.systemIndex;
05594                         rakPeer->AddPacketToProducer(packet);
05595                 }
05596                 else if ((unsigned char) data[ 0 ] == ID_OUT_OF_BAND_INTERNAL &&
05597                         (size_t) length < MAX_OFFLINE_DATA_LENGTH+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)+RakNetGUID::size())
05598                 {
05599                         unsigned int dataLength = (unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()-sizeof(MessageID));
05600                         RakAssert(dataLength<1024);
05601                         packet=rakPeer->AllocPacket(dataLength+sizeof(MessageID), __FILE__, __LINE__);
05602                         RakAssert(packet->length<1024);
05603 
05604                         RakNet::BitStream bs2((unsigned char*) data, length, false);
05605                         bs2.IgnoreBytes(sizeof(MessageID));
05606                         bs2.Read(packet->guid);
05607 
05608                         if (data[sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID) + RakNetGUID::size()]==ID_ADVERTISE_SYSTEM)
05609                         {
05610                                 packet->length--;
05611                                 packet->bitSize=BYTES_TO_BITS(packet->length);
05612                                 packet->data[0]=ID_ADVERTISE_SYSTEM;
05613                                 memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)*2 + RakNetGUID::size(), dataLength);
05614                         }
05615                         else
05616                         {
05617                                 packet->data[0]=ID_OUT_OF_BAND_INTERNAL;
05618                                 memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID) + RakNetGUID::size(), dataLength);
05619                         }
05620 
05621                         packet->systemAddress = systemAddress;
05622                         packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
05623                         packet->guid.systemIndex=packet->systemAddress.systemIndex;
05624                         rakPeer->AddPacketToProducer(packet);
05625                 }
05626                 else if ((unsigned char)(data)[0] == (MessageID)ID_OPEN_CONNECTION_REPLY)
05627                 {
05628                         for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05629                                 rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
05630 
05631                         RakNet::BitStream bs((unsigned char*) data,length,false);
05632                         bs.IgnoreBytes(sizeof(MessageID));
05633                         bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
05634                         RakNetGUID guid;
05635                         bs.Read(guid);
05636                         SystemAddress bindingAddress;
05637                         bs.Read(bindingAddress);
05638 
05639                         RakPeer::RequestedConnectionStruct *rcs;
05640                         bool unlock=true;
05641                         unsigned i;
05642                         rakPeer->requestedConnectionQueueMutex.Lock();
05643                         for (i=0; i <  rakPeer->requestedConnectionQueue.Size(); i++)
05644                         {
05645                                 rcs=rakPeer->requestedConnectionQueue[i];
05646                                 if (rcs->systemAddress==systemAddress)
05647                                 {
05648                                         rakPeer->requestedConnectionQueueMutex.Unlock();
05649                                         unlock=false;
05650 
05651                                         RakAssert(rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT);
05652                                         // You might get this when already connected because of cross-connections
05653                                         bool thisIPConnectedRecently=false;
05654                                         remoteSystem=rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
05655                                         // Removeme
05656                                         // printf("1 p=%i\n", rakPeer->mySystemAddress->port);
05657                                         if (remoteSystem==0)
05658                                         {
05659                                                 // Removeme
05660                                                 // printf("2 p=%i\n", rakPeer->mySystemAddress->port);
05661                                                 if (rcs->socket.IsNull())
05662                                                 {
05663                                                         // Removeme
05664                                                         // printf("3 p=%i\n", rakPeer->mySystemAddress->port);
05665                                                         remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, length+UDP_HEADER_SIZE, guid);
05666                                                 }
05667                                                 else
05668                                                 {
05669                                                         // Removeme
05670                                                         // printf("4 p=%i\n", rakPeer->mySystemAddress->port);
05671                                                         remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rcs->socket, &thisIPConnectedRecently, bindingAddress, length+UDP_HEADER_SIZE, guid);
05672                                                 }
05673 
05674 
05675                                                 //                                              printf("System %i got ID_OPEN_CONNECTION_REPLY from %i\n", rakPeer->mySystemAddress[0].port, systemAddress.port);
05676                                         }
05677 
05678                                         // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
05679                                         // Ignore connection attempts if this IP address connected within the last 100 milliseconds
05680                                         if (thisIPConnectedRecently==false)
05681                                         {
05682                                                 // Don't check GetRemoteSystemFromGUID, server will verify
05683                                                 if (remoteSystem)
05684                                                 {
05685                                                         // RakNetTimeUS time = RakNet::GetTimeNS();
05686                                                         remoteSystem->weInitiatedTheConnection=true;
05687                                                         remoteSystem->connectMode=RakPeer::RemoteSystemStruct::REQUESTED_CONNECTION;
05688                                                         if (rcs->timeoutTime!=0)
05689                                                                 remoteSystem->reliabilityLayer.SetTimeoutTime(rcs->timeoutTime);
05690 
05691 
05692                                                         RakNet::BitStream temp;
05693                                                         temp.Write( (MessageID)ID_CONNECTION_REQUEST );
05694                                                         temp.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05695                                                         temp.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
05696                                                         temp.Write(RakNet::GetTime());
05697 
05698                                                         if ( rcs->outgoingPasswordLength > 0 )
05699                                                                 temp.Write( ( char* ) rcs->outgoingPassword,  rcs->outgoingPasswordLength );
05700 
05701                                                         rakPeer->SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, timeRead, 0 );
05702                                                 }
05703                                                 else
05704                                                 {
05705                                                         // Failed, no connections available anymore
05706                                                         packet=rakPeer->AllocPacket(sizeof( char ), __FILE__, __LINE__);
05707                                                         packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
05708                                                         packet->bitSize = ( sizeof( char ) * 8);
05709                                                         packet->systemAddress = rcs->systemAddress;
05710                                                         packet->guid=guid;
05711                                                         rakPeer->AddPacketToProducer(packet);
05712                                                 }
05713                                         }
05714 
05715                                         rakPeer->requestedConnectionQueueMutex.Lock();
05716                                         for (unsigned int k=0; k < rakPeer->requestedConnectionQueue.Size(); k++)
05717                                         {
05718                                                 if (rakPeer->requestedConnectionQueue[k]->systemAddress==systemAddress)
05719                                                 {
05720                                                         rakPeer->requestedConnectionQueue.RemoveAtIndex(k);
05721                                                         break;
05722                                                 }
05723                                         }
05724                                         rakPeer->requestedConnectionQueueMutex.Unlock();
05725 
05726                                         RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
05727 
05728                                         break;
05729                                 }
05730                         }
05731 
05732                         if (unlock)
05733                                 rakPeer->requestedConnectionQueueMutex.Unlock();
05734 
05735                         return true;
05736 
05737                 }
05738                 else if ((unsigned char)(data)[0] == (MessageID)ID_CONNECTION_ATTEMPT_FAILED ||
05739                         (unsigned char)(data)[0] == (MessageID)ID_NO_FREE_INCOMING_CONNECTIONS ||
05740                         (unsigned char)(data)[0] == (MessageID)ID_CONNECTION_BANNED ||
05741                         (unsigned char)(data)[0] == (MessageID)ID_ALREADY_CONNECTED ||
05742                         (unsigned char)(data)[0] == (MessageID)ID_INVALID_PASSWORD ||
05743                         (unsigned char)(data)[0] == (MessageID)ID_IP_RECENTLY_CONNECTED ||
05744                         (unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
05745                 {
05746 
05747                         RakNet::BitStream bs((unsigned char*) data,length,false);
05748                         bs.IgnoreBytes(sizeof(MessageID));
05749                         bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
05750                         if ((unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
05751                                 bs.IgnoreBytes(sizeof(unsigned char));
05752 
05753                         RakNetGUID guid;
05754                         bs.Read(guid);
05755 
05756                         RakPeer::RequestedConnectionStruct *rcs;
05757                         bool connectionAttemptCancelled=false;
05758                         unsigned i;
05759                         rakPeer->requestedConnectionQueueMutex.Lock();
05760                         for (i=0; i <  rakPeer->requestedConnectionQueue.Size(); i++)
05761                         {
05762                                 rcs=rakPeer->requestedConnectionQueue[i];
05763                                 if (rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT && rcs->systemAddress==systemAddress)
05764                                 {
05765                                         connectionAttemptCancelled=true;
05766 #if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
05767                                                                                 
05768 #endif
05769 
05770                                         rakPeer->requestedConnectionQueue.RemoveAtIndex(i);
05771                                         RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
05772                                         break;
05773                                 }
05774                         }
05775 
05776                         rakPeer->requestedConnectionQueueMutex.Unlock();
05777 
05778                         if (connectionAttemptCancelled)
05779                         {
05780                                 // Tell user of connection attempt failed
05781                                 packet=rakPeer->AllocPacket(sizeof( char ), __FILE__, __LINE__);
05782                                 packet->data[ 0 ] = data[0]; // Attempted a connection and couldn't
05783                                 packet->bitSize = ( sizeof( char ) * 8);
05784                                 packet->systemAddress = systemAddress;
05785                                 packet->guid=guid;
05786                                 rakPeer->AddPacketToProducer(packet);
05787                         }
05788                 }
05789                 else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST && length >= sizeof(unsigned char)*2)
05790                 {
05791                         //                      if (rakPeer->mySystemAddress[0].port!=60481)
05792                         //                              return;
05793 
05794                         unsigned int i;
05795                         //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
05796                         char remoteProtocol=data[1];
05797                         if (remoteProtocol!=RAKNET_PROTOCOL_VERSION)
05798                         {
05799                                 RakNet::BitStream bs;
05800                                 bs.Write((MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION);
05801                                 bs.Write((unsigned char)RAKNET_PROTOCOL_VERSION);
05802                                 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05803                                 bs.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
05804 
05805                                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05806                                         rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*)bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
05807 
05808                                 SocketLayer::Instance()->SendTo( rakNetSocket->s, (char*)bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05809                                 return true;
05810                         }
05811 
05812                         for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05813                                 rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, systemAddress);
05814 
05815                         RakNetGUID guid;
05816                         RakNet::BitStream bsOut;
05817                         RakNet::BitStream bs((unsigned char*) data, length, false);
05818                         bs.IgnoreBytes(sizeof(MessageID)*2);
05819                         bs.Read(guid);
05820                         bs.AlignReadToByteBoundary();
05821                         bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
05822                         SystemAddress bindingAddress;
05823                         bs.Read(bindingAddress);
05824 
05825                         RakPeer::RemoteSystemStruct *rssFromSA = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
05826                         bool IPAddrInUse = rssFromSA != 0 && rssFromSA->isActive;
05827                         RakPeer::RemoteSystemStruct *rssFromGuid = rakPeer->GetRemoteSystemFromGUID(guid, true);
05828                         bool GUIDInUse = rssFromGuid != 0 && rssFromGuid->isActive;
05829 
05830                         // IPAddrInUse, GuidInUse, outcome
05831                         // TRUE,          , TRUE         , ID_OPEN_CONNECTION_REPLY if they are the same, else ID_ALREADY_CONNECTED
05832                         // FALSE,     , TRUE     , ID_ALREADY_CONNECTED (someone else took this guid)
05833                         // TRUE,          , FALSE        , ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
05834                         // FALSE          , FALSE        , Allow connection
05835 
05836                         int outcome;
05837                         if (IPAddrInUse & GUIDInUse)
05838                         {
05839                                 if (rssFromSA==rssFromGuid && rssFromSA->connectMode==RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER)
05840                                 {
05841                                         // ID_OPEN_CONNECTION_REPLY if they are the same
05842                                         outcome=1;
05843                                 }
05844                                 else
05845                                 {
05846                                         // ID_ALREADY_CONNECTED (restarted raknet, connected again from same ip, plus someone else took this guid)
05847                                         outcome=2;
05848                                 }
05849                         }
05850                         else if (IPAddrInUse==false && GUIDInUse==true)
05851                         {
05852                                 // ID_ALREADY_CONNECTED (someone else took this guid)
05853                                 outcome=3;
05854                         }
05855                         else if (IPAddrInUse==true && GUIDInUse==false)
05856                         {
05857                                 // ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
05858                                 outcome=4;
05859                         }
05860                         else
05861                         {
05862                                 // Allow connection
05863                                 outcome=0;
05864                         }
05865 
05866                         if (outcome==1)
05867                         {
05868                                 // Duplicate connection request packet
05869                                 bsOut.Write((MessageID)ID_OPEN_CONNECTION_REPLY);
05870                                 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05871                                 bsOut.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
05872                                 bsOut.Write(systemAddress);
05873                                 bsOut.PadWithZeroToByteLength(length); // Pad to the same MTU
05874                                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05875                                         rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
05876                                 SocketLayer::SetDoNotFragment(rakNetSocket->s, 1);
05877                                 SocketLayer::Instance()->SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05878                                 SocketLayer::SetDoNotFragment(rakNetSocket->s, 0);
05879                                 return true;
05880                         }
05881                         else if (outcome!=0)
05882                         {
05883                                 bsOut.Write((MessageID)ID_ALREADY_CONNECTED);
05884                                 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05885                                 bsOut.Write(guid);
05886                                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05887                                         rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
05888                                 SocketLayer::Instance()->SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05889 
05890                                 return true;
05891                         }
05892 
05893                         if (rakPeer->AllowIncomingConnections()==false)
05894                         {
05895                                 bsOut.Write((MessageID)ID_NO_FREE_INCOMING_CONNECTIONS);
05896                                 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05897                                 bsOut.Write(guid);
05898                                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05899                                         rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
05900                                 SocketLayer::Instance()->SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05901 
05902                                 return true;
05903                         }
05904 
05905                         bool thisIPConnectedRecently=false;
05906                         rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, length+UDP_HEADER_SIZE, guid);
05907 
05908                         if (thisIPConnectedRecently==true)
05909                         {
05910                                 bsOut.Write((MessageID)ID_IP_RECENTLY_CONNECTED);
05911                                 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05912                                 bsOut.Write(guid);
05913                                 for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05914                                         rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
05915                                 SocketLayer::Instance()->SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05916 
05917                                 return true;
05918                         }
05919 
05920                         bsOut.Write((MessageID)ID_OPEN_CONNECTION_REPLY);
05921                         bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
05922                         bsOut.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
05923                         bsOut.Write(systemAddress);
05924                         bsOut.PadWithZeroToByteLength(length); // Pad to the same MTU
05925                         for (i=0; i < rakPeer->messageHandlerList.Size(); i++)
05926                                 rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
05927                         SocketLayer::SetDoNotFragment(rakNetSocket->s, 1);
05928                         SocketLayer::Instance()->SendTo( rakNetSocket->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress.binaryAddress, systemAddress.port, rakNetSocket->remotePortRakNetWasStartedOn_PS3 );
05929                         SocketLayer::SetDoNotFragment(rakNetSocket->s, 0);
05930 
05931 
05932                 }
05933                 return true;
05934         }
05935 
05936         return false;
05937 }
05938 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05939 void ProcessNetworkPacket( const SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetTimeUS timeRead )
05940 {
05941         ProcessNetworkPacket(systemAddress,data,length,rakPeer,rakPeer->socketList[0],timeRead);
05942 }
05943 void ProcessNetworkPacket( const SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSmartPtr<RakNetSocket> rakNetSocket, RakNetTimeUS timeRead )
05944 {
05945         RakAssert(systemAddress.port);
05946         bool isOfflineMessage;
05947         if (ProcessOfflineNetworkPacket(systemAddress, data, length, rakPeer, rakNetSocket, &isOfflineMessage, timeRead))
05948         {
05949                 return;
05950         }
05951 
05952         Packet *packet;
05953         RakPeer::RemoteSystemStruct *remoteSystem;
05954 
05955         // See if this datagram came from a connected system
05956         remoteSystem = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
05957         if ( remoteSystem )
05958         {
05959                 if (remoteSystem->connectMode==RakPeer::RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET && (length & 15)==0) // & 15 = mod 16
05960                 {
05961                         // Test the key before setting it
05962                         unsigned int newLength;
05963                         char output[ MAXIMUM_MTU_SIZE ];
05964                         DataBlockEncryptor testEncryptor;
05965                         testEncryptor.SetKey(remoteSystem->AESKey);
05966                         //if ( testEncryptor.Decrypt( ( unsigned char* ) data, length, (unsigned char*) output,&newLength ) == true )
05967                         if ( testEncryptor.Decrypt( ( unsigned char* ) data, length, (unsigned char*) output, &newLength ) == true )
05968                                 remoteSystem->reliabilityLayer.SetEncryptionKey( remoteSystem->AESKey);
05969                 }
05970 
05971                 // Handle regular incoming data
05972                 // HandleSocketReceiveFromConnectedPlayer is only safe to be called from the same thread as Update, which is this thread
05973                 if ( isOfflineMessage==false)
05974                 {
05975                         if (remoteSystem->reliabilityLayer.HandleSocketReceiveFromConnectedPlayer( 
05976                                 data, length, systemAddress, rakPeer->messageHandlerList, remoteSystem->MTUSize,
05977                                 rakNetSocket->s, &rnr, rakNetSocket->remotePortRakNetWasStartedOn_PS3, timeRead) == false)
05978                         {
05979                                 // These kinds of packets may have been duplicated and incorrectly determined to be
05980                                 // cheat packets.  Anything else really is a cheat packet
05981                                 if ( !(
05982                                         ( (unsigned char)data[0] == ID_CONNECTION_BANNED  ) ||
05983                                         ( (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST ) ||
05984                                         ( (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY ) ||
05985                                         ( (unsigned char)data[0] == ID_CONNECTION_ATTEMPT_FAILED ) ||
05986                                         ( (unsigned char)data[0] == ID_IP_RECENTLY_CONNECTED ) ||
05987                                         ( (unsigned char)data[0] == ID_INCOMPATIBLE_PROTOCOL_VERSION ))
05988                                         )
05989                                 {
05990                                         // Unknown message.  Could be caused by old out of order stuff from unconnected or no longer connected systems, etc.
05991                                         packet=rakPeer->AllocPacket(1, __FILE__, __LINE__);
05992                                         packet->data[ 0 ] = ID_MODIFIED_PACKET;
05993                                         packet->bitSize = sizeof( char ) * 8;
05994                                         packet->systemAddress = systemAddress;
05995                                         packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
05996                                         packet->guid=remoteSystem->guid;
05997                                         packet->guid.systemIndex=packet->systemAddress.systemIndex;
05998                                         rakPeer->AddPacketToProducer(packet);
05999                                 }
06000                         }
06001                 }
06002         }
06003 }
06004 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
06005 unsigned int RakPeer::GenerateSeedFromGuid(void)
06006 {
06007         /*
06008         // Construct a random seed based on the initial guid value, and the last digits of the difference to each subsequent number
06009         // This assumes that only the last 3 bits of each guidId integer has a meaningful amount of randomness between it and the prior number
06010         unsigned int t = guid.g[0];
06011         unsigned int i;
06012         for (i=1; i < sizeof(guid.g) / sizeof(guid.g[0]); i++)
06013         {
06014                 unsigned int diff = guid.g[i]-guid.g[i-1];
06015                 unsigned int diff3Bits = diff & 0x0007;
06016                 diff3Bits <<= 29;
06017                 diff3Bits >>= (i-1)*3;
06018                 t ^= diff3Bits;
06019         }
06020 
06021         return t;
06022         */
06023         return (unsigned int) ((myGuid.g >> 32) ^ myGuid.g);
06024 }
06025 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
06026 void RakPeer::DerefAllSockets(void)
06027 {
06028         unsigned int i;
06029         for (i=0; i < socketList.Size(); i++)
06030         {
06031                 socketList[i].SetNull();
06032         }
06033         socketList.Clear(false, __FILE__, __LINE__);
06034 }
06035 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
06036 unsigned int RakPeer::GetRakNetSocketFromUserConnectionSocketIndex(unsigned int userIndex) const
06037 {
06038         unsigned int i;
06039         for (i=0; i < socketList.Size(); i++)
06040         {
06041                 if (socketList[i]->userConnectionSocketIndex==userIndex)
06042                         return i;
06043         }
06044         RakAssert("GetRakNetSocketFromUserConnectionSocketIndex failed" && 0);
06045         return (unsigned int) -1;
06046 }
06047 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
06048 bool RakPeer::RunUpdateCycle( void )
06049 {
06050         RakPeer::RemoteSystemStruct * remoteSystem;
06051         unsigned remoteSystemIndex;
06052         Packet *packet;
06053         // int currentSentBytes,currentReceivedBytes;
06054 //      unsigned numberOfBytesUsed;
06055         BitSize_t numberOfBitsUsed;
06056         //SystemAddress authoritativeClientSystemAddress;
06057         BitSize_t bitSize;
06058         unsigned int byteSize;
06059         unsigned char *data;
06060         RakNetTimeUS timeNS;
06061         RakNetTime timeMS;
06062         SystemAddress systemAddress;
06063         BufferedCommandStruct *bcs;
06064         bool callerDataAllocationUsed;
06065         RakNetStatistics *rnss;
06066 
06067         /*
06068         int errorCode;
06069         int gotData;
06070         unsigned connectionSocketIndex;
06071         for (connectionSocketIndex=0; connectionSocketIndex < socketList.Size(); connectionSocketIndex++)
06072         {
06073                 do
06074                 {
06075                         gotData = SocketLayer::Instance()->RecvFrom( socketList[connectionSocketIndex]->s, this, &errorCode, socketList[connectionSocketIndex], socketList[connectionSocketIndex]->remotePortRakNetWasStartedOn_PS3 );
06076 
06077                         if ( gotData == -1 )
06078                         {
06079 #ifdef _WIN32
06080                                 if ( errorCode == WSAECONNRESET )
06081                                 {
06082                                         gotData=false;
06083                                 }
06084                                 else
06085                                         if ( errorCode != 0 && endThreads == false )
06086                                         {
06087 #ifdef _DO_PRINTF
06088                                                 RAKNET_DEBUG_PRINTF( "Server RecvFrom critical failure!\n" );
06089 #endif
06090                                                 // Some kind of critical error
06091                                                 // peer->isRecvfromThreadActive=false;
06092                                                 endThreads = true;
06093                                                 Shutdown( 0, 0 );
06094                                                 return false;
06095                                         }
06096 
06097 #else
06098                                 if ( errorCode == -1 )
06099                                 {
06100                                         // isRecvfromThreadActive=false;
06101                                         endThreads = true;
06102                                         Shutdown( 0 );
06103                                         return false;
06104                                 }
06105 #endif
06106                         }
06107 
06108                         if ( endThreads )
06109                                 return false;
06110                 }
06111                 while ( gotData>0 ); // Read until there is nothing left
06112         }
06113         */
06114 
06115         // This is here so RecvFromBlocking actually gets data from the same thread
06116         if (SocketLayer::Instance()->GetSocketLayerOverride())
06117         {
06118                 SystemAddress sender;
06119                 char dataOut[ MAXIMUM_MTU_SIZE ];
06120                 int len = SocketLayer::Instance()->GetSocketLayerOverride()->RakNetRecvFrom(socketList[0]->s,this,dataOut,&sender,true);
06121                 if (len>0)
06122                 {
06123                         ProcessNetworkPacket( sender, dataOut, len, this, socketList[0], RakNet::GetTimeUS() );
06124                         return 1;
06125                 }
06126         }
06127 
06128         unsigned int socketListIndex;
06129         RakPeer::RecvFromStruct *recvFromStruct;
06130         while ((recvFromStruct=bufferedPackets.PopInaccurate())!=0)
06131         {
06132                 for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
06133                 {
06134                         if (socketList[socketListIndex]->s==recvFromStruct->s)
06135                                 break;
06136                 }
06137                 if (socketListIndex!=socketList.Size())
06138                         ProcessNetworkPacket(recvFromStruct->systemAddress, recvFromStruct->data, recvFromStruct->bytesRead, this, socketList[socketListIndex], recvFromStruct->timeRead);
06139                 bufferedPackets.Deallocate(recvFromStruct, __FILE__,__LINE__);
06140         }
06141 
06142 
06143         timeNS=0;
06144         timeMS=0;
06145 
06146 #ifdef _RAKNET_THREADSAFE
06147         while ((bcs=bufferedCommands.PopInaccurate())!=0)
06148 #else
06149         // Process all the deferred user thread Send and connect calls
06150         while ((bcs=bufferedCommands.ReadLock())!=0)
06151 #endif
06152         {
06153                 if (bcs->command==BufferedCommandStruct::BCS_SEND)
06154                 {
06155                         // GetTime is a very slow call so do it once and as late as possible
06156                         if (timeNS==0)
06157                         {
06158                                 timeNS = RakNet::GetTimeNS();
06159                                 timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
06160                         }
06161 
06162                         callerDataAllocationUsed=SendImmediate((char*)bcs->data, bcs->numberOfBitsToSend, bcs->priority, bcs->reliability, bcs->orderingChannel, bcs->systemIdentifier, bcs->broadcast, true, timeNS, bcs->receipt);
06163                         if ( callerDataAllocationUsed==false )
06164                                 rakFree_Ex(bcs->data, __FILE__, __LINE__ );
06165 
06166                         // Set the new connection state AFTER we call sendImmediate in case we are setting it to a disconnection state, which does not allow further sends
06167                         if (bcs->connectionMode!=RemoteSystemStruct::NO_ACTION )
06168                         {
06169                                 remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
06170                                 if (remoteSystem)
06171                                         remoteSystem->connectMode=bcs->connectionMode;
06172                         }
06173                 }
06174                 else if (bcs->command==BufferedCommandStruct::BCS_CLOSE_CONNECTION)
06175                 {
06176                         CloseConnectionInternal(bcs->systemIdentifier, false, true, bcs->orderingChannel, bcs->priority);
06177                 }
06178                 else if (bcs->command==BufferedCommandStruct::BCS_CHANGE_SYSTEM_ADDRESS)
06179                 {
06180                         // Reroute
06181                         RakPeer::RemoteSystemStruct *rssFromGuid = GetRemoteSystem(bcs->systemIdentifier.rakNetGuid,true,true);
06182                         if (rssFromGuid!=0)
06183                         {
06184                                 unsigned int existingSystemIndex = GetRemoteSystemIndex(rssFromGuid->systemAddress);
06185                                 ReferenceRemoteSystem(bcs->systemIdentifier.systemAddress, existingSystemIndex);
06186                         }
06187                 }
06188                 else if (bcs->command==BufferedCommandStruct::BCS_GET_SOCKET)
06189                 {
06190                         SocketQueryOutput *sqo;
06191                         if (bcs->systemIdentifier.IsUndefined())
06192                         {
06193 #ifdef _RAKNET_THREADSAFE
06194                                 sqo = socketQueryOutput.Allocate( __FILE__, __LINE__ );
06195                                 sqo->sockets=socketList;
06196                                 socketQueryOutput.Push(sqo);
06197 #else
06198                                 sqo = socketQueryOutput.WriteLock();
06199                                 sqo->sockets=socketList;
06200                                 socketQueryOutput.WriteUnlock();
06201 #endif
06202                         }
06203                         else
06204                         {
06205                                 remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
06206 #ifdef _RAKNET_THREADSAFE
06207                                 sqo = socketQueryOutput.Allocate( __FILE__, __LINE__ );
06208 #else
06209                                 sqo = socketQueryOutput.WriteLock();
06210 #endif
06211                                 sqo->sockets.Clear(false, __FILE__, __LINE__);
06212                                 if (remoteSystem)
06213                                 {
06214                                         sqo->sockets.Push(remoteSystem->rakNetSocket, __FILE__, __LINE__ );
06215                                 }
06216                                 else
06217                                 {
06218                                         // Leave empty smart pointer
06219                                 }
06220 #ifdef _RAKNET_THREADSAFE
06221                                 socketQueryOutput.Push(sqo);
06222 #else
06223                                 socketQueryOutput.WriteUnlock();
06224 #endif
06225                         }
06226 
06227                 }
06228 
06229 #ifdef _DEBUG
06230                 bcs->data=0;
06231 #endif
06232 
06233 #ifdef _RAKNET_THREADSAFE
06234                 bufferedCommands.Deallocate(bcs, __FILE__,__LINE__);
06235 #else
06236                 bufferedCommands.ReadUnlock();
06237 #endif
06238         }
06239 
06240         if (requestedConnectionQueue.IsEmpty()==false)
06241         {
06242                 if (timeNS==0)
06243                 {
06244                         timeNS = RakNet::GetTimeNS();
06245                         timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
06246                 }
06247 
06248                 bool condition1, condition2;
06249                 RequestedConnectionStruct *rcs;
06250                 unsigned requestedConnectionQueueIndex=0;
06251                 requestedConnectionQueueMutex.Lock();
06252                 while (requestedConnectionQueueIndex < requestedConnectionQueue.Size())
06253                 {
06254                         rcs = requestedConnectionQueue[requestedConnectionQueueIndex];
06255                         requestedConnectionQueueMutex.Unlock();
06256                         if (rcs->nextRequestTime < timeMS)
06257                         {
06258                                 condition1=rcs->requestsMade==rcs->sendConnectionAttemptCount+1;
06259                                 condition2=(bool)((rcs->systemAddress==UNASSIGNED_SYSTEM_ADDRESS)==1);
06260                                 // If too many requests made or a hole then remove this if possible, otherwise invalidate it
06261                                 if (condition1 || condition2)
06262                                 {
06263                                         if (rcs->data)
06264                                         {
06265                                                 rakFree_Ex(rcs->data, __FILE__, __LINE__ );
06266                                                 rcs->data=0;
06267                                         }
06268 
06269                                         if (condition1 && !condition2 && rcs->actionToTake==RequestedConnectionStruct::CONNECT)
06270                                         {
06271                                                 // Tell user of connection attempt failed
06272                                                 packet=AllocPacket(sizeof( char ), __FILE__, __LINE__);
06273                                                 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
06274                                                 packet->bitSize = ( sizeof(      char ) * 8);
06275                                                 packet->systemAddress = rcs->systemAddress;
06276                                                 AddPacketToProducer(packet);
06277                                         }
06278 
06279                                         RakNet::OP_DELETE(rcs,__FILE__,__LINE__);
06280 
06281                                         requestedConnectionQueueMutex.Lock();
06282                                         for (unsigned int k=0; k < requestedConnectionQueue.Size(); k++)
06283                                         {
06284                                                 if (requestedConnectionQueue[k]==rcs)
06285                                                 {
06286                                                         requestedConnectionQueue.RemoveAtIndex(k);
06287                                                         break;
06288                                                 }
06289                                         }
06290                                         requestedConnectionQueueMutex.Unlock();
06291                                 }
06292                                 else
06293                                 {
06294 
06295                                         int MTUSizeIndex = rcs->requestsMade / (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES);
06296                                         if (MTUSizeIndex>=NUM_MTU_SIZES)
06297                                                 MTUSizeIndex=NUM_MTU_SIZES-1;
06298                                         rcs->requestsMade++;
06299                                         rcs->nextRequestTime=timeMS+rcs->timeBetweenSendConnectionAttemptsMS;
06300                 //                      char c[MAXIMUM_MTU_SIZE];
06301                 //                      c[0] = ID_OPEN_CONNECTION_REQUEST;
06302                 //                      c[1] = RAKNET_PROTOCOL_VERSION;
06303 
06304                                         RakNet::BitStream bitStream;
06305                                         bitStream.Write((MessageID)ID_OPEN_CONNECTION_REQUEST);
06306                                         bitStream.Write((MessageID)RAKNET_PROTOCOL_VERSION);
06307                                         bitStream.Write(myGuid);
06308                                         bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
06309                                         bitStream.Write(rcs->systemAddress);
06310                                         // Pad out to MTU test size
06311                                         bitStream.PadWithZeroToByteLength(mtuSizes[MTUSizeIndex]-UDP_HEADER_SIZE);
06312 
06313 //                                      bool isProperOfflineMessage=memcmp(bitStream.GetData()+sizeof(MessageID)*2 + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
06314 //                                      RakAssert(isProperOfflineMessage);
06315 
06316                                         char str[256];
06317                                         rcs->systemAddress.ToString(true,str);
06318 
06319                                         //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
06320 
06321                                         unsigned i;
06322                                         for (i=0; i < messageHandlerList.Size(); i++)
06323                                                 messageHandlerList[i]->OnDirectSocketSend((const char*) bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), rcs->systemAddress);
06324 
06325                                         if (rcs->socket.IsNull())
06326                                         {
06327                                                 SocketLayer::SetDoNotFragment(socketList[rcs->socketIndex]->s, 1);
06328                                                 if (SocketLayer::Instance()->SendTo( socketList[rcs->socketIndex]->s, (const char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), rcs->systemAddress.binaryAddress, rcs->systemAddress.port, socketList[rcs->socketIndex]->remotePortRakNetWasStartedOn_PS3 )==-10040)
06329                                                 {
06330                                                         // Don't use this MTU size again
06331                                                         rcs->requestsMade = (unsigned char) ((MTUSizeIndex + 1) * (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES));
06332                                                         rcs->nextRequestTime=timeMS;
06333                                                 }
06334                                                 SocketLayer::SetDoNotFragment(socketList[rcs->socketIndex]->s, 0);
06335                                         }
06336                                         else
06337                                         {
06338                                                 SocketLayer::SetDoNotFragment(rcs->socket->s, 1);
06339                                                 if (SocketLayer::Instance()->SendTo( rcs->socket->s, (const char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), rcs->systemAddress.binaryAddress, rcs->systemAddress.port, socketList[rcs->socketIndex]->remotePortRakNetWasStartedOn_PS3 )==-10040)
06340                                                 {
06341                                                         // Don't use this MTU size again
06342                                                         rcs->requestsMade = (unsigned char) ((MTUSizeIndex + 1) * (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES));
06343                                                         rcs->nextRequestTime=timeMS;
06344                                                 }
06345                                                 SocketLayer::SetDoNotFragment(socketList[rcs->socketIndex]->s, 0);
06346                                         }
06347                                 //      printf("ID_OPEN_CONNECTION_REQUEST\n");
06348 
06349                                         requestedConnectionQueueIndex++;
06350                                 }
06351                         }
06352                         else
06353                                 requestedConnectionQueueIndex++;
06354 
06355                         requestedConnectionQueueMutex.Lock();
06356                 }
06357                 requestedConnectionQueueMutex.Unlock();
06358         }
06359 
06360         // remoteSystemList in network thread
06361         for ( remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
06362         //for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; ++remoteSystemIndex )
06363         {
06364                 // I'm using systemAddress from remoteSystemList but am not locking it because this loop is called very frequently and it doesn't
06365                 // matter if we miss or do an extra update.  The reliability layers themselves never care which player they are associated with
06366                 //systemAddress = remoteSystemList[ remoteSystemIndex ].systemAddress;
06367                 // Allow the systemAddress for this remote system list to change.  We don't care if it changes now.
06368         //      remoteSystemList[ remoteSystemIndex ].allowSystemAddressAssigment=true;
06369                 if ( remoteSystemList[ remoteSystemIndex ].isActive )
06370                 {
06371                         systemAddress = remoteSystemList[ remoteSystemIndex ].systemAddress;
06372                         RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
06373 
06374                         // Found an active remote system
06375                         remoteSystem = remoteSystemList + remoteSystemIndex;
06376                         // Update is only safe to call from the same thread that calls HandleSocketReceiveFromConnectedPlayer,
06377                         // which is this thread
06378 
06379                         if (timeNS==0)
06380                         {
06381                                 timeNS = RakNet::GetTimeNS();
06382                                 timeMS = (RakNetTime)(timeNS/(RakNetTimeUS)1000);
06383                                 //RAKNET_DEBUG_PRINTF("timeNS = %I64i timeMS=%i\n", timeNS, timeMS);
06384                         }
06385 
06386 
06387                         if (timeMS > remoteSystem->lastReliableSend && timeMS-remoteSystem->lastReliableSend > defaultTimeoutTime/2 && remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
06388                         {
06389                                 // If no reliable packets are waiting for an ack, do a one byte reliable send so that disconnections are noticed
06390                                 RakNetStatistics rakNetStatistics;
06391                                 rnss=remoteSystem->reliabilityLayer.GetStatistics(&rakNetStatistics);
06392                                 if (rnss->messagesInResendBuffer==0)
06393                                 {
06394                                         PingInternal( systemAddress, true, RELIABLE );
06395                                         /*
06396                                         unsigned char keepAlive=ID_DETECT_LOST_CONNECTIONS;
06397                                         SendImmediate((char*)&keepAlive,8,LOW_PRIORITY, RELIABLE, 0, remoteSystem->systemAddress, false, false, timeNS);
06398                                         */
06399                                         //remoteSystem->lastReliableSend=timeMS+remoteSystem->reliabilityLayer.GetTimeoutTime();
06400                                         remoteSystem->lastReliableSend=timeMS;
06401                                 }
06402                         }
06403 
06404                         remoteSystem->reliabilityLayer.Update( remoteSystem->rakNetSocket->s, systemAddress, remoteSystem->MTUSize, timeNS, maxOutgoingBPS, messageHandlerList, &rnr, remoteSystem->rakNetSocket->remotePortRakNetWasStartedOn_PS3 ); // systemAddress only used for the internet simulator test
06405 
06406                         // Check for failure conditions
06407                         if ( remoteSystem->reliabilityLayer.IsDeadConnection() ||
06408                                 ((remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY) && remoteSystem->reliabilityLayer.IsOutgoingDataWaiting()==false) ||
06409                                 (remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK && (remoteSystem->reliabilityLayer.AreAcksWaiting()==false || remoteSystem->reliabilityLayer.AckTimeout(timeMS)==true)) ||
06410                                 ((
06411                                 (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
06412                                 remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
06413                                 remoteSystem->connectMode==RemoteSystemStruct::UNVERIFIED_SENDER ||
06414                                 remoteSystem->connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET)
06415                                 && timeMS > remoteSystem->connectionTime && timeMS - remoteSystem->connectionTime > 10000))
06416                                 )
06417                         {
06418                         //      RAKNET_DEBUG_PRINTF("timeMS=%i remoteSystem->connectionTime=%i\n", timeMS, remoteSystem->connectionTime );
06419 
06420                                 // Failed.  Inform the user?
06421                                 // TODO - RakNet 4.0 - Return a different message identifier for DISCONNECT_ASAP_SILENTLY and DISCONNECT_ASAP than for DISCONNECT_ON_NO_ACK
06422                                 // The first two mean we called CloseConnection(), the last means the other system sent us ID_DISCONNECTION_NOTIFICATION
06423                                 if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED || remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION
06424                                         || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
06425                                 {
06426 
06427 //                                      RakNet::BitStream undeliveredMessages;
06428 //                                      remoteSystem->reliabilityLayer.GetUndeliveredMessages(&undeliveredMessages,remoteSystem->MTUSize);
06429 
06430 //                                      packet=AllocPacket(sizeof( char ) + undeliveredMessages.GetNumberOfBytesUsed());
06431                                         packet=AllocPacket(sizeof( char ), __FILE__, __LINE__);
06432                                         if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
06433                                                 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
06434                                         else if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
06435                                                 packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
06436                                         else
06437                                                 packet->data[ 0 ] = ID_DISCONNECTION_NOTIFICATION; // DeadConnection
06438 
06439 //                                      memcpy(packet->data+1, undeliveredMessages.GetData(), undeliveredMessages.GetNumberOfBytesUsed());
06440 
06441                                         packet->guid = remoteSystem->guid;
06442                                         packet->systemAddress = systemAddress;
06443                                         packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
06444                                         packet->guid.systemIndex=packet->systemAddress.systemIndex;
06445 
06446                                         AddPacketToProducer(packet);
06447                                 }
06448                                 // else connection shutting down, don't bother telling the user
06449 
06450 #ifdef _DO_PRINTF
06451                                 RAKNET_DEBUG_PRINTF("Connection dropped for player %i:%i\n", systemAddress.binaryAddress, systemAddress.port);
06452 #endif
06453                                 CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
06454                                 continue;
06455                         }
06456 
06457                         // Did the reliability layer detect a modified packet?
06458                         if ( remoteSystem->reliabilityLayer.IsCheater() )
06459                         {
06460                                 packet=AllocPacket(sizeof(char), __FILE__, __LINE__);
06461                                 packet->bitSize=8;
06462                                 packet->data[ 0 ] = (MessageID)ID_MODIFIED_PACKET;
06463                                 packet->systemAddress = systemAddress;
06464                                 packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
06465                                 packet->guid = remoteSystem->guid;
06466                                 packet->guid.systemIndex=packet->systemAddress.systemIndex;
06467                                 AddPacketToProducer(packet);
06468                                 continue;
06469                         }
06470 
06471                         // Ping this guy if it is time to do so
06472                         if ( remoteSystem->connectMode==RemoteSystemStruct::CONNECTED && timeMS > remoteSystem->nextPingTime && ( occasionalPing || remoteSystem->lowestPing == (unsigned short)-1 ) )
06473                         {
06474                                 remoteSystem->nextPingTime = timeMS + 5000;
06475                                 PingInternal( systemAddress, true, UNRELIABLE );
06476 
06477                                 // Update again immediately after this tick so the ping goes out right away
06478                                 quitAndDataEvents.SetEvent();
06479                         }
06480 
06481                         // Find whoever has the lowest player ID
06482                         //if (systemAddress < authoritativeClientSystemAddress)
06483                         // authoritativeClientSystemAddress=systemAddress;
06484 
06485                         // Does the reliability layer have any packets waiting for us?
06486                         // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
06487                         bitSize = remoteSystem->reliabilityLayer.Receive( &data );
06488 
06489                         while ( bitSize > 0 )
06490                         {
06491                                 // These types are for internal use and should never arrive from a network packet
06492                                 if (data[0]==ID_CONNECTION_ATTEMPT_FAILED || data[0]==ID_MODIFIED_PACKET)
06493                                 {
06494                                         RakAssert(0);
06495                                         continue;
06496                                 }
06497 
06498                                 // Put the input through compression if necessary
06499                                 if ( inputTree )
06500                                 {
06501                                         RakNet::BitStream dataBitStream( MAXIMUM_MTU_SIZE );
06502                                         // Since we are decompressing input, we need to copy to a bitstream, decompress, then copy back to a probably
06503                                         // larger data block.  It's slow, but the user should have known that anyway
06504                                         dataBitStream.Reset();
06505                                         dataBitStream.WriteAlignedBytes( ( unsigned char* ) data, BITS_TO_BYTES( bitSize ) );
06506                                         rawBytesReceived += (unsigned int) dataBitStream.GetNumberOfBytesUsed();
06507 
06508 //                                      numberOfBytesUsed = dataBitStream.GetNumberOfBytesUsed();
06509                                         numberOfBitsUsed = dataBitStream.GetNumberOfBitsUsed();
06510                                         //rawBytesReceived += numberOfBytesUsed;
06511                                         // Decompress the input data.
06512 
06513                                         if (numberOfBitsUsed>0)
06514                                         {
06515                                                 unsigned char *dataCopy = (unsigned char*) rakMalloc_Ex( (unsigned int) dataBitStream.GetNumberOfBytesUsed(), __FILE__, __LINE__ );
06516                                                 memcpy( dataCopy, dataBitStream.GetData(), (size_t) dataBitStream.GetNumberOfBytesUsed() );
06517                                                 dataBitStream.Reset();
06518                                                 inputTree->DecodeArray( dataCopy, numberOfBitsUsed, &dataBitStream );
06519                                                 compressedBytesReceived += (unsigned int) dataBitStream.GetNumberOfBytesUsed();
06520                                                 rakFree_Ex(dataCopy, __FILE__, __LINE__ );
06521 
06522                                                 byteSize = (unsigned int) dataBitStream.GetNumberOfBytesUsed();
06523 
06524                                                 if ( byteSize > BITS_TO_BYTES( bitSize ) )   // Probably the case - otherwise why decompress?
06525                                                 {
06526                                                         rakFree_Ex(data, __FILE__, __LINE__ );
06527                                                         data = (unsigned char*) rakMalloc_Ex( (size_t) byteSize, __FILE__, __LINE__ );
06528                                                 }
06529                                                 bitSize = (BitSize_t) dataBitStream.GetNumberOfBitsUsed();
06530                                                 memcpy( data, dataBitStream.GetData(), byteSize );
06531                                         }
06532                                         else
06533                                                 byteSize=0;
06534                                 }
06535                                 else
06536                                         // Fast and easy - just use the data that was returned
06537                                         byteSize = (unsigned int) BITS_TO_BYTES( bitSize );
06538 
06539                                 // For unknown senders we only accept a few specific packets
06540                                 if (remoteSystem->connectMode==RemoteSystemStruct::UNVERIFIED_SENDER)
06541                                 {
06542                                         if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
06543                                         {
06544                                                 ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
06545                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06546                                         }
06547                                         else
06548                                         {
06549                                                 CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
06550 #ifdef _DO_PRINTF
06551                                                 RAKNET_DEBUG_PRINTF("Temporarily banning %i:%i for sending nonsense data\n", systemAddress.binaryAddress, systemAddress.port);
06552 #endif
06553 #if !defined(_XBOX) && !defined(X360)
06554                                                 char str1[64];
06555                                                 systemAddress.ToString(false, str1);
06556                                                 AddToBanList(str1, remoteSystem->reliabilityLayer.GetTimeoutTime());
06557 #endif
06558 
06559                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06560                                         }
06561                                 }
06562                                 else
06563                                 {
06564                                         // However, if we are connected we still take a connection request in case both systems are trying to connect to each other
06565                                         // at the same time
06566                                         if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
06567                                         {
06568                                                 // 04/27/06 This is wrong.  With cross connections, we can both have initiated the connection are in state REQUESTED_CONNECTION
06569                                                 // 04/28/06 Downgrading connections from connected will close the connection due to security at ((remoteSystem->connectMode!=RemoteSystemStruct::CONNECTED && time > remoteSystem->connectionTime && time - remoteSystem->connectionTime > 10000))
06570                                                 if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
06571                                                 {
06572                                                         ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
06573                                                 }
06574                                                 else
06575                                                 {
06576 
06577                                                         RakNet::BitStream bs((unsigned char*) data,byteSize,false);
06578                                                         bs.IgnoreBytes(sizeof(MessageID));
06579                                                         bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
06580                                                         bs.IgnoreBytes(RakNetGUID::size());
06581                                                         RakNetTime incomingTimestamp;
06582                                                         bs.Read(incomingTimestamp);
06583 
06584                                                         // Got a connection request message from someone we are already connected to. Just reply normally.
06585                                                         // This can happen due to race conditions with the fully connected mesh
06586                                                         SendConnectionRequestAccepted(remoteSystem, incomingTimestamp);
06587                                                 }
06588                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06589                                         }
06590                                         else if ( (unsigned char) data[ 0 ] == ID_NEW_INCOMING_CONNECTION && byteSize > sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(RakNetTime)*2 )
06591                                         {
06592 
06593                                                 if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
06594                                                         // WHy was this here? In CrossConnectinoTest it resulted in returning both ID_NEW_INCOMING_CONNECTION and ID_CONNECTION_REQUEST_ACCEPTED
06595                                 //                      remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
06596                                                         remoteSystem->connectMode==RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET)
06597                                                 {
06598                                                         // Removeme
06599 //                                                      static int count5=1;
06600 //                                                      printf("Processed ID_NEW_INCOMING_CONNECTION count=%i\n", count5++);
06601 
06602                                                         remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
06603                                                         PingInternal( systemAddress, true, UNRELIABLE );
06604 
06605                                                         // Update again immediately after this tick so the ping goes out right away
06606                                                         quitAndDataEvents.SetEvent();
06607 
06608                                                         RakNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
06609                                                         SystemAddress bsSystemAddress;
06610 
06611                                                         inBitStream.IgnoreBits(8);
06612                                                         inBitStream.Read(bsSystemAddress);
06613                                                         for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
06614                                                                 inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
06615 
06616                                                         RakNetTime sendPingTime, sendPongTime;
06617                                                         inBitStream.Read(sendPingTime);
06618                                                         inBitStream.Read(sendPongTime);
06619                                                         OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
06620 
06621                                                         // Overwrite the data in the packet
06622                                                         //                                      NewIncomingConnectionStruct newIncomingConnectionStruct;
06623                                                         //                                      RakNet::BitStream nICS_BS( data, NewIncomingConnectionStruct_Size, false );
06624                                                         //                                      newIncomingConnectionStruct.Deserialize( nICS_BS );
06625 
06626                                                         remoteSystem->myExternalSystemAddress = bsSystemAddress;
06627                                                         firstExternalID=bsSystemAddress;
06628 
06629                                                         // Send this info down to the game
06630                                                         packet=AllocPacket(byteSize, data, __FILE__, __LINE__);
06631                                                         packet->bitSize = bitSize;
06632                                                         packet->systemAddress = systemAddress;
06633                                                         packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
06634                                                         packet->guid = remoteSystem->guid;
06635                                                         packet->guid.systemIndex=packet->systemAddress.systemIndex;
06636                                                         AddPacketToProducer(packet);
06637                                                 }
06638                                         }
06639                                         else if ( (unsigned char) data[ 0 ] == ID_CONNECTED_PONG && byteSize == sizeof(unsigned char)+sizeof(RakNetTime)*2 )
06640                                         {
06641                                                 RakNetTime sendPingTime, sendPongTime;
06642 
06643                                                 // Copy into the ping times array the current time - the value returned
06644                                                 // First extract the sent ping
06645                                                 RakNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
06646                                                 //PingStruct ps;
06647                                                 //ps.Deserialize(psBS);
06648                                                 inBitStream.IgnoreBits(8);
06649                                                 inBitStream.Read(sendPingTime);
06650                                                 inBitStream.Read(sendPongTime);
06651 
06652                                                 OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
06653 
06654                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06655                                         }
06656                                         else if ( (unsigned char)data[0] == ID_INTERNAL_PING && byteSize == sizeof(unsigned char)+sizeof(RakNetTime) )
06657                                         {
06658                                                 RakNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
06659                                                 inBitStream.IgnoreBits(8);
06660                                                 RakNetTime sendPingTime;
06661                                                 inBitStream.Read(sendPingTime);
06662 
06663                                                 RakNet::BitStream outBitStream;
06664                                                 outBitStream.Write((MessageID)ID_CONNECTED_PONG);
06665                                                 outBitStream.Write(sendPingTime);
06666                                                 timeMS = RakNet::GetTime();
06667                                                 timeNS = RakNet::GetTimeNS();
06668                                                 outBitStream.Write(timeMS);
06669                                                 SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, UNRELIABLE, 0, systemAddress, false, false, timeNS, 0 );
06670 
06671                                                 // Update again immediately after this tick so the ping goes out right away
06672                                                 quitAndDataEvents.SetEvent();
06673 
06674                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06675                                         }
06676                                         else if ( (unsigned char) data[ 0 ] == ID_DISCONNECTION_NOTIFICATION )
06677                                         {
06678                                                 // We shouldn't close the connection immediately because we need to ack the ID_DISCONNECTION_NOTIFICATION
06679                                                 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ON_NO_ACK;
06680                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06681 
06682                                         //      AddPacketToProducer(packet);
06683                                         }
06684                                         else if ( (unsigned char) data[ 0 ] == ID_RPC_MAPPING )
06685                                         {
06686                                                 RakNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
06687                                                 RPCIndex index;
06688                                                 char output[256];
06689                                                 inBitStream.IgnoreBits(8);
06690                                                 stringCompressor->DecodeString(output, 255, &inBitStream);
06691                                                 inBitStream.ReadCompressed(index);
06692                         remoteSystem->rpcMap.AddIdentifierAtIndex((char*)output,index);
06693                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06694                                         }
06695 #if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
06696                                         else if ( (unsigned char)(data)[0] == ID_SECURED_CONNECTION_RESPONSE &&
06697                                                 byteSize == 1 + sizeof( uint32_t ) + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS + 20 )
06698                                         {
06699                                                 SecuredConnectionConfirmation( remoteSystem, (char*)data );
06700                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06701                                         }
06702                                         else if ( (unsigned char)(data)[0] == ID_SECURED_CONNECTION_CONFIRMATION &&
06703                                                 byteSize == 1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS + sizeof(RakNetTime) )
06704                                         {
06705                                                 CSHA1 sha1;
06706                                                 bool confirmedHash;
06707                                                 //bool newRandNumber;
06708 
06709                                                 confirmedHash = false;
06710 
06711                                                 // Hash the SYN-Cookie
06712                                                 // s2c syn-cookie = SHA1_HASH(source ip address + source port + random number)
06713                                                 sha1.Reset();
06714                                                 sha1.Update( ( unsigned char* ) & systemAddress.binaryAddress, sizeof( systemAddress.binaryAddress ) );
06715                                                 sha1.Update( ( unsigned char* ) & systemAddress.port, sizeof( systemAddress.port ) );
06716                                                 sha1.Update( ( unsigned char* ) & ( newRandomNumber ), 20 );
06717                                                 sha1.Final();
06718 
06719                                                 //newRandNumber = false;
06720 
06721                                                 // Confirm if
06722                                                 //syn-cookie ?= HASH(source ip address + source port + last random number)
06723                                                 //syn-cookie ?= HASH(source ip address + source port + current random number)
06724                                                 if ( memcmp( sha1.GetHash(), data + 1, 20 ) == 0 )
06725                                                 {
06726                                                         confirmedHash = true;
06727                                                 }
06728                                                 else
06729                                                 {
06730                                                         sha1.Reset();
06731                                                         sha1.Update( ( unsigned char* ) & systemAddress.binaryAddress, sizeof( systemAddress.binaryAddress ) );
06732                                                         sha1.Update( ( unsigned char* ) & systemAddress.port, sizeof( systemAddress.port ) );
06733                                                         sha1.Update( ( unsigned char* ) & ( oldRandomNumber ), 20 );
06734                                                         sha1.Final();
06735 
06736                                                         if ( memcmp( sha1.GetHash(), data + 1, 20 ) == 0 )
06737                                                                 confirmedHash = true;
06738                                                 }
06739                                                 if ( confirmedHash )
06740                                                 {
06741                                                         int i;
06742                                                         unsigned char AESKey[ 16 ];
06743                                                         //RSA_BIT_SIZE message, encryptedMessage;
06744                                                         uint32_t message[RAKNET_RSA_FACTOR_LIMBS], encryptedMessage[RAKNET_RSA_FACTOR_LIMBS];
06745 
06746                                                         // On connection accept, AES key is c2s RSA_Decrypt(random number) XOR s2c syn-cookie
06747                                                         // Get the random number first
06748 
06749                                                         memcpy( encryptedMessage, data + 1 + 20, sizeof( encryptedMessage ) );
06750 
06751                                         //              printf("enc3[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
06752 
06753                                                         if (RakNet::BitStream::DoEndianSwap())
06754                                                         {
06755                                                                 for (int i=0; i < RAKNET_RSA_FACTOR_LIMBS; i++)
06756                                                                         RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &encryptedMessage[i], sizeof(encryptedMessage[i]));
06757                                                         }
06758 
06759                                 //                      printf("enc4[0]=%i,%i\n", encryptedMessage[0], encryptedMessage[19]);
06760 
06761                                                         // rsacrypt.decrypt( encryptedMessage, message );
06762                                                         rsacrypt.decrypt( message, encryptedMessage );
06763 
06764                                                 //      printf("message[0]=%i,%i\n", message[0], message[19]);
06765 
06766 
06767 
06768 //                                                      if (RakNet::BitStream::DoEndianSwap())
06769 //                                                      {
06770                                                                 // The entire message is endian swapped, then just the random number
06771 //                                                              unsigned char randomNumber[ 20 ];
06772 //                                                              if (RakNet::BitStream::DoEndianSwap())
06773 //                                                              {
06774 //                                                                      for (int i=0; i < 20; i++)
06775 //                                                                              RakNet::BitStream::ReverseBytesInPlace((unsigned char*) message[i], sizeof(message[i]));
06776 //                                                              }
06777 //                                                      }
06778 
06779                                                         /*
06780                                                         // On connection accept, AES key is c2s RSA_Decrypt(random number) XOR s2c syn-cookie
06781                                                         // Get the random number first
06782                                                         #ifdef HOST_ENDIAN_IS_BIG
06783                                                                 BSWAPCPY( (unsigned char *) encryptedMessage, (unsigned char *)(data + 1 + 20), sizeof( RSA_BIT_SIZE ) );
06784                                                         #else
06785                                                                 memcpy( encryptedMessage, data + 1 + 20, sizeof( RSA_BIT_SIZE ) );
06786                                                         #endif
06787                                                         rsacrypt.decrypt( encryptedMessage, message );
06788                                                         #ifdef HOST_ENDIAN_IS_BIG
06789                                                                 BSWAPSELF( (unsigned char *) message, sizeof( RSA_BIT_SIZE ) );
06790                                                         #endif
06791                                                         */
06792 
06793                                                         // Save the AES key
06794                                                         for ( i = 0; i < 16; i++ )
06795                                                                 AESKey[ i ] = data[ 1 + i ] ^ ( ( unsigned char* ) ( message ) ) [ i ];
06796 
06797                                                         RakNet::BitStream bsTimestamp(data+1 + 20 + sizeof( uint32_t ) * RAKNET_RSA_FACTOR_LIMBS,sizeof(RakNetTime),false);
06798                                                         RakNetTime timeStamp;
06799                                                         bsTimestamp.Read(timeStamp);
06800 
06801                                                         // Connect this player assuming we have open slots
06802                                                         OnConnectionRequest( remoteSystem, AESKey, true, timeStamp );
06803                                                 }
06804                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06805                                         }
06806 #endif // #if !defined(_XBOX) && !defined(_WIN32_WCE)
06807                                         else if ( (unsigned char)(data)[0] == ID_DETECT_LOST_CONNECTIONS && byteSize == sizeof(unsigned char) )
06808                                         {
06809                                                 // Do nothing
06810                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06811                                         }
06812                                         else if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST_ACCEPTED )
06813                                         {
06814                                                 if (byteSize > sizeof(MessageID)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(SystemIndex)+sizeof(RakNetTime)*2)
06815                                                 {
06816                                                         // Make sure this connection accept is from someone we wanted to connect to
06817                                                         bool allowConnection, alreadyConnected;
06818 
06819                                                         if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
06820                                                                 remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
06821                                                                 allowConnectionResponseIPMigration)
06822                                                                 allowConnection=true;
06823                                                         else
06824                                                                 allowConnection=false;
06825 
06826                                                         if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST)
06827                                                                 alreadyConnected=true;
06828                                                         else
06829                                                                 alreadyConnected=false;
06830 
06831                                                         if ( allowConnection )
06832                                                         {
06833                                                                 SystemAddress externalID;
06834                                                                 SystemIndex systemIndex;
06835 //                                                              SystemAddress internalID;
06836 
06837                                                                 RakNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
06838                                                                 inBitStream.IgnoreBits(8); // ID_CONNECTION_REQUEST_ACCEPTED
06839                                                                 //      inBitStream.Read(remotePort);
06840                                                                 inBitStream.Read(externalID);
06841                                                                 inBitStream.Read(systemIndex);
06842                                                                 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
06843                                                                         inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
06844                                                         
06845                                                                 RakNetTime sendPingTime, sendPongTime;
06846                                                                 inBitStream.Read(sendPingTime);
06847                                                                 inBitStream.Read(sendPongTime);
06848                                                                 OnConnectedPong(sendPingTime, sendPongTime, remoteSystem);
06849 
06850                                                                 // Find a free remote system struct to use
06851                                                                 //                                              RakNet::BitStream casBitS(data, byteSize, false);
06852                                                                 //                                              ConnectionAcceptStruct cas;
06853                                                                 //                                              cas.Deserialize(casBitS);
06854                                                                 //      systemAddress.port = remotePort;
06855 
06856                                                                 // The remote system told us our external IP, so save it
06857                                                                 remoteSystem->myExternalSystemAddress = externalID;
06858                                                                 remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
06859 
06860                                                                 firstExternalID=externalID;
06861 
06862                                                                 if (alreadyConnected==false)
06863                                                                 {
06864                                                                         // Use the stored encryption key
06865                                                                         if (remoteSystem->setAESKey)
06866                                                                                 remoteSystem->reliabilityLayer.SetEncryptionKey( remoteSystem->AESKey );
06867                                                                         else
06868                                                                                 remoteSystem->reliabilityLayer.SetEncryptionKey( 0 );
06869                                                                 }
06870 
06871                                                                 // Send the connection request complete to the game
06872                                                                 packet=AllocPacket(byteSize, data, __FILE__, __LINE__);
06873                                                                 packet->bitSize = byteSize * 8;
06874                                                                 packet->systemAddress = systemAddress;
06875                                                                 packet->systemAddress.systemIndex = ( SystemIndex ) GetIndexFromSystemAddress( systemAddress, true );
06876                                                                 packet->guid = remoteSystem->guid;
06877                                                                 packet->guid.systemIndex=packet->systemAddress.systemIndex;
06878                                                                 AddPacketToProducer(packet);
06879 
06880 
06881                                                                 // Removeme
06882 //                                                              static int count3=1;
06883 //                                                              printf("Send ID_NEW_INCOMING_CONNECTION count=%i\n", count3++);
06884 
06885                                                                 RakNet::BitStream outBitStream;
06886                                                                 outBitStream.Write((MessageID)ID_NEW_INCOMING_CONNECTION);
06887                                                                 outBitStream.Write(systemAddress);
06888                                                                 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
06889                                                                         outBitStream.Write(mySystemAddress[i]);
06890                                                                 outBitStream.Write(sendPongTime);
06891                                                                 outBitStream.Write(RakNet::GetTime());
06892                                                                 
06893 
06894                                                                 // We turned on encryption with SetEncryptionKey.  This pads packets to up to a multiple of 16 bytes.
06895                                                                 // As soon as a multiple of 16 byte packet arrives on the remote system, we will turn on AES.  This works because all encrypted packets are multiples of 16 and the
06896                                                                 // packets I happen to be sending before this are not a multiple of 16 bytes.  Otherwise there is no way to know if a packet that arrived is
06897                                                                 // encrypted or not so the other side won't know to turn on encryption or not.
06898                                                                 RakAssert((outBitStream.GetNumberOfBytesUsed()&15)!=0);
06899                                                                 SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false, false, RakNet::GetTimeNS(), 0 );
06900 
06901                                                                 if (alreadyConnected==false)
06902                                                                 {
06903                                                                         PingInternal( systemAddress, true, UNRELIABLE );
06904                                                                 }
06905                                                         }
06906                                                         else
06907                                                         {
06908                                                                 // Ignore, already connected
06909                                                                 rakFree_Ex(data, __FILE__, __LINE__ );
06910                                                         }
06911                                                 }
06912                                                 else
06913                                                 {
06914                                                         // Version mismatch error?
06915                                                         RakAssert(0);
06916                                                         rakFree_Ex(data, __FILE__, __LINE__ );
06917                                                 }
06918                                         }
06919                                         else
06920                                         {
06921                                                 // What do I do if I get a message from a system, before I am fully connected?
06922                                                 // I can either ignore it or give it to the user
06923                                                 // It seems like giving it to the user is a better option
06924                                                 if (data[0]>=(MessageID)ID_RPC &&
06925                                                         remoteSystem->isActive
06926                                                         /*
06927                                                         (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED ||
06928                                                         remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP ||
06929                                                         remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY ||
06930                                                         remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
06931                                                         */
06932                                                         )
06933                                                 {
06934                                                         packet=AllocPacket(byteSize, data, __FILE__, __LINE__);
06935                                                         packet->bitSize = bitSize;
06936                                                         packet->systemAddress = systemAddress;
06937                                                         packet->systemAddress.systemIndex = ( SystemIndex ) remoteSystemIndex;
06938                                                         packet->guid = remoteSystem->guid;
06939                                                         packet->guid.systemIndex=packet->systemAddress.systemIndex;
06940                                                         AddPacketToProducer(packet);
06941                                                 }
06942                                                 else
06943                                                 {
06944                                                         rakFree_Ex(data, __FILE__, __LINE__ );
06945                                                 }
06946                                         }
06947                                 }
06948 
06949                                 // Does the reliability layer have any more packets waiting for us?
06950                                 // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
06951                                 bitSize = remoteSystem->reliabilityLayer.Receive( &data );
06952                         }
06953                 }
06954         }
06955 
06956         return true;
06957 }
06958 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
06959 RAK_THREAD_DECLARATION(RecvFromLoop)
06960 {
06961         RakPeerAndIndex *rpai = ( RakPeerAndIndex * ) arguments;
06962         RakPeer * rakPeer = rpai->rakPeer;
06963         SOCKET s = rpai->s;
06964         unsigned short remotePortRakNetWasStartedOn_PS3 = rpai->remotePortRakNetWasStartedOn_PS3;
06965 
06966         rakPeer->isRecvFromLoopThreadActive = true;
06967         
06968         RakPeer::RecvFromStruct *recvFromStruct;
06969         while ( rakPeer->endThreads == false )
06970         {
06971                 recvFromStruct=rakPeer->bufferedPackets.Allocate( __FILE__, __LINE__ );
06972                 recvFromStruct->s=s;
06973                 recvFromStruct->remotePortRakNetWasStartedOn_PS3=remotePortRakNetWasStartedOn_PS3;
06974                 SocketLayer::RecvFromBlocking(s, rakPeer, remotePortRakNetWasStartedOn_PS3, recvFromStruct->data, &recvFromStruct->bytesRead, &recvFromStruct->systemAddress, &recvFromStruct->timeRead);
06975                 if (recvFromStruct->bytesRead>0)
06976                 {
06977                         RakAssert(recvFromStruct->systemAddress.port);
06978                         rakPeer->bufferedPackets.Push(recvFromStruct);
06979 
06980                         rakPeer->quitAndDataEvents.SetEvent();
06981                 }
06982                 else
06983                 {
06984                         rakPeer->bufferedPackets.Deallocate(recvFromStruct, __FILE__,__LINE__);
06985                 }
06986         }
06987         rakPeer->isRecvFromLoopThreadActive = false;
06988         return 0;
06989 }
06990 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
06991 RAK_THREAD_DECLARATION(UpdateNetworkLoop)
06992 {
06993         RakPeer * rakPeer = ( RakPeer * ) arguments;
06994 
06995 /*
06996         // 11/15/05 - this is slower than Sleep()
06997 #ifdef _WIN32
06998 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
06999         // Lets see if these timers give better performance than Sleep
07000         HANDLE timerHandle;
07001         LARGE_INTEGER dueTime;
07002 
07003         if ( rakPeer->threadSleepTimer <= 0 )
07004                 rakPeer->threadSleepTimer = 1;
07005 
07006         // 2nd parameter of false means synchronization timer instead of manual-reset timer
07007         timerHandle = CreateWaitableTimer( NULL, FALSE, 0 );
07008 
07009         RakAssert( timerHandle );
07010 
07011         dueTime.QuadPart = -10000 * rakPeer->threadSleepTimer; // 10000 is 1 ms?
07012 
07013         BOOL success = SetWaitableTimer( timerHandle, &dueTime, rakPeer->threadSleepTimer, NULL, NULL, FALSE );
07014     (void) success;
07015         RakAssert( success );
07016 
07017 #endif
07018 #endif
07019 */
07020 
07021         rakPeer->isMainLoopThreadActive = true;
07022 
07023         while ( rakPeer->endThreads == false )
07024         {
07025                 if (rakPeer->userUpdateThreadPtr)
07026                         rakPeer->userUpdateThreadPtr(rakPeer, rakPeer->userUpdateThreadData);
07027 
07028                 rakPeer->RunUpdateCycle();
07029 
07030 
07031                 // Pending sends go out this often, unless quitAndDataEvents is set
07032                 rakPeer->quitAndDataEvents.WaitOnEvent(10);
07033 
07034                 /*
07035 
07036 // #if ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) &&
07037 #if defined(USE_WAIT_FOR_MULTIPLE_EVENTS) && defined(_WIN32)
07038 
07039                 if (rakPeer->threadSleepTimer>0)
07040                 {
07041                         WSAEVENT eventArray[256];
07042                         unsigned int i, eventArrayIndex;
07043                         for (i=0,eventArrayIndex=0; i < rakPeer->socketList.Size(); i++)
07044                         {
07045                                 if (rakPeer->socketList[i]->recvEvent!=INVALID_HANDLE_VALUE)
07046                                 {
07047                                         eventArray[eventArrayIndex]=rakPeer->socketList[i]->recvEvent;
07048                                         eventArrayIndex++;
07049                                         if (eventArrayIndex==256)
07050                                                 break;
07051                                 }
07052                         }
07053                         WSAWaitForMultipleEvents(eventArrayIndex,(const HANDLE*) &eventArray,FALSE,rakPeer->threadSleepTimer,FALSE);
07054                 }
07055                 else
07056                 {
07057                         RakSleep(0);
07058                 }
07059 
07060 #else // ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
07061                 #pragma message("-- RakNet: Using Sleep(). Uncomment USE_WAIT_FOR_MULTIPLE_EVENTS in RakNetDefines.h if you want to use WaitForSingleObject instead. --")
07062 
07063                 RakSleep( rakPeer->threadSleepTimer );
07064 #endif
07065                 */
07066         }
07067 
07068         rakPeer->isMainLoopThreadActive = false;
07069 
07070         /*
07071 #ifdef _WIN32
07072 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
07073         CloseHandle(timerHandle);
07074 #endif
07075 #endif
07076         */
07077 
07078         return 0;
07079 }
07080 
07081 #if defined(RMO_NEW_UNDEF_ALLOCATING_QUEUE)
07082 #pragma pop_macro("new")
07083 #undef RMO_NEW_UNDEF_ALLOCATING_QUEUE
07084 #endif
07085 
07086 
07087 #ifdef _MSC_VER
07088 #pragma warning( pop )
07089 #endif

Generated on Thu Sep 30 2010 01:27:26 for RakNet by  doxygen 1.7.1