SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RakPeer.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2019, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 // \file
17 //
18
19
20
21 #define CAT_NEUTER_EXPORT /* Neuter dllimport for libcat */
22
23 #include "slikenet/defines.h"
24 #include "slikenet/peer.h"
25 #include "slikenet/types.h"
26
27 #ifdef _WIN32
28
29 #else
30 #include <unistd.h>
31 #endif
32
33 // #if defined(new)
34 // #pragma push_macro("new")
35 // #undef new
36 // #define RMO_NEW_UNDEF_ALLOCATING_QUEUE
37 // #endif
38
39 #include <time.h>
40 #include <ctype.h> // toupper
41 #include <string.h>
42 #include "slikenet/GetTime.h"
43 #include "slikenet/MessageIdentifiers.h"
44 #include "slikenet/DS_HuffmanEncodingTree.h"
45 #include "slikenet/Rand.h"
46 #include "slikenet/PluginInterface2.h"
47 #include "slikenet/StringCompressor.h"
48 #include "slikenet/StringTable.h"
49 #include "slikenet/NetworkIDObject.h"
50 #include "slikenet/types.h"
51 #include "slikenet/DR_SHA1.h"
52 #include "slikenet/sleep.h"
53 #include "slikenet/assert.h"
54 #include "slikenet/version.h"
55 #include "slikenet/NetworkIDManager.h"
56 #include "slikenet/gettimeofday.h"
57 #include "slikenet/SignaledEvent.h"
58 #include "slikenet/SuperFastHash.h"
59 #include "slikenet/alloca.h"
60 #include "slikenet/WSAStartupSingleton.h"
61 #include "slikenet/linux_adapter.h"
62 #include "slikenet/osx_adapter.h"
63
64 #ifdef USE_THREADED_SEND
65 #include "slikenet/SendToThread.h"
66 #endif
67
68 #ifdef CAT_AUDIT
69 #define CAT_AUDIT_PRINTF(...) printf(__VA_ARGS__)
70 #else
71 #define CAT_AUDIT_PRINTF(...)
72 #endif
73
74 namespace SLNet
75 {
76 RAK_THREAD_DECLARATION(UpdateNetworkLoop);
77 RAK_THREAD_DECLARATION(RecvFromLoop);
78 RAK_THREAD_DECLARATION(UDTConnect);
79 }
80 #define REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE 8
81
82 #if !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ )
83 #include <stdlib.h> // malloc
84 #endif
85
86
87
88 #if defined(_WIN32)
89 //
90 #else
91 /*
92 #include <alloca.h> // Console 2
93 #include <stdlib.h>
94 extern bool _extern_Console2LoadModules(void);
95 extern int _extern_Console2GetConnectionStatus(void);
96 extern int _extern_Console2GetLobbyStatus(void);
97 //extern bool Console2StartupFluff(unsigned int *);
98 extern void Console2ShutdownFluff(void);
99 //extern unsigned int Console2ActivateConnection(unsigned int, void *);
100 //extern bool Console2BlockOnEstablished(void);
101 extern void Console2GetIPAndPort(unsigned int, char *, unsigned short *, unsigned int );
102 //extern void Console2DeactivateConnection(unsigned int, unsigned int);
103 */
104 #endif
105
106
107 static const int NUM_MTU_SIZES=3;
108
109
110
111 static const int mtuSizes[NUM_MTU_SIZES]={MAXIMUM_MTU_SIZE, 1200, 576};
112
113
114 // Note to self - if I change this it might affect RECIPIENT_OFFLINE_MESSAGE_INTERVAL in Natpunchthrough.cpp
115 //static const int MAX_OPEN_CONNECTION_REQUESTS=8;
116 //static const int TIME_BETWEEN_OPEN_CONNECTION_REQUESTS=500;
117
118 using namespace SLNet;
119
120 static RakNetRandom rnr;
121
122 /*
123 struct RakPeerAndIndex
124 {
125 RakNetSocket2 *s;
126 RakPeer *rakPeer;
127 };
128 */
129
130 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.
131
132 // Used to distinguish between offline messages with data, and messages from the reliability layer
133 // Should be different than any message that could result from messages from the reliability layer
134 // Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false
135 static const unsigned char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78};
136
137 struct PacketFollowedByData
138 {
139 Packet p;
140 unsigned char data[1];
141 };
142
143 Packet *RakPeer::AllocPacket(unsigned dataSize, const char *file, unsigned int line)
144 {
145 // Crashes when dataSize is 4 bytes - not sure why
146 // unsigned char *data = (unsigned char *) rakMalloc_Ex(sizeof(PacketFollowedByData)+dataSize, file, line);
147 // Packet *p = &((PacketFollowedByData *)data)->p;
148 // p->data=((PacketFollowedByData *)data)->data;
149 // p->length=dataSize;
150 // p->bitSize=BYTES_TO_BITS(dataSize);
151 // p->deleteData=false;
152 // p->guid=UNASSIGNED_RAKNET_GUID;
153 // return p;
154
155 SLNet::Packet *p;
156 packetAllocationPoolMutex.Lock();
157 p = packetAllocationPool.Allocate(file,line);
158 packetAllocationPoolMutex.Unlock();
159 p = new ((void*)p) Packet;
160 p->data=(unsigned char*) rakMalloc_Ex(dataSize,file,line);
161 p->length=dataSize;
162 p->bitSize=BYTES_TO_BITS(dataSize);
163 p->deleteData=true;
164 p->guid=UNASSIGNED_RAKNET_GUID;
165 p->wasGeneratedLocally=false;
166 return p;
167 }
168
169 Packet *RakPeer::AllocPacket(unsigned dataSize, unsigned char *data, const char *file, unsigned int line)
170 {
171 // Packet *p = (Packet *)rakMalloc_Ex(sizeof(Packet), file, line);
172 SLNet::Packet *p;
173 packetAllocationPoolMutex.Lock();
174 p = packetAllocationPool.Allocate(file,line);
175 packetAllocationPoolMutex.Unlock();
176 p = new ((void*)p) Packet;
177 RakAssert(p);
178 p->data=data;
179 p->length=dataSize;
180 p->bitSize=BYTES_TO_BITS(dataSize);
181 p->deleteData=true;
182 p->guid=UNASSIGNED_RAKNET_GUID;
183 p->wasGeneratedLocally=false;
184 return p;
185 }
186
187 STATIC_FACTORY_DEFINITIONS(RakPeerInterface,RakPeer)
188
189 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
190 // Constructor
191 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
192 RakPeer::RakPeer()
193 {
194 #if LIBCAT_SECURITY==1
195 // Encryption and security
196 CAT_AUDIT_PRINTF("AUDIT: Initializing RakPeer security flags: using_security = false, server_handshake = null, cookie_jar = null\n");
197 _using_security = false;
198 _server_handshake = 0;
199 _cookie_jar = 0;
200 #endif
201
202 StringCompressor::AddReference();
203 SLNet::StringTable::AddReference();
204 WSAStartupSingleton::AddRef();
205
206 defaultMTUSize = mtuSizes[NUM_MTU_SIZES-1];
207 trackFrequencyTable = false;
208 maximumIncomingConnections = 0;
209 maximumNumberOfPeers = 0;
210 //remoteSystemListSize=0;
211 remoteSystemList = 0;
212 activeSystemList = 0;
213 activeSystemListSize=0;
214 remoteSystemLookup=0;
215 bytesSentPerSecond = bytesReceivedPerSecond = 0;
216 endThreads = true;
217 isMainLoopThreadActive = false;
218 incomingDatagramEventHandler=0;
219
220
221
222
223
224 // isRecvfromThreadActive=false;
225 #if defined(GET_TIME_SPIKE_LIMIT) && GET_TIME_SPIKE_LIMIT>0
226 occasionalPing = true;
227 #else
228 occasionalPing = false;
229 #endif
230 allowInternalRouting=false;
231 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
232 ipList[i]=UNASSIGNED_SYSTEM_ADDRESS;
233 allowConnectionResponseIPMigration = false;
234 //incomingPasswordLength=outgoingPasswordLength=0;
235 incomingPasswordLength=0;
236 splitMessageProgressInterval=0;
237 //unreliableTimeout=0;
238 unreliableTimeout=1000;
239 maxOutgoingBPS=0;
240 firstExternalID=UNASSIGNED_SYSTEM_ADDRESS;
241 myGuid=UNASSIGNED_RAKNET_GUID;
242 userUpdateThreadPtr=0;
243 userUpdateThreadData=0;
244
245 #ifdef _DEBUG
246 // Wait longer to disconnect in debug so I don't get disconnected while tracing
247 defaultTimeoutTime=30000;
248 #else
249 defaultTimeoutTime=10000;
250 #endif
251
252 #ifdef _DEBUG
253 _packetloss=0.0;
254 _minExtraPing=0;
255 _extraPingVariance=0;
256 #endif
257
258 bufferedCommands.SetPageSize(sizeof(BufferedCommandStruct)*16);
259 socketQueryOutput.SetPageSize(sizeof(SocketQueryOutput)*8);
260
261 packetAllocationPoolMutex.Lock();
262 packetAllocationPool.SetPageSize(sizeof(DataStructures::MemoryPool<Packet>::MemoryWithPage)*32);
263 packetAllocationPoolMutex.Unlock();
264
265 remoteSystemIndexPool.SetPageSize(sizeof(DataStructures::MemoryPool<RemoteSystemIndex>::MemoryWithPage)*32);
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 GenerateGUID();
310
311 quitAndDataEvents.InitEvent();
312 limitConnectionFrequencyFromTheSameIP=false;
313 ResetSendReceipt();
314 }
315
316 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
317 // Destructor
318 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
319 RakPeer::~RakPeer()
320 {
321 Shutdown( 0, 0 );
322
323 // Free the ban list.
324 ClearBanList();
325
326 StringCompressor::RemoveReference();
327 SLNet::StringTable::RemoveReference();
328 WSAStartupSingleton::Deref();
329
330 quitAndDataEvents.CloseEvent();
331
332 #if LIBCAT_SECURITY==1
333 // Encryption and security
334 CAT_AUDIT_PRINTF("AUDIT: Deleting RakPeer security objects, handshake = %x, cookie jar = %x\n", _server_handshake, _cookie_jar);
335 if (_server_handshake) SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
336 if (_cookie_jar) SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
337 #endif
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 // for (unsigned int i=0; i < pluginListTS.Size(); i++)
355 // pluginListTS[i]->SetRakPeerInterface(0);
356 // for (unsigned int i=0; i < pluginListNTS.Size(); i++)
357 // pluginListNTS[i]->SetRakPeerInterface(0);
358 }
359
360 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
361 // \brief Starts the network threads, opens the listen port.
362 // You must call this before calling Connect().
363 // Multiple calls while already active are ignored. To call this function again with different settings, you must first call Shutdown().
364 // \note Call SetMaximumIncomingConnections if you want to accept incoming connections
365 // \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
366 // \param[in] localPort The port to listen for connections on.
367 // \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.
368 // \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();
369 // \param[in] socketDescriptorCount The size of the \a socketDescriptors array. Pass 1 if you are not sure what to pass.
370 // \return False on failure (can't create socket or thread), true on success.
371 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
372 StartupResult RakPeer::Startup( unsigned int maxConnections, SocketDescriptor *socketDescriptors, unsigned socketDescriptorCount, int threadPriority )
373 {
374 if (IsActive())
375 return RAKNET_ALREADY_STARTED;
376
377 // If getting the guid failed in the constructor, try again
378 if (myGuid.g==0)
379 {
380 GenerateGUID();
381 if (myGuid.g==0)
382 return COULD_NOT_GENERATE_GUID;
383 }
384
385 if (threadPriority==-99999)
386 {
387
388
389 #if defined(_WIN32)
390 threadPriority=0;
391
392
393
394
395 #else
396 threadPriority=1000;
397 #endif
398 }
399
400
401 FillIPList();
402
403 if (myGuid==UNASSIGNED_RAKNET_GUID)
404 {
405 rnr.SeedMT( GenerateSeedFromGuid() );
406 }
407
408 //RakPeerAndIndex rpai[32];
409 //RakAssert(socketDescriptorCount<32);
410
411 RakAssert(socketDescriptors && socketDescriptorCount>=1);
412
413 if (socketDescriptors==0 || socketDescriptorCount<1)
414 return INVALID_SOCKET_DESCRIPTORS;
415
416 //unsigned short localPort;
417 //localPort=socketDescriptors[0].port;
418
419 RakAssert( maxConnections > 0 );
420
421 if ( maxConnections <= 0 )
422 return INVALID_MAX_CONNECTIONS;
423
424 DerefAllSockets();
425
426
427 unsigned i;
428 // Go through all socket descriptors and precreate sockets on the specified addresses
429 for (i=0; i<socketDescriptorCount; i++)
430 {
431 /*
432 const char *addrToBind;
433 if (socketDescriptors[i].hostAddress[0]==0)
434 addrToBind=0;
435 else
436 addrToBind=socketDescriptors[i].hostAddress;
437 */
438
439
440
441
442
443
444
445
446
447 /*
448 #if RAKNET_SUPPORT_IPV6==1
449 if (SocketLayer::IsSocketFamilySupported(addrToBind, socketDescriptors[i].socketFamily)==false)
450 return SOCKET_FAMILY_NOT_SUPPORTED;
451 #endif
452
453 if (socketDescriptors[i].port!=0 && SocketLayer::IsPortInUse(socketDescriptors[i].port, addrToBind, socketDescriptors[i].socketFamily)==true)
454 {
455 DerefAllSockets();
456 return SOCKET_PORT_ALREADY_IN_USE;
457 }
458
459 RakNetSocket* rns = 0;
460 if (socketDescriptors[i].remotePortRakNetWasStartedOn_PS3_PSP2==0)
461 {
462 rns = SocketLayer::CreateBoundSocket( this, socketDescriptors[i].port, socketDescriptors[i].blockingSocket, addrToBind, 100, socketDescriptors[i].extraSocketOptions, socketDescriptors[i].socketFamily, socketDescriptors[i].chromeInstance );
463 }
464 else
465 {
466 #if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) || defined(_PS4)
467 rns = SocketLayer::CreateBoundSocket_PS3Lobby( socketDescriptors[i].port, socketDescriptors[i].blockingSocket, addrToBind, socketDescriptors[i].socketFamily );
468 #elif defined(SN_TARGET_PSP2)
469 rns = SocketLayer::CreateBoundSocket_PSP2( socketDescriptors[i].port, socketDescriptors[i].blockingSocket, addrToBind, socketDescriptors[i].socketFamily );
470 #endif
471 }
472 */
473
474 RakNetSocket2 *r2 = RakNetSocket2Allocator::AllocRNS2();
475 r2->SetUserConnectionSocketIndex(i);
476 #if defined(__native_client__)
477 NativeClientBindParameters ncbp;
478 RNS2_NativeClient * nativeClientSocket = (RNS2_NativeClient*) r2;
479 ncbp.eventHandler=this;
480 ncbp.forceHostAddress=(char*) socketDescriptors[i].hostAddress;
481 ncbp.is_ipv6=socketDescriptors[i].socketFamily==AF_INET6;
482 ncbp.nativeClientInstance=socketDescriptors[i].chromeInstance;
483 ncbp.port=socketDescriptors[i].port;
484 nativeClientSocket->Bind(&ncbp, _FILE_AND_LINE_);
485 #elif defined(WINDOWS_STORE_RT)
486 RNS2BindResult br;
487 ((RNS2_WindowsStore8*) r2)->SetRecvEventHandler(this);
488 br = ((RNS2_WindowsStore8*) r2)->Bind(ref new Platform::String());
489 if (br!=BR_SUCCESS)
490 {
491 RakNetSocket2Allocator::DeallocRNS2(r2);
492 DerefAllSockets();
493 return SOCKET_FAILED_TO_BIND;
494 }
495 #else
496 if (r2->IsBerkleySocket())
497 {
498 RNS2_BerkleyBindParameters bbp;
499 bbp.port=socketDescriptors[i].port;
500 bbp.hostAddress=(char*) socketDescriptors[i].hostAddress;
501 bbp.addressFamily=socketDescriptors[i].socketFamily;
502 bbp.type=SOCK_DGRAM;
503 bbp.protocol=socketDescriptors[i].extraSocketOptions;
504 bbp.nonBlockingSocket=false;
505 bbp.setBroadcast=true;
506 bbp.setIPHdrIncl=false;
507 bbp.doNotFragment=false;
508 bbp.pollingThreadPriority=threadPriority;
509 bbp.eventHandler=this;
510 bbp.remotePortRakNetWasStartedOn_PS3_PS4_PSP2=socketDescriptors[i].remotePortRakNetWasStartedOn_PS3_PSP2;
511 RNS2BindResult br = ((RNS2_Berkley*) r2)->Bind(&bbp, _FILE_AND_LINE_);
512
513 if (
514 #if RAKNET_SUPPORT_IPV6==0
515 socketDescriptors[i].socketFamily!=AF_INET ||
516 #endif
517 br==BR_REQUIRES_RAKNET_SUPPORT_IPV6_DEFINE)
518 {
519 RakNetSocket2Allocator::DeallocRNS2(r2);
520 DerefAllSockets();
521 return SOCKET_FAMILY_NOT_SUPPORTED;
522 }
523 else if (br==BR_FAILED_TO_BIND_SOCKET)
524 {
525 RakNetSocket2Allocator::DeallocRNS2(r2);
526 DerefAllSockets();
527 return SOCKET_PORT_ALREADY_IN_USE;
528 }
529 else if (br==BR_FAILED_SEND_TEST)
530 {
531 RakNetSocket2Allocator::DeallocRNS2(r2);
532 DerefAllSockets();
533 return SOCKET_FAILED_TEST_SEND;
534 }
535 else
536 {
537 RakAssert(br==BR_SUCCESS);
538 }
539 }
540 else
541 {
542 RakAssert("TODO" && 0);
543 }
544 #endif
545 /*
546
547 SystemAddress saOut;
548 SocketLayer::GetSystemAddress( rns, &saOut );
549 rns->SetBoundAddress(saOut);
550 rns->SetRemotePortRakNetWasStartedOn(socketDescriptors[i].remotePortRakNetWasStartedOn_PS3_PSP2);
551 rns->SetChromeInstance(socketDescriptors[i].chromeInstance);
552 rns->SetExtraSocketOptions(socketDescriptors[i].extraSocketOptions);
553 rns->SetUserConnectionSocketIndex(i);
554 rns->SetBlockingSocket(socketDescriptors[i].blockingSocket);
555
556 #if RAKNET_SUPPORT_IPV6==0
557 if (addrToBind==0)
558 rns->SetBoundAddressToLoopback(4);
559 #endif
560
561 // GetBoundAddress is asynch, which isn't supported by this architecture
562 #if !defined(__native_client__)
563 int zero=0;
564 if (SocketLayer::SendTo(rns, (const char*) &zero,4, rns->GetBoundAddress(), _FILE_AND_LINE_)!=0)
565 {
566 DerefAllSockets();
567 return SOCKET_FAILED_TEST_SEND;
568 }
569 #endif
570 */
571
572 socketList.Push(r2, _FILE_AND_LINE_ );
573
574 }
575
576 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
577 for (i=0; i<socketDescriptorCount; i++)
578 {
579 if (socketList[i]->IsBerkleySocket())
580 ((RNS2_Berkley*) socketList[i])->CreateRecvPollingThread(threadPriority);
581 }
582 #endif
583
584 // #if !defined(_XBOX) && !defined(_XBOX_720_COMPILE_AS_WINDOWS) && !defined(X360)
585 for (i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
586 {
587 if (ipList[i]==UNASSIGNED_SYSTEM_ADDRESS)
588 break;
589 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
590 if (socketList[0]->IsBerkleySocket())
591 {
592 unsigned short port = ((RNS2_Berkley*)socketList[0])->GetBoundAddress().GetPort();
593 ipList[i].SetPortHostOrder(port);
594
595 }
596 #endif
597 // ipList[i].SetPort(((RNS2_360_720*)socketList[0])->GetBoundAddress().GetPort());
598 }
599 // #endif
600
601
602 if ( maximumNumberOfPeers == 0 )
603 {
604 // Don't allow more incoming connections than we have peers.
605 if ( maximumIncomingConnections > maxConnections )
606 maximumIncomingConnections = maxConnections;
607
608 maximumNumberOfPeers = maxConnections;
609 // 04/19/2006 - Don't overallocate because I'm no longer allowing connected pings.
610 // The disconnects are not consistently processed and the process was sloppy and complicated.
611 // Allocate 10% extra to handle new connections from players trying to connect when the server is full
612 //remoteSystemListSize = maxConnections;// * 11 / 10 + 1;
613
614 // remoteSystemList in Single thread
615 //remoteSystemList = SLNet::OP_NEW<RemoteSystemStruct[ remoteSystemListSize ]>( _FILE_AND_LINE_ );
616 remoteSystemList = SLNet::OP_NEW_ARRAY<RemoteSystemStruct>(maximumNumberOfPeers, _FILE_AND_LINE_ );
617
618 remoteSystemLookup = SLNet::OP_NEW_ARRAY<RemoteSystemIndex*>((unsigned int) maximumNumberOfPeers * REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE, _FILE_AND_LINE_ );
619
620 activeSystemList = SLNet::OP_NEW_ARRAY<RemoteSystemStruct*>(maximumNumberOfPeers, _FILE_AND_LINE_ );
621
622 for ( i = 0; i < maximumNumberOfPeers; i++ )
623 //for ( i = 0; i < remoteSystemListSize; i++ )
624 {
625 // remoteSystemList in Single thread
626 remoteSystemList[ i ].isActive = false;
627 remoteSystemList[ i ].systemAddress = UNASSIGNED_SYSTEM_ADDRESS;
628 remoteSystemList[ i ].guid = UNASSIGNED_RAKNET_GUID;
629 remoteSystemList[ i ].myExternalSystemAddress = UNASSIGNED_SYSTEM_ADDRESS;
630 remoteSystemList[ i ].connectMode=RemoteSystemStruct::NO_ACTION;
631 remoteSystemList[ i ].MTUSize = defaultMTUSize;
632 remoteSystemList[ i ].remoteSystemIndex = (SystemIndex) i;
633 #ifdef _DEBUG
634 remoteSystemList[ i ].reliabilityLayer.ApplyNetworkSimulator(_packetloss, _minExtraPing, _extraPingVariance);
635 #endif
636
637 // All entries in activeSystemList have valid pointers all the time.
638 activeSystemList[ i ] = &remoteSystemList[ i ];
639 }
640
641 for (i=0; i < (unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE; i++)
642 {
643 remoteSystemLookup[i]=0;
644 }
645 }
646
647 // For histogram statistics
648 // nextReadBytesTime=0;
649 // lastSentBytes=lastReceivedBytes=0;
650
651 if ( endThreads )
652 {
653 updateCycleIsRunning = false;
654 endThreads = false;
655 firstExternalID=UNASSIGNED_SYSTEM_ADDRESS;
656
657 ClearBufferedCommands();
658 ClearBufferedPackets();
659 ClearSocketQueryOutput();
660
661 if ( isMainLoopThreadActive == false )
662 {
663 #if RAKPEER_USER_THREADED!=1
664
665 int errorCode;
666
667
668
669
670
671
672
673 errorCode = SLNet::RakThread::Create(UpdateNetworkLoop, this, threadPriority);
674
675
676 if ( errorCode != 0 )
677 {
678 Shutdown( 0, 0 );
679 return FAILED_TO_CREATE_NETWORK_THREAD;
680 }
681 // RakAssert(isRecvFromLoopThreadActive.GetValue()==0);
682 #endif // RAKPEER_USER_THREADED!=1
683
684 /*
685 for (i=0; i<socketDescriptorCount; i++)
686 {
687 RakPeerAndIndex *rpai = SLNet::OP_NEW<RakPeerAndIndex>(_FILE_AND_LINE_);
688 rpai->s=socketList[i];
689 rpai->rakPeer=this;
690
691 #if RAKPEER_USER_THREADED!=1
692
693 #if defined(SN_TARGET_PSP2)
694 sprintf_s(threadName, "RecvFromLoop_%p", this);
695 //errorCode = SLNet::RakThread::Create(RecvFromLoop, rpai, threadPriority, threadName, 1+i, runtime);
696 errorCode = SLNet::RakThread::Create(RecvFromLoop, rpai, threadPriority, threadName, 1024*1);
697 #else
698 errorCode = SLNet::RakThread::Create(RecvFromLoop, rpai, threadPriority);
699 #endif
700
701 if ( errorCode != 0 )
702 {
703 Shutdown( 0, 0 );
704 return FAILED_TO_CREATE_NETWORK_THREAD;
705 }
706 #endif // RAKPEER_USER_THREADED!=1
707 }
708 */
709
710
711 /*
712 #if RAKPEER_USER_THREADED!=1
713
714 while ( isRecvFromLoopThreadActive.GetValue() < (uint32_t) socketDescriptorCount )
715 RakSleep(10);
716 #endif // RAKPEER_USER_THREADED!=1
717 */
718
719 }
720
721 #if RAKPEER_USER_THREADED!=1
722 // Wait for the threads to activate. When they are active they will set these variables to true
723 while ( isMainLoopThreadActive == false )
724 RakSleep(10);
725 #endif // RAKPEER_USER_THREADED!=1
726 }
727
728 for (i=0; i < pluginListTS.Size(); i++)
729 {
730 pluginListTS[i]->OnRakPeerStartup();
731 }
732
733 for (i=0; i < pluginListNTS.Size(); i++)
734 {
735 pluginListNTS[i]->OnRakPeerStartup();
736 }
737
738 #ifdef USE_THREADED_SEND
739 SLNet::SendToThread::AddRef();
740 #endif
741
742 return RAKNET_STARTED;
743 }
744
745 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
746 // Description:
747 // Must be called while offline
748 //
749 // If you accept connections, you must call this or else security will not be enabled for incoming connections.
750 //
751 // This feature requires more round trips, bandwidth, and CPU time for the connection handshake
752 // x64 builds require under 25% of the CPU time of other builds
753 //
754 // See the Encryption sample for example usage
755 //
756 // Parameters:
757 // publicKey = A pointer to the public key for accepting new connections
758 // privateKey = A pointer to the private key for accepting new connections
759 // If the private keys are 0, then a new key will be generated when this function is called
760 // bRequireClientKey: Should be set to false for most servers. Allows the server to accept a public key from connecting clients as a proof of identity but eats twice as much CPU time as a normal connection
761 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
762 bool RakPeer::InitializeSecurity(const char *public_key, const char *private_key, bool bRequireClientKey)
763 {
764 #if LIBCAT_SECURITY==1
765 if ( endThreads == false )
766 return false;
767
768 // Copy client public key requirement flag
769 _require_client_public_key = bRequireClientKey;
770
771 if (_server_handshake)
772 {
773 CAT_AUDIT_PRINTF("AUDIT: Deleting old server_handshake %x\n", _server_handshake);
774 SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
775 }
776 if (_cookie_jar)
777 {
778 CAT_AUDIT_PRINTF("AUDIT: Deleting old cookie jar %x\n", _cookie_jar);
779 SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
780 }
781
782 _server_handshake = SLNet::OP_NEW<cat::ServerEasyHandshake>(_FILE_AND_LINE_);
783 _cookie_jar = SLNet::OP_NEW<cat::CookieJar>(_FILE_AND_LINE_);
784
785 CAT_AUDIT_PRINTF("AUDIT: Created new server_handshake %x\n", _server_handshake);
786 CAT_AUDIT_PRINTF("AUDIT: Created new cookie jar %x\n", _cookie_jar);
787 CAT_AUDIT_PRINTF("AUDIT: Running _server_handshake->Initialize()\n");
788
789 if (_server_handshake->Initialize(public_key, private_key))
790 {
791 CAT_AUDIT_PRINTF("AUDIT: Successfully initialized, filling cookie jar with goodies, storing public key and setting using security flag to true\n");
792
793 _server_handshake->FillCookieJar(_cookie_jar);
794
795 memcpy(my_public_key, public_key, sizeof(my_public_key));
796
797 _using_security = true;
798 return true;
799 }
800
801 CAT_AUDIT_PRINTF("AUDIT: Failure to initialize so deleting server handshake and cookie jar; also setting using_security flag = false\n");
802
803 SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
804 _server_handshake=0;
805 SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
806 _cookie_jar=0;
807 _using_security = false;
808 return false;
809 #else
810 (void) public_key;
811 (void) private_key;
812 (void) bRequireClientKey;
813
814 return false;
815 #endif
816 }
817
818 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
819 // Description
820 // Must be called while offline
821 // Disables security for incoming connections.
822 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
823 void RakPeer::DisableSecurity( void )
824 {
825 #if LIBCAT_SECURITY==1
826 CAT_AUDIT_PRINTF("AUDIT: DisableSecurity() called, so deleting _server_handshake %x and cookie_jar %x\n", _server_handshake, _cookie_jar);
827 SLNet::OP_DELETE(_server_handshake,_FILE_AND_LINE_);
828 _server_handshake=0;
829 SLNet::OP_DELETE(_cookie_jar,_FILE_AND_LINE_);
830 _cookie_jar=0;
831
832 _using_security = false;
833 #endif
834 }
835
836 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
837 void RakPeer::AddToSecurityExceptionList(const char *ip)
838 {
839 securityExceptionMutex.Lock();
840 securityExceptionList.Insert(RakString(ip), _FILE_AND_LINE_);
841 securityExceptionMutex.Unlock();
842 }
843
844 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
845 void RakPeer::RemoveFromSecurityExceptionList(const char *ip)
846 {
847 if (securityExceptionList.Size()==0)
848 return;
849
850 if (ip==0)
851 {
852 securityExceptionMutex.Lock();
853 securityExceptionList.Clear(false, _FILE_AND_LINE_);
854 securityExceptionMutex.Unlock();
855 }
856 else
857 {
858 unsigned i=0;
859 securityExceptionMutex.Lock();
860 while (i < securityExceptionList.Size())
861 {
862 if (securityExceptionList[i].IPAddressMatch(ip))
863 {
864 securityExceptionList[i]=securityExceptionList[securityExceptionList.Size()-1];
865 securityExceptionList.RemoveAtIndex(securityExceptionList.Size()-1);
866 }
867 else
868 i++;
869 }
870 securityExceptionMutex.Unlock();
871 }
872 }
873 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
874 bool RakPeer::IsInSecurityExceptionList(const char *ip)
875 {
876 if (securityExceptionList.Size()==0)
877 return false;
878
879 unsigned i=0;
880 securityExceptionMutex.Lock();
881 for (; i < securityExceptionList.Size(); i++)
882 {
883 if (securityExceptionList[i].IPAddressMatch(ip))
884 {
885 securityExceptionMutex.Unlock();
886 return true;
887 }
888 }
889 securityExceptionMutex.Unlock();
890 return false;
891 }
892
893 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
894 // Description:
895 // Sets how many incoming connections are allowed. If this is less than the number of players currently connected, no
896 // more players will be allowed to connect. If this is greater than the maximum number of peers allowed, it will be reduced
897 // to the maximum number of peers allowed. Defaults to 0.
898 //
899 // Parameters:
900 // numberAllowed - Maximum number of incoming connections allowed.
901 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
902 void RakPeer::SetMaximumIncomingConnections( unsigned short numberAllowed )
903 {
904 maximumIncomingConnections = numberAllowed;
905 }
906
907 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
908 // Description:
909 // Returns the maximum number of incoming connections, which is always <= maxConnections
910 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
911 unsigned int RakPeer::GetMaximumIncomingConnections( void ) const
912 {
913 return maximumIncomingConnections;
914 }
915
916 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
917 // Returns how many open connections there are at this time
918 // \return the number of open connections
919 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
920 unsigned short RakPeer::NumberOfConnections(void) const
921 {
922 DataStructures::List<SystemAddress> addresses;
923 DataStructures::List<RakNetGUID> guids;
924 GetSystemList(addresses, guids);
925 return (unsigned short) addresses.Size();
926 }
927
928 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
929 // Description:
930 // Sets the password incoming connections must match in the call to Connect (defaults to none)
931 // Pass 0 to passwordData to specify no password
932 //
933 // Parameters:
934 // passwordData: A data block that incoming connections must match. This can be just a password, or can be a stream of data.
935 // - Specify 0 for no password data
936 // passwordDataLength: The length in bytes of passwordData
937 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
938 void RakPeer::SetIncomingPassword( const char* passwordData, int passwordDataLength )
939 {
940 //if (passwordDataLength > MAX_OFFLINE_DATA_LENGTH)
941 // passwordDataLength=MAX_OFFLINE_DATA_LENGTH;
942
943 if (passwordDataLength > 255)
944 passwordDataLength=255;
945
946 if (passwordData==0)
947 passwordDataLength=0;
948
949 // Not threadsafe but it's not important enough to lock. Who is going to change the password a lot during runtime?
950 // It won't overflow at least because incomingPasswordLength is an unsigned char
951 if (passwordDataLength>0)
952 memcpy(incomingPassword, passwordData, passwordDataLength);
953 incomingPasswordLength=(unsigned char)passwordDataLength;
954 }
955
956 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
957 void RakPeer::GetIncomingPassword( char* passwordData, int *passwordDataLength )
958 {
959 if (passwordData==0)
960 {
961 *passwordDataLength=incomingPasswordLength;
962 return;
963 }
964
965 if (*passwordDataLength > incomingPasswordLength)
966 *passwordDataLength=incomingPasswordLength;
967
968 if (*passwordDataLength>0)
969 memcpy(passwordData, incomingPassword, *passwordDataLength);
970 }
971
972 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
973 // Description:
974 // Call this to connect to the specified host (ip or domain name) and server port.
975 // Calling Connect and not calling SetMaximumIncomingConnections acts as a dedicated client. Calling both acts as a true peer.
976 // This is a non-blocking connection. You know the connection is successful when IsConnected() returns true
977 // or receive gets a packet with the type identifier ID_CONNECTION_REQUEST_ACCEPTED. If the connection is not
978 // successful, such as rejected connection or no response then neither of these things will happen.
979 // Requires that you first call Initialize
980 //
981 // Parameters:
982 // host: Either a dotted IP address or a domain name
983 // remotePort: Which port to connect to on the remote machine.
984 // 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
985 // passwordDataLength: The length in bytes of passwordData
986 //
987 // Returns:
988 // True on successful initiation. False on incorrect parameters, internal error, or too many existing peers
989 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
990 ConnectionAttemptResult RakPeer::Connect( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, PublicKey *publicKey, unsigned connectionSocketIndex, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime )
991 {
992 // If endThreads is true here you didn't call Startup() first.
993 if ( host == 0 || endThreads || connectionSocketIndex>=socketList.Size() )
994 return INVALID_PARAMETER;
995
996 RakAssert(remotePort!=0);
997
998 connectionSocketIndex=GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
999
1000 if (passwordDataLength>255)
1001 passwordDataLength=255;
1002
1003 if (passwordData==0)
1004 passwordDataLength=0;
1005
1006 // Not threadsafe but it's not important enough to lock. Who is going to change the password a lot during runtime?
1007 // It won't overflow at least because outgoingPasswordLength is an unsigned char
1008 // if (passwordDataLength>0)
1009 // memcpy(outgoingPassword, passwordData, passwordDataLength);
1010 // outgoingPasswordLength=(unsigned char) passwordDataLength;
1011
1012 // 04/02/09 - Can't remember why I disabled connecting to self, but it seems to work
1013 // Connecting to ourselves in the same instance of the program?
1014 // if ( ( strcmp( host, "127.0.0.1" ) == 0 || strcmp( host, "0.0.0.0" ) == 0 ) && remotePort == mySystemAddress[0].port )
1015 // return false;
1016
1017 return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, publicKey, connectionSocketIndex, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime);
1018 }
1019
1020 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1021
1022 ConnectionAttemptResult RakPeer::ConnectWithSocket(const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, RakNetSocket2* socket, PublicKey *publicKey, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime)
1023 {
1024 if ( host == 0 || endThreads || socket == 0 )
1025 return INVALID_PARAMETER;
1026
1027 if (passwordDataLength>255)
1028 passwordDataLength=255;
1029
1030 if (passwordData==0)
1031 passwordDataLength=0;
1032
1033 return SendConnectionRequest( host, remotePort, passwordData, passwordDataLength, publicKey, 0, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS, timeoutTime, socket );
1034
1035 }
1036
1037 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1038 // Description:
1039 // Stops the network threads and close all connections. Multiple calls are ok.
1040 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1041 void RakPeer::Shutdown( unsigned int blockDuration, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
1042 {
1043 unsigned i,j;
1044 bool anyActive;
1045 SLNet::TimeMS startWaitingTime;
1046 // SystemAddress systemAddress;
1047 SLNet::TimeMS time;
1048 //unsigned short systemListSize = remoteSystemListSize; // This is done for threading reasons
1049 unsigned int systemListSize = maximumNumberOfPeers;
1050
1051 if ( blockDuration > 0 )
1052 {
1053 for ( i = 0; i < systemListSize; i++ )
1054 {
1055 // remoteSystemList in user thread
1056 if (remoteSystemList[i].isActive)
1057 NotifyAndFlagForShutdown(remoteSystemList[i].systemAddress, false, orderingChannel, disconnectionNotificationPriority);
1058 }
1059
1060 time = SLNet::GetTimeMS();
1061 startWaitingTime = time;
1062 while ( time - startWaitingTime < blockDuration )
1063 {
1064 anyActive=false;
1065 for (j=0; j < systemListSize; j++)
1066 {
1067 // remoteSystemList in user thread
1068 if (remoteSystemList[j].isActive)
1069 {
1070 anyActive=true;
1071 break;
1072 }
1073 }
1074
1075 // If this system is out of packets to send, then stop waiting
1076 if ( anyActive==false )
1077 break;
1078
1079 // This will probably cause the update thread to run which will probably
1080 // send the disconnection notification
1081
1082 RakSleep(15);
1083 time = SLNet::GetTimeMS();
1084 }
1085 }
1086 for (i=0; i < pluginListTS.Size(); i++)
1087 {
1088 pluginListTS[i]->OnRakPeerShutdown();
1089 }
1090 for (i=0; i < pluginListNTS.Size(); i++)
1091 {
1092 pluginListNTS[i]->OnRakPeerShutdown();
1093 }
1094
1095 quitAndDataEvents.SetEvent();
1096
1097 endThreads = true;
1098
1099 // SLNet::TimeMS timeout;
1100 #if RAKPEER_USER_THREADED!=1
1101
1102 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
1103 for (i=0; i < socketList.Size(); i++)
1104 {
1105 if (socketList[i]->IsBerkleySocket())
1106 {
1107 ((RNS2_Berkley *)socketList[i])->SignalStopRecvPollingThread();
1108 }
1109 }
1110 #endif
1111
1112 /*
1113 // Get recvfrom to unblock
1114 for (i=0; i < socketList.Size(); i++)
1115 {
1116 if (SocketLayer::SendTo(socketList[i], (const char*) &i,1,socketList[i]->GetBoundAddress(), _FILE_AND_LINE_)!=0)
1117 break;
1118 }
1119 */
1120
1121 while ( isMainLoopThreadActive )
1122 {
1123 endThreads = true;
1124 RakSleep(15);
1125 }
1126
1127 activeSystemListSize = 0;
1128
1129 /*
1130 timeout = SLNet::GetTimeMS()+1000;
1131 while ( isRecvFromLoopThreadActive.GetValue()>0 && SLNet::GetTimeMS()<timeout )
1132 {
1133 // Get recvfrom to unblock
1134 for (i=0; i < socketList.Size(); i++)
1135 {
1136 SocketLayer::SendTo(socketList[i], (const char*) &i,1,socketList[i]->GetBoundAddress(), _FILE_AND_LINE_);
1137 }
1138
1139 RakSleep(30);
1140 }
1141 */
1142
1143 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
1144 for (i=0; i < socketList.Size(); i++)
1145 {
1146 if (socketList[i]->IsBerkleySocket())
1147 {
1148 ((RNS2_Berkley *)socketList[i])->BlockOnStopRecvPollingThread();
1149 }
1150 }
1151 #endif
1152
1153
1154 #endif // RAKPEER_USER_THREADED!=1
1155
1156 // char c=0;
1157 // unsigned int socketIndex;
1158 // remoteSystemList in Single thread
1159 for ( i = 0; i < systemListSize; i++ )
1160 {
1161 // Reserve this reliability layer for ourselves
1162 remoteSystemList[ i ].isActive = false;
1163
1164 // Remove any remaining packets
1165 RakAssert(remoteSystemList[ i ].MTUSize <= MAXIMUM_MTU_SIZE);
1166 remoteSystemList[ i ].reliabilityLayer.Reset(false, remoteSystemList[ i ].MTUSize, false);
1167 remoteSystemList[ i ].rakNetSocket = 0;
1168 }
1169
1170
1171 // Setting maximumNumberOfPeers to 0 allows remoteSystemList to be reallocated in Initialize.
1172 // Setting remoteSystemListSize prevents threads from accessing the reliability layer
1173 maximumNumberOfPeers = 0;
1174 //remoteSystemListSize = 0;
1175
1176 // Free any packets the user didn't deallocate
1177 packetReturnMutex.Lock();
1178 for (i=0; i < packetReturnQueue.Size(); i++)
1179 DeallocatePacket(packetReturnQueue[i]);
1180 packetReturnQueue.Clear(_FILE_AND_LINE_);
1181 packetReturnMutex.Unlock();
1182 packetAllocationPoolMutex.Lock();
1183 packetAllocationPool.Clear(_FILE_AND_LINE_);
1184 packetAllocationPoolMutex.Unlock();
1185
1186 /*
1187 if (isRecvFromLoopThreadActive.GetValue()>0)
1188 {
1189 timeout = SLNet::GetTimeMS()+1000;
1190 while ( isRecvFromLoopThreadActive.GetValue()>0 && SLNet::GetTimeMS()<timeout )
1191 {
1192 RakSleep(30);
1193 }
1194 }
1195 */
1196
1197 DerefAllSockets();
1198
1199 ClearBufferedCommands();
1200 ClearBufferedPackets();
1201 ClearSocketQueryOutput();
1202 bytesSentPerSecond = bytesReceivedPerSecond = 0;
1203
1204 ClearRequestedConnectionList();
1205
1206
1207 // Clear out the reliability layer list in case we want to reallocate it in a successive call to Init.
1208 RemoteSystemStruct * temp = remoteSystemList;
1209 remoteSystemList = 0;
1210 SLNet::OP_DELETE_ARRAY(temp, _FILE_AND_LINE_);
1211 SLNet::OP_DELETE_ARRAY(activeSystemList, _FILE_AND_LINE_);
1212 activeSystemList=0;
1213
1214 ClearRemoteSystemLookup();
1215
1216 #ifdef USE_THREADED_SEND
1217 SLNet::SendToThread::Deref();
1218 #endif
1219
1220 ResetSendReceipt();
1221 }
1222
1223 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1224 // Description:
1225 // Returns true if the network threads are running
1226 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1227 inline bool RakPeer::IsActive( void ) const
1228 {
1229 return endThreads == false;
1230 }
1231
1232 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1233 // Description:
1234 // Fills the array remoteSystems with the systemAddress of all the systems we are connected to
1235 //
1236 // Parameters:
1237 // remoteSystems (out): An array of SystemAddress structures to be filled with the SystemAddresss of the systems we are connected to
1238 // - pass 0 to remoteSystems to only get the number of systems we are connected to
1239 // numberOfSystems (int, out): As input, the size of remoteSystems array. As output, the number of elements put into the array
1240 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1241 bool RakPeer::GetConnectionList( SystemAddress *remoteSystems, unsigned short *numberOfSystems ) const
1242 {
1243 if (numberOfSystems==0)
1244 return false;
1245
1246 if ( remoteSystemList == 0 || endThreads == true )
1247 {
1248 if (numberOfSystems)
1249 *numberOfSystems=0;
1250 return false;
1251 }
1252
1253 DataStructures::List<SystemAddress> addresses;
1254 DataStructures::List<RakNetGUID> guids;
1255 GetSystemList(addresses, guids);
1256 if (remoteSystems)
1257 {
1258 unsigned short i;
1259 for (i=0; i < *numberOfSystems && i < addresses.Size(); i++)
1260 remoteSystems[i]=addresses[i];
1261 *numberOfSystems=i;
1262 }
1263 else
1264 {
1265 *numberOfSystems=(unsigned short) addresses.Size();
1266 }
1267 return true;
1268 }
1269
1270 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1271 uint32_t RakPeer::GetNextSendReceipt(void)
1272 {
1273 sendReceiptSerialMutex.Lock();
1274 uint32_t retVal = sendReceiptSerial;
1275 sendReceiptSerialMutex.Unlock();
1276 return retVal;
1277 }
1278 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1279 uint32_t RakPeer::IncrementNextSendReceipt(void)
1280 {
1281 sendReceiptSerialMutex.Lock();
1282 uint32_t returned = sendReceiptSerial;
1283 if (++sendReceiptSerial==0)
1284 sendReceiptSerial=1;
1285 sendReceiptSerialMutex.Unlock();
1286 return returned;
1287 }
1288
1289 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1290 // Description:
1291 // Sends a block of data to the specified system that you are connected to.
1292 // This function only works while the client is connected (Use the Connect function).
1293 // The first byte should be a message identifier starting at ID_USER_PACKET_ENUM
1294 //
1295 // Parameters:
1296 // data: The block of data to send
1297 // length: The size in bytes of the data to send
1298 // bitStream: The bitstream to send
1299 // priority: What priority level to send on.
1300 // reliability: How reliability to send this data
1301 // orderingChannel: When using ordered or sequenced packets, what channel to order these on.
1302 // - Packets are only ordered relative to other packets on the same stream
1303 // 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
1304 // broadcast: True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to.
1305 // Returns:
1306 // \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
1307 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1308 uint32_t RakPeer::Send( const char *data, const int length, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceiptNumber )
1309 {
1310 #ifdef _DEBUG
1311 RakAssert( data && length > 0 );
1312 #endif
1313 RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
1314 RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
1315 RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
1316
1317 if ( data == 0 || length < 0 )
1318 return 0;
1319
1320 if ( remoteSystemList == 0 || endThreads == true )
1321 return 0;
1322
1323 if ( broadcast == false && systemIdentifier.IsUndefined())
1324 return 0;
1325
1326 uint32_t usedSendReceipt;
1327 if (forceReceiptNumber!=0)
1328 usedSendReceipt=forceReceiptNumber;
1329 else
1330 usedSendReceipt=IncrementNextSendReceipt();
1331
1332 if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
1333 {
1334 SendLoopback(data,length);
1335
1336 if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
1337 {
1338 char buff[5];
1339 buff[0]=ID_SND_RECEIPT_ACKED;
1340 sendReceiptSerialMutex.Lock();
1341 memcpy(buff+1, &sendReceiptSerial, 4);
1342 sendReceiptSerialMutex.Unlock();
1343 SendLoopback( buff, 5 );
1344 }
1345
1346 return usedSendReceipt;
1347 }
1348
1349 SendBuffered(data, length*8, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1350
1351 return usedSendReceipt;
1352 }
1353
1354 void RakPeer::SendLoopback( const char *data, const int length )
1355 {
1356 if ( data == 0 || length < 0 )
1357 return;
1358
1359 Packet *packet = AllocPacket(length, _FILE_AND_LINE_);
1360 memcpy(packet->data, data, length);
1361 packet->systemAddress = GetLoopbackAddress();
1362 packet->guid=myGuid;
1363 PushBackPacket(packet, false);
1364 }
1365
1366 uint32_t RakPeer::Send( const SLNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, uint32_t forceReceiptNumber )
1367 {
1368 #ifdef _DEBUG
1369 RakAssert( bitStream->GetNumberOfBytesUsed() > 0 );
1370 #endif
1371
1372 RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
1373 RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
1374 RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
1375
1376 if ( bitStream->GetNumberOfBytesUsed() == 0 )
1377 return 0;
1378
1379 if ( remoteSystemList == 0 || endThreads == true )
1380 return 0;
1381
1382 if ( broadcast == false && systemIdentifier.IsUndefined() )
1383 return 0;
1384
1385 uint32_t usedSendReceipt;
1386 if (forceReceiptNumber!=0)
1387 usedSendReceipt=forceReceiptNumber;
1388 else
1389 usedSendReceipt=IncrementNextSendReceipt();
1390
1391 if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
1392 {
1393 SendLoopback((const char*) bitStream->GetData(),bitStream->GetNumberOfBytesUsed());
1394 if (reliability>=UNRELIABLE_WITH_ACK_RECEIPT)
1395 {
1396 char buff[5];
1397 buff[0]=ID_SND_RECEIPT_ACKED;
1398 sendReceiptSerialMutex.Lock();
1399 memcpy(buff+1, &sendReceiptSerial,4);
1400 sendReceiptSerialMutex.Unlock();
1401 SendLoopback( buff, 5 );
1402 }
1403 return usedSendReceipt;
1404 }
1405
1406 // Sends need to be buffered and processed in the update thread because the systemAddress associated with the reliability layer can change,
1407 // from that thread, resulting in a send to the wrong player! While I could mutex the systemAddress, that is much slower than doing this
1408 SendBuffered((const char*)bitStream->GetData(), bitStream->GetNumberOfBitsUsed(), priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1409
1410
1411 return usedSendReceipt;
1412 }
1413 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1414 // Sends multiple blocks of data, concatenating them automatically.
1415 //
1416 // This is equivalent to:
1417 // SLNet::BitStream bs;
1418 // bs.WriteAlignedBytes(block1, blockLength1);
1419 // bs.WriteAlignedBytes(block2, blockLength2);
1420 // bs.WriteAlignedBytes(block3, blockLength3);
1421 // Send(&bs, ...)
1422 //
1423 // This function only works while connected
1424 // \param[in] data An array of pointers to blocks of data
1425 // \param[in] lengths An array of integers indicating the length of each block of data
1426 // \param[in] numParameters Length of the arrays data and lengths
1427 // \param[in] priority What priority level to send on. See PacketPriority.h
1428 // \param[in] reliability How reliability to send this data. See PacketPriority.h
1429 // \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
1430 // \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
1431 // \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to.
1432 // \return False if we are not connected to the specified recipient. True otherwise
1433 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1434 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 forceReceiptNumber )
1435 {
1436 #ifdef _DEBUG
1437 RakAssert( data );
1438 #endif
1439
1440 if ( data == 0 || lengths == 0 )
1441 return 0;
1442
1443 if ( remoteSystemList == 0 || endThreads == true )
1444 return 0;
1445
1446 if (numParameters==0)
1447 return 0;
1448
1449 if (lengths==0)
1450 return 0;
1451
1452 if ( broadcast == false && systemIdentifier.IsUndefined() )
1453 return 0;
1454
1455 uint32_t usedSendReceipt;
1456 if (forceReceiptNumber!=0)
1457 usedSendReceipt=forceReceiptNumber;
1458 else
1459 usedSendReceipt=IncrementNextSendReceipt();
1460
1461 SendBufferedList(data, lengths, numParameters, priority, reliability, orderingChannel, systemIdentifier, broadcast, RemoteSystemStruct::NO_ACTION, usedSendReceipt);
1462
1463 return usedSendReceipt;
1464 }
1465
1466 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1467 // Description:
1468 // Gets a packet from the incoming packet queue. Use DeallocatePacket to deallocate the packet after you are done with it.
1469 // Check the Packet struct at the top of CoreNetworkStructures.h for the format of the struct
1470 //
1471 // Returns:
1472 // 0 if no packets are waiting to be handled, otherwise an allocated packet
1473 // If the client is not active this will also return 0, as all waiting packets are flushed when the client is Disconnected
1474 // This also updates all memory blocks associated with synchronized memory and distributed objects
1475 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1476 Packet* RakPeer::Receive( void )
1477 {
1478 if ( !( IsActive() ) )
1479 return 0;
1480
1481 SLNet::Packet *packet;
1482 // Packet **threadPacket;
1483 PluginReceiveResult pluginResult;
1484
1485 int offset;
1486 unsigned int i;
1487
1488 // User should call RunUpdateCycle and RunRecvFromOnce to do this commented code
1489 /*
1490 #if RAKPEER_SINGLE_THREADED==1
1491 RakPeer::RecvFromStruct *recvFromStruct;
1492 for (i=0; i < socketList.Size(); i++)
1493 {
1494 for(;;)
1495 {
1496 recvFromStruct=bufferedPackets.Allocate( _FILE_AND_LINE_ );
1497 recvFromStruct->s=socketList[i]->s;
1498 recvFromStruct->remotePortRakNetWasStartedOn_PS3=socketList[i]->remotePortRakNetWasStartedOn_PS3_PSP2;
1499 recvFromStruct->extraSocketOptions=socketList[i]->extraSocketOptions;
1500 SocketLayer::RecvFromBlocking(
1501 recvFromStruct->s, this, recvFromStruct->remotePortRakNetWasStartedOn_PS3,
1502 recvFromStruct->extraSocketOptions, recvFromStruct->data, &recvFromStruct->bytesRead, &recvFromStruct->systemAddress, &recvFromStruct->timeRead);
1503 if (recvFromStruct->bytesRead<=0)
1504 {
1505 bufferedPackets.Deallocate(recvFromStruct, _FILE_AND_LINE_);
1506 break;
1507 }
1508 else
1509 {
1510 RakAssert(recvFromStruct->systemAddress.GetPort());
1511 bufferedPackets.Push(recvFromStruct);
1512 }
1513 }
1514 }
1515
1516 BitStream updateBitStream( MAXIMUM_MTU_SIZE
1517 #if LIBCAT_SECURITY==1
1518 + cat::AuthenticatedEncryption::OVERHEAD_BYTES
1519 #endif
1520 );
1521 RunUpdateCycle(0, 0, updateBitStream);
1522 #endif
1523 */
1524
1525 for (i=0; i < pluginListTS.Size(); i++)
1526 {
1527 pluginListTS[i]->Update();
1528 }
1529 for (i=0; i < pluginListNTS.Size(); i++)
1530 {
1531 pluginListNTS[i]->Update();
1532 }
1533
1534 do
1535 {
1536 packetReturnMutex.Lock();
1537 if (packetReturnQueue.IsEmpty())
1538 packet=0;
1539 else
1540 packet = packetReturnQueue.Pop();
1541 packetReturnMutex.Unlock();
1542 if (packet==0)
1543 return 0;
1544
1545 // unsigned char msgId;
1546 if ( ( packet->length >= sizeof(unsigned char) + sizeof(SLNet::Time ) ) &&
1547 ( (unsigned char) packet->data[ 0 ] == ID_TIMESTAMP ) )
1548 {
1549 offset = sizeof(unsigned char);
1550 ShiftIncomingTimestamp( packet->data + offset, packet->systemAddress );
1551 // msgId=packet->data[sizeof(unsigned char) + sizeof( SLNet::Time )];
1552 }
1553 // else
1554 // msgId=packet->data[0];
1555
1556 // Some locally generated packets need to be processed by plugins, for example ID_FCM2_NEW_HOST
1557 // The plugin itself should intercept these messages generated remotely
1558 // if (packet->wasGeneratedLocally)
1559 // return packet;
1560
1561
1562 CallPluginCallbacks(pluginListTS, packet);
1563 CallPluginCallbacks(pluginListNTS, packet);
1564
1565 for (i=0; i < pluginListTS.Size(); i++)
1566 {
1567 pluginResult=pluginListTS[i]->OnReceive(packet);
1568 if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
1569 {
1570 DeallocatePacket( packet );
1571 packet=0; // Will do the loop again and get another packet
1572 break; // break out of the enclosing for
1573 }
1574 else if (pluginResult==RR_STOP_PROCESSING)
1575 {
1576 packet=0;
1577 break;
1578 }
1579 }
1580
1581 for (i=0; i < pluginListNTS.Size(); i++)
1582 {
1583 pluginResult=pluginListNTS[i]->OnReceive(packet);
1584 if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
1585 {
1586 DeallocatePacket( packet );
1587 packet=0; // Will do the loop again and get another packet
1588 break; // break out of the enclosing for
1589 }
1590 else if (pluginResult==RR_STOP_PROCESSING)
1591 {
1592 packet=0;
1593 break;
1594 }
1595 }
1596
1597 } while(packet==0);
1598
1599 #ifdef _DEBUG
1600 RakAssert( packet->data );
1601 #endif
1602
1603 return packet;
1604 }
1605
1606 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1607 // Description:
1608 // Call this to deallocate a packet returned by Receive
1609 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1610 void RakPeer::DeallocatePacket( Packet *packet )
1611 {
1612 if ( packet == 0 )
1613 return;
1614
1615 if (packet->deleteData)
1616 {
1617 rakFree_Ex(packet->data, _FILE_AND_LINE_ );
1618 packet->~Packet();
1619 packetAllocationPoolMutex.Lock();
1620 packetAllocationPool.Release(packet,_FILE_AND_LINE_);
1621 packetAllocationPoolMutex.Unlock();
1622 }
1623 else
1624 {
1625 rakFree_Ex(packet, _FILE_AND_LINE_ );
1626 }
1627 }
1628
1629 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1630 // Description:
1631 // Return the total number of connections we are allowed
1632 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1633 unsigned int RakPeer::GetMaximumNumberOfPeers( void ) const
1634 {
1635 return maximumNumberOfPeers;
1636 }
1637
1638 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1639 // Description:
1640 // Close the connection to another host (if we initiated the connection it will disconnect, if they did it will kick them out).
1641 //
1642 // Parameters:
1643 // target: Which connection to close
1644 // sendDisconnectionNotification: True to send ID_DISCONNECTION_NOTIFICATION to the recipient. False to close it silently.
1645 // channel: If blockDuration > 0, the disconnect packet will be sent on this channel
1646 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1647 void RakPeer::CloseConnection( const AddressOrGUID target, bool sendDisconnectionNotification, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
1648 {
1649 /*
1650 // This only be called from the user thread, for the user shutting down.
1651 // From the network thread, this should occur because of ID_DISCONNECTION_NOTIFICATION and ID_CONNECTION_LOST
1652 unsigned j;
1653 for (j=0; j < messageHandlerList.Size(); j++)
1654 {
1655 messageHandlerList[j]->OnClosedConnection(
1656 target.systemAddress==UNASSIGNED_SYSTEM_ADDRESS ? GetSystemAddressFromGuid(target.rakNetGuid) : target.systemAddress,
1657 target.rakNetGuid==UNASSIGNED_RAKNET_GUID ? GetGuidFromSystemAddress(target.systemAddress) : target.rakNetGuid,
1658 LCR_CLOSED_BY_USER);
1659 }
1660 */
1661
1662 CloseConnectionInternal(target, sendDisconnectionNotification, false, orderingChannel, disconnectionNotificationPriority);
1663
1664 // 12/14/09 Return ID_CONNECTION_LOST when calling CloseConnection with sendDisconnectionNotification==false, elsewise it is never returned
1665 if (sendDisconnectionNotification==false && GetConnectionState(target)==IS_CONNECTED)
1666 {
1667 Packet *packet=AllocPacket(sizeof( char ), _FILE_AND_LINE_);
1668 packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
1669 packet->guid = target.rakNetGuid==UNASSIGNED_RAKNET_GUID ? GetGuidFromSystemAddress(target.systemAddress) : target.rakNetGuid;
1670 packet->systemAddress = target.systemAddress==UNASSIGNED_SYSTEM_ADDRESS ? GetSystemAddressFromGuid(target.rakNetGuid) : target.systemAddress;
1671 packet->systemAddress.systemIndex = (SystemIndex) GetIndexFromSystemAddress(packet->systemAddress);
1672 packet->guid.systemIndex=packet->systemAddress.systemIndex;
1673 packet->wasGeneratedLocally=true; // else processed twice
1674 AddPacketToProducer(packet);
1675 }
1676 }
1677
1678 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1679 // Cancel a pending connection attempt
1680 // If we are already connected, the connection stays open
1681 // \param[in] target Which system to cancel
1682 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1683 void RakPeer::CancelConnectionAttempt( const SystemAddress target )
1684 {
1685 unsigned int i;
1686
1687 // Cancel pending connection attempt, if there is one
1688 i=0;
1689 requestedConnectionQueueMutex.Lock();
1690 while (i < requestedConnectionQueue.Size())
1691 {
1692 if (requestedConnectionQueue[i]->systemAddress==target)
1693 {
1694 #if LIBCAT_SECURITY==1
1695 CAT_AUDIT_PRINTF("AUDIT: Deleting requestedConnectionQueue %i client_handshake %x\n", i, requestedConnectionQueue[ i ]->client_handshake);
1696 SLNet::OP_DELETE(requestedConnectionQueue[i]->client_handshake, _FILE_AND_LINE_ );
1697 #endif
1698 SLNet::OP_DELETE(requestedConnectionQueue[i], _FILE_AND_LINE_ );
1699 requestedConnectionQueue.RemoveAtIndex(i);
1700 break;
1701 }
1702 else
1703 i++;
1704 }
1705 requestedConnectionQueueMutex.Unlock();
1706
1707 }
1708
1709 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1710
1711 ConnectionState RakPeer::GetConnectionState(const AddressOrGUID systemIdentifier)
1712 {
1713 if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
1714 {
1715 unsigned int i=0;
1716 requestedConnectionQueueMutex.Lock();
1717 for (; i < requestedConnectionQueue.Size(); i++)
1718 {
1719 if (requestedConnectionQueue[i]->systemAddress==systemIdentifier.systemAddress)
1720 {
1721 requestedConnectionQueueMutex.Unlock();
1722 return IS_PENDING;
1723 }
1724 }
1725 requestedConnectionQueueMutex.Unlock();
1726 }
1727
1728 int index;
1729 if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
1730 {
1731 index = GetIndexFromSystemAddress(systemIdentifier.systemAddress, false);
1732 }
1733 else
1734 {
1735 index = GetIndexFromGuid(systemIdentifier.rakNetGuid);
1736 }
1737
1738 if (index==-1)
1739 return IS_NOT_CONNECTED;
1740
1741 if (remoteSystemList[index].isActive==false)
1742 return IS_DISCONNECTED;
1743
1744 switch (remoteSystemList[index].connectMode)
1745 {
1746 case RemoteSystemStruct::DISCONNECT_ASAP:
1747 return IS_DISCONNECTING;
1748 case RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY:
1749 return IS_SILENTLY_DISCONNECTING;
1750 case RemoteSystemStruct::DISCONNECT_ON_NO_ACK:
1751 return IS_DISCONNECTING;
1752 case RemoteSystemStruct::REQUESTED_CONNECTION:
1753 return IS_CONNECTING;
1754 case RemoteSystemStruct::HANDLING_CONNECTION_REQUEST:
1755 return IS_CONNECTING;
1756 case RemoteSystemStruct::UNVERIFIED_SENDER:
1757 return IS_CONNECTING;
1758 case RemoteSystemStruct::CONNECTED:
1759 return IS_CONNECTED;
1760 default:
1761 return IS_NOT_CONNECTED;
1762 }
1763 }
1764
1765
1766 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1767 // Description:
1768 // Given a systemAddress, returns an index from 0 to the maximum number of players allowed - 1.
1769 //
1770 // Parameters
1771 // systemAddress - The systemAddress to search for
1772 //
1773 // Returns
1774 // An integer from 0 to the maximum number of peers -1, or -1 if that player is not found
1775 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1776 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress ) const
1777 {
1778 return GetIndexFromSystemAddress(systemAddress, false);
1779 }
1780
1781 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1782 // Description:
1783 // This function is only useful for looping through all players.
1784 //
1785 // Parameters
1786 // index - an integer between 0 and the maximum number of players allowed - 1.
1787 //
1788 // Returns
1789 // A valid systemAddress or UNASSIGNED_SYSTEM_ADDRESS if no such player at that index
1790 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1791 SystemAddress RakPeer::GetSystemAddressFromIndex( unsigned int index )
1792 {
1793 // remoteSystemList in user thread
1794 //if ( index >= 0 && index < remoteSystemListSize )
1795 if ( index < maximumNumberOfPeers )
1796 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
1797 return remoteSystemList[ index ].systemAddress;
1798
1799 return UNASSIGNED_SYSTEM_ADDRESS;
1800 }
1801
1802 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1803 // Same as GetSystemAddressFromIndex but returns RakNetGUID
1804 // \param[in] index Index should range between 0 and the maximum number of players allowed - 1.
1805 // \return The RakNetGUID
1806 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1807 RakNetGUID RakPeer::GetGUIDFromIndex( unsigned int index )
1808 {
1809 // remoteSystemList in user thread
1810 //if ( index >= 0 && index < remoteSystemListSize )
1811 if ( index < maximumNumberOfPeers )
1812 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
1813 return remoteSystemList[ index ].guid;
1814
1815 return UNASSIGNED_RAKNET_GUID;
1816 }
1817
1818 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1819 // Same as calling GetSystemAddressFromIndex and GetGUIDFromIndex for all systems, but more efficient
1820 // Indices match each other, so \a addresses[0] and \a guids[0] refer to the same system
1821 // \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.
1822 // \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.
1823 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1824 void RakPeer::GetSystemList(DataStructures::List<SystemAddress> &addresses, DataStructures::List<RakNetGUID> &guids) const
1825 {
1826 addresses.Clear(false, _FILE_AND_LINE_);
1827 guids.Clear(false, _FILE_AND_LINE_);
1828
1829 if ( remoteSystemList == 0 || endThreads == true )
1830 return;
1831
1832 unsigned int i;
1833 for (i=0; i < activeSystemListSize; i++)
1834 {
1835 if ((activeSystemList[i])->isActive &&
1836 (activeSystemList[i])->connectMode==RakPeer::RemoteSystemStruct::CONNECTED)
1837 {
1838 addresses.Push((activeSystemList[i])->systemAddress, _FILE_AND_LINE_ );
1839 guids.Push((activeSystemList[i])->guid, _FILE_AND_LINE_ );
1840 }
1841 }
1842 }
1843
1844 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1845 // Description:
1846 // Bans an IP from connecting. Banned IPs persist between connections.
1847 //
1848 // Parameters
1849 // IP - Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will ban
1850 // All IP addresses starting with 128.0.0
1851 // milliseconds - how many ms for a temporary ban. Use 0 for a permanent ban
1852 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1853 void RakPeer::AddToBanList( const char *IP, SLNet::TimeMS milliseconds )
1854 {
1855 unsigned index;
1856 SLNet::TimeMS time = SLNet::GetTimeMS();
1857
1858 if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
1859 return ;
1860
1861 // If this guy is already in the ban list, do nothing
1862 index = 0;
1863
1864 banListMutex.Lock();
1865
1866 for ( ; index < banList.Size(); index++ )
1867 {
1868 if ( strcmp( IP, banList[ index ]->IP ) == 0 )
1869 {
1870 // Already in the ban list. Just update the time
1871 if (milliseconds==0)
1872 banList[ index ]->timeout=0; // Infinite
1873 else
1874 banList[ index ]->timeout=time+milliseconds;
1875 banListMutex.Unlock();
1876 return;
1877 }
1878 }
1879
1880 banListMutex.Unlock();
1881
1882 BanStruct *banStruct = SLNet::OP_NEW<BanStruct>( _FILE_AND_LINE_ );
1883 banStruct->IP = (char*) rakMalloc_Ex( 16, _FILE_AND_LINE_ );
1884 if (milliseconds==0)
1885 banStruct->timeout=0; // Infinite
1886 else
1887 banStruct->timeout=time+milliseconds;
1888 strcpy_s( banStruct->IP, 16, IP );
1889 banListMutex.Lock();
1890 banList.Insert( banStruct, _FILE_AND_LINE_ );
1891 banListMutex.Unlock();
1892 }
1893
1894 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1895 // Description:
1896 // Allows a previously banned IP to connect.
1897 //
1898 // Parameters
1899 // IP - Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will ban
1900 // All IP addresses starting with 128.0.0
1901 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1902 void RakPeer::RemoveFromBanList( const char *IP )
1903 {
1904 unsigned index;
1905 BanStruct *temp;
1906
1907 if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
1908 return ;
1909
1910 index = 0;
1911 temp=0;
1912
1913 banListMutex.Lock();
1914
1915 for ( ; index < banList.Size(); index++ )
1916 {
1917 if ( strcmp( IP, banList[ index ]->IP ) == 0 )
1918 {
1919 temp = banList[ index ];
1920 banList[ index ] = banList[ banList.Size() - 1 ];
1921 banList.RemoveAtIndex( banList.Size() - 1 );
1922 break;
1923 }
1924 }
1925
1926 banListMutex.Unlock();
1927
1928 if (temp)
1929 {
1930 rakFree_Ex(temp->IP, _FILE_AND_LINE_ );
1931 SLNet::OP_DELETE(temp, _FILE_AND_LINE_);
1932 }
1933
1934 }
1935
1936 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1937 // Description:
1938 // Allows all previously banned IPs to connect.
1939 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1940 void RakPeer::ClearBanList( void )
1941 {
1942 unsigned index;
1943 index = 0;
1944 banListMutex.Lock();
1945
1946 for ( ; index < banList.Size(); index++ )
1947 {
1948 rakFree_Ex(banList[ index ]->IP, _FILE_AND_LINE_ );
1949 SLNet::OP_DELETE(banList[ index ], _FILE_AND_LINE_);
1950 }
1951
1952 banList.Clear(false, _FILE_AND_LINE_);
1953
1954 banListMutex.Unlock();
1955 }
1956 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1957 void RakPeer::SetLimitIPConnectionFrequency(bool b)
1958 {
1959 limitConnectionFrequencyFromTheSameIP=b;
1960 }
1961
1962 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1963 // Description:
1964 // Determines if a particular IP is banned.
1965 //
1966 // Parameters
1967 // IP - Complete dotted IP address
1968 //
1969 // Returns
1970 // True if IP matches any IPs in the ban list, accounting for any wildcards.
1971 // False otherwise.
1972 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1973 bool RakPeer::IsBanned( const char *IP )
1974 {
1975 unsigned banListIndex, characterIndex;
1976 SLNet::TimeMS time;
1977 BanStruct *temp;
1978
1979 if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
1980 return false;
1981
1982 banListIndex = 0;
1983
1984 if ( banList.Size() == 0 )
1985 return false; // Skip the mutex if possible
1986
1987 time = SLNet::GetTimeMS();
1988
1989 banListMutex.Lock();
1990
1991 while ( banListIndex < banList.Size() )
1992 {
1993 if (banList[ banListIndex ]->timeout>0 && banList[ banListIndex ]->timeout<time)
1994 {
1995 // Delete expired ban
1996 temp = banList[ banListIndex ];
1997 banList[ banListIndex ] = banList[ banList.Size() - 1 ];
1998 banList.RemoveAtIndex( banList.Size() - 1 );
1999 rakFree_Ex(temp->IP, _FILE_AND_LINE_ );
2000 SLNet::OP_DELETE(temp, _FILE_AND_LINE_);
2001 }
2002 else
2003 {
2004 characterIndex = 0;
2005
2006 for(;;)
2007 {
2008 if ( banList[ banListIndex ]->IP[ characterIndex ] == IP[ characterIndex ] )
2009 {
2010 // Equal characters
2011
2012 if ( IP[ characterIndex ] == 0 )
2013 {
2014 banListMutex.Unlock();
2015 // End of the string and the strings match
2016
2017 return true;
2018 }
2019
2020 characterIndex++;
2021 }
2022
2023 else
2024 {
2025 if ( banList[ banListIndex ]->IP[ characterIndex ] == 0 || IP[ characterIndex ] == 0 )
2026 {
2027 // End of one of the strings
2028 break;
2029 }
2030
2031 // Characters do not match
2032 if ( banList[ banListIndex ]->IP[ characterIndex ] == '*' )
2033 {
2034 banListMutex.Unlock();
2035
2036 // Domain is banned.
2037 return true;
2038 }
2039
2040 // Characters do not match and it is not a *
2041 break;
2042 }
2043 }
2044
2045 banListIndex++;
2046 }
2047 }
2048
2049 banListMutex.Unlock();
2050
2051 // No match found.
2052 return false;
2053 }
2054
2055 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2056 // Description:
2057 // Send a ping to the specified connected system.
2058 //
2059 // Parameters:
2060 // target - who to ping
2061 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2062 void RakPeer::Ping( const SystemAddress target )
2063 {
2064 PingInternal(target, false, UNRELIABLE);
2065 }
2066
2067 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2068 // Description:
2069 // Send a ping to the specified unconnected system.
2070 // The remote system, if it is Initialized, will respond with ID_UNCONNECTED_PONG.
2071 // The final ping time will be encoded in the following sizeof(SLNet::TimeMS) bytes. (Default is 4 bytes - See __GET_TIME_64BIT in types.h
2072 //
2073 // Parameters:
2074 // host: Either a dotted IP address or a domain name. Can be 255.255.255.255 for LAN broadcast.
2075 // remotePort: Which port to connect to on the remote machine.
2076 // onlyReplyOnAcceptingConnections: Only request a reply if the remote system has open connections
2077 // connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on.
2078 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2079 bool RakPeer::Ping( const char* host, unsigned short remotePort, bool onlyReplyOnAcceptingConnections, unsigned connectionSocketIndex )
2080 {
2081 if ( host == 0 )
2082 return false;
2083
2084 // If this assert hits then Startup wasn't called or the call failed.
2085 RakAssert(connectionSocketIndex < socketList.Size());
2086
2087 // if ( IsActive() == false )
2088 // return;
2089
2090 SLNet::BitStream bitStream( sizeof(unsigned char) + sizeof(SLNet::Time) );
2091 if ( onlyReplyOnAcceptingConnections )
2092 bitStream.Write((MessageID)ID_UNCONNECTED_PING_OPEN_CONNECTIONS);
2093 else
2094 bitStream.Write((MessageID)ID_UNCONNECTED_PING);
2095
2096 bitStream.Write(SLNet::GetTime());
2097
2098 bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
2099
2100 bitStream.Write(GetMyGUID());
2101
2102 // No timestamp for 255.255.255.255
2103 unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
2104 /*
2105
2106 SystemAddress systemAddress;
2107 systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
2108 systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
2109
2110 unsigned i;
2111 for (i=0; i < pluginListNTS.Size(); i++)
2112 pluginListNTS[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
2113 SocketLayer::SendTo( socketList[realIndex], (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
2114 */
2115
2116 RNS2_SendParameters bsp;
2117 bsp.data = (char*) bitStream.GetData() ;
2118 bsp.length = bitStream.GetNumberOfBytesUsed();
2119 bsp.systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
2120 if (bsp.systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
2121 return false;
2122 bsp.systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
2123 unsigned i;
2124 for (i=0; i < pluginListNTS.Size(); i++)
2125 pluginListNTS[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), bsp.systemAddress);
2126 socketList[realIndex]->Send(&bsp, _FILE_AND_LINE_);
2127
2128 return true;
2129 }
2130
2131 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2132 // Description:
2133 // Returns the average of all ping times read for a specified target
2134 //
2135 // Parameters:
2136 // target - whose time to read
2137 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2138 int RakPeer::GetAveragePing( const AddressOrGUID systemIdentifier )
2139 {
2140 int sum, quantity;
2141 RemoteSystemStruct *remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2142
2143 if ( remoteSystem == 0 )
2144 return -1;
2145
2146 for ( sum = 0, quantity = 0; quantity < PING_TIMES_ARRAY_SIZE; quantity++ )
2147 {
2148 if ( remoteSystem->pingAndClockDifferential[ quantity ].pingTime == 65535 )
2149 break;
2150 else
2151 sum += remoteSystem->pingAndClockDifferential[ quantity ].pingTime;
2152 }
2153
2154 if ( quantity > 0 )
2155 return sum / quantity;
2156 else
2157 return -1;
2158 }
2159
2160 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2161 // Description:
2162 // Returns the last ping time read for the specific player or -1 if none read yet
2163 //
2164 // Parameters:
2165 // target - whose time to read
2166 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2167 int RakPeer::GetLastPing( const AddressOrGUID systemIdentifier ) const
2168 {
2169 RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2170
2171 if ( remoteSystem == 0 )
2172 return -1;
2173
2174 // return (int)(remoteSystem->reliabilityLayer.GetAckPing()/(SLNet::TimeUS)1000);
2175
2176 if ( remoteSystem->pingAndClockDifferentialWriteIndex == 0 )
2177 return remoteSystem->pingAndClockDifferential[ PING_TIMES_ARRAY_SIZE - 1 ].pingTime;
2178 else
2179 return remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex - 1 ].pingTime;
2180 }
2181
2182 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2183 // Description:
2184 // Returns the lowest ping time read or -1 if none read yet
2185 //
2186 // Parameters:
2187 // target - whose time to read
2188 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2189 int RakPeer::GetLowestPing( const AddressOrGUID systemIdentifier ) const
2190 {
2191 RemoteSystemStruct * remoteSystem = GetRemoteSystem( systemIdentifier, false, false );
2192
2193 if ( remoteSystem == 0 )
2194 return -1;
2195
2196 return remoteSystem->lowestPing;
2197 }
2198
2199 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2200 // Description:
2201 // Ping the remote systems every so often. This is off by default
2202 // This will work anytime
2203 //
2204 // Parameters:
2205 // doPing - True to start occasional pings. False to stop them.
2206 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2207 void RakPeer::SetOccasionalPing( bool doPing )
2208 {
2209 occasionalPing = doPing;
2210 }
2211
2212 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2216 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2217 SLNet::Time RakPeer::GetClockDifferential( const AddressOrGUID systemIdentifier )
2218 {
2219 RemoteSystemStruct *remoteSystem = GetRemoteSystem(systemIdentifier, false, false);
2220 if (remoteSystem == 0)
2221 return 0;
2222 return GetClockDifferentialInt(remoteSystem);
2223 }
2224
2225 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2226
2227 SLNet::Time RakPeer::GetClockDifferentialInt(RemoteSystemStruct *remoteSystem) const
2228 {
2229 int counter, lowestPingSoFar;
2230 SLNet::Time clockDifferential;
2231
2232 lowestPingSoFar = 65535;
2233
2234 clockDifferential = 0;
2235
2236 for ( counter = 0; counter < PING_TIMES_ARRAY_SIZE; counter++ )
2237 {
2238 if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime == 65535 )
2239 break;
2240
2241 if ( remoteSystem->pingAndClockDifferential[ counter ].pingTime < lowestPingSoFar )
2242 {
2243 clockDifferential = remoteSystem->pingAndClockDifferential[ counter ].clockDifferential;
2244 lowestPingSoFar = remoteSystem->pingAndClockDifferential[ counter ].pingTime;
2245 }
2246 }
2247
2248 return clockDifferential;
2249 }
2250 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2251 // Description:
2252 // Length should be under 400 bytes, as a security measure against flood attacks
2253 // Sets the data to send with an (LAN server discovery) /(offline ping) response
2254 // See the Ping sample project for how this is used.
2255 // data: a block of data to store, or 0 for none
2256 // length: The length of data in bytes, or 0 for none
2257 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2258 void RakPeer::SetOfflinePingResponse( const char *data, const unsigned int length )
2259 {
2260 RakAssert(length < 400);
2261
2262 rakPeerMutexes[ offlinePingResponse_Mutex ].Lock();
2263 offlinePingResponse.Reset();
2264
2265 if ( data && length > 0 )
2266 offlinePingResponse.Write( data, length );
2267
2268 rakPeerMutexes[ offlinePingResponse_Mutex ].Unlock();
2269 }
2270
2271 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2272 // Returns pointers to a copy of the data passed to SetOfflinePingResponse
2273 // \param[out] data A pointer to a copy of the data passed to \a SetOfflinePingResponse()
2274 // \param[out] length A pointer filled in with the length parameter passed to SetOfflinePingResponse()
2275 // \sa SetOfflinePingResponse
2276 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2277 void RakPeer::GetOfflinePingResponse( char **data, unsigned int *length )
2278 {
2279 rakPeerMutexes[ offlinePingResponse_Mutex ].Lock();
2280 *data = (char*) offlinePingResponse.GetData();
2281 *length = (int) offlinePingResponse.GetNumberOfBytesUsed();
2282 rakPeerMutexes[ offlinePingResponse_Mutex ].Unlock();
2283 }
2284
2285 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2286 // Description:
2287 // Return the unique SystemAddress that represents you on the the network
2288 // Note that unlike in previous versions, this is a struct and is not sequential
2289 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2290 SystemAddress RakPeer::GetInternalID( const SystemAddress systemAddress, const int index ) const
2291 {
2292 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
2293 {
2294 return ipList[index];
2295 }
2296 else
2297 {
2298
2299 // SystemAddress returnValue;
2300 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, false, true );
2301 if (remoteSystem==0)
2302 return UNASSIGNED_SYSTEM_ADDRESS;
2303
2304 return remoteSystem->theirInternalSystemAddress[index];
2305 /*
2306 sockaddr_in sa;
2307 socklen_t len = sizeof(sa);
2308 if (getsockname__(connectionSockets[remoteSystem->connectionSocketIndex], (sockaddr*)&sa, &len)!=0)
2309 return UNASSIGNED_SYSTEM_ADDRESS;
2310 returnValue.port=ntohs(sa.sin_port);
2311 returnValue.binaryAddress=sa.sin_addr.s_addr;
2312 return returnValue;
2313 */
2314
2315
2316
2317 }
2318 }
2319
2320 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2324 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2325 void RakPeer::SetInternalID(SystemAddress systemAddress, int index)
2326 {
2327 RakAssert(index >=0 && index < MAXIMUM_NUMBER_OF_INTERNAL_IDS);
2328 ipList[index]=systemAddress;
2329 }
2330
2331 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2332 // Description:
2333 // Return the unique address identifier that represents you on the the network and is based on your external
2334 // IP / port (the IP / port the specified player uses to communicate with you)
2335 // Note that unlike in previous versions, this is a struct and is not sequential
2336 //
2337 // Parameters:
2338 // target: Which remote system you are referring to for your external ID
2339 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2340 SystemAddress RakPeer::GetExternalID( const SystemAddress target ) const
2341 {
2342 unsigned i;
2343 SystemAddress inactiveExternalId;
2344
2345 inactiveExternalId=UNASSIGNED_SYSTEM_ADDRESS;
2346
2347 if (target==UNASSIGNED_SYSTEM_ADDRESS)
2348 return firstExternalID;
2349
2350 // First check for active connection with this systemAddress
2351 for ( i = 0; i < maximumNumberOfPeers; i++ )
2352 {
2353 if (remoteSystemList[ i ].systemAddress == target )
2354 {
2355 if ( remoteSystemList[ i ].isActive )
2356 return remoteSystemList[ i ].myExternalSystemAddress;
2357 else if (remoteSystemList[ i ].myExternalSystemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
2358 inactiveExternalId=remoteSystemList[ i ].myExternalSystemAddress;
2359 }
2360 }
2361
2362 return inactiveExternalId;
2363 }
2364
2365 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2366
2367 const RakNetGUID RakPeer::GetMyGUID(void) const
2368 {
2369 return myGuid;
2370 }
2371 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2372 SystemAddress RakPeer::GetMyBoundAddress(const int socketIndex)
2373 {
2374 DataStructures::List<RakNetSocket2* > sockets;
2375 GetSockets( sockets );
2376 if (sockets.Size()>0)
2377 return sockets[socketIndex]->GetBoundAddress();
2378 else
2379 return UNASSIGNED_SYSTEM_ADDRESS;
2380 }
2381 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2382
2383 const RakNetGUID& RakPeer::GetGuidFromSystemAddress( const SystemAddress input ) const
2384 {
2385 if (input==UNASSIGNED_SYSTEM_ADDRESS)
2386 return myGuid;
2387
2388 if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].systemAddress == input)
2389 return remoteSystemList[ input.systemIndex ].guid;
2390
2391 unsigned int i;
2392 for ( i = 0; i < maximumNumberOfPeers; i++ )
2393 {
2394 if (remoteSystemList[ i ].systemAddress == input )
2395 {
2396 // Set the systemIndex so future lookups will be fast
2397 remoteSystemList[i].guid.systemIndex = (SystemIndex) i;
2398
2399 return remoteSystemList[ i ].guid;
2400 }
2401 }
2402
2403 return UNASSIGNED_RAKNET_GUID;
2404 }
2405
2406 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2407
2408 unsigned int RakPeer::GetSystemIndexFromGuid( const RakNetGUID input ) const
2409 {
2410 if (input==UNASSIGNED_RAKNET_GUID)
2411 return (unsigned int) -1;
2412
2413 if (input==myGuid)
2414 return (unsigned int) -1;
2415
2416 if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
2417 return input.systemIndex;
2418
2419 unsigned int i;
2420 for ( i = 0; i < maximumNumberOfPeers; i++ )
2421 {
2422 if (remoteSystemList[ i ].guid == input )
2423 {
2424 // Set the systemIndex so future lookups will be fast
2425 remoteSystemList[i].guid.systemIndex = (SystemIndex) i;
2426
2427 return i;
2428 }
2429 }
2430
2431 return (unsigned int) -1;
2432 }
2433
2434 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2435
2436 SystemAddress RakPeer::GetSystemAddressFromGuid( const RakNetGUID input ) const
2437 {
2438 if (input==UNASSIGNED_RAKNET_GUID)
2439 return UNASSIGNED_SYSTEM_ADDRESS;
2440
2441 if (input==myGuid)
2442 return GetInternalID(UNASSIGNED_SYSTEM_ADDRESS);
2443
2444 if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].guid == input)
2445 return remoteSystemList[ input.systemIndex ].systemAddress;
2446
2447 unsigned int i;
2448 for ( i = 0; i < maximumNumberOfPeers; i++ )
2449 {
2450 if (remoteSystemList[ i ].guid == input )
2451 {
2452 // Set the systemIndex so future lookups will be fast
2453 remoteSystemList[i].guid.systemIndex = (SystemIndex) i;
2454
2455 return remoteSystemList[ i ].systemAddress;
2456 }
2457 }
2458
2459 return UNASSIGNED_SYSTEM_ADDRESS;
2460 }
2461
2462 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2463
2464 bool RakPeer::GetClientPublicKeyFromSystemAddress( const SystemAddress input, char *client_public_key ) const
2465 {
2466 #if LIBCAT_SECURITY == 1
2467 if (input == UNASSIGNED_SYSTEM_ADDRESS)
2468 return false;
2469
2470 char *copy_source = 0;
2471
2472 if (input.systemIndex!=(SystemIndex)-1 && input.systemIndex<maximumNumberOfPeers && remoteSystemList[ input.systemIndex ].systemAddress == input)
2473 {
2474 copy_source = remoteSystemList[ input.systemIndex ].client_public_key;
2475 }
2476 else
2477 {
2478 for ( unsigned int i = 0; i < maximumNumberOfPeers; i++ )
2479 {
2480 if (remoteSystemList[ i ].systemAddress == input )
2481 {
2482 copy_source = remoteSystemList[ i ].client_public_key;
2483 break;
2484 }
2485 }
2486 }
2487
2488 if (copy_source)
2489 {
2490 // Verify that at least one byte in the public key is non-zero to indicate that the key was received
2491 for (int ii = 0; ii < cat::EasyHandshake::PUBLIC_KEY_BYTES; ++ii)
2492 {
2493 if (copy_source[ii] != 0)
2494 {
2495 memcpy(client_public_key, copy_source, cat::EasyHandshake::PUBLIC_KEY_BYTES);
2496 return true;
2497 }
2498 }
2499 }
2500
2501 #else
2502 (void) input;
2503 (void) client_public_key;
2504 #endif
2505
2506 return false;
2507 }
2508
2509 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2510 // Set the time, in MS, to use before considering ourselves disconnected after not being able to deliver a reliable packet
2511 // \param[in] time Time, in MS
2512 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2513 void RakPeer::SetTimeoutTime(SLNet::TimeMS timeMS, const SystemAddress target )
2514 {
2515 if (target==UNASSIGNED_SYSTEM_ADDRESS)
2516 {
2517 defaultTimeoutTime=timeMS;
2518
2519 unsigned i;
2520 for ( i = 0; i < maximumNumberOfPeers; i++ )
2521 {
2522 if (remoteSystemList[ i ].isActive)
2523 {
2524 if ( remoteSystemList[ i ].isActive )
2525 remoteSystemList[ i ].reliabilityLayer.SetTimeoutTime(timeMS);
2526 }
2527 }
2528 }
2529 else
2530 {
2531 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
2532
2533 if ( remoteSystem != 0 )
2534 remoteSystem->reliabilityLayer.SetTimeoutTime(timeMS);
2535 }
2536 }
2537
2538 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2539
2540 SLNet::TimeMS RakPeer::GetTimeoutTime( const SystemAddress target )
2541 {
2542 if (target==UNASSIGNED_SYSTEM_ADDRESS)
2543 {
2544 return defaultTimeoutTime;
2545 }
2546 else
2547 {
2548 RemoteSystemStruct * remoteSystem = GetRemoteSystemFromSystemAddress( target, false, true );
2549
2550 if ( remoteSystem != 0 )
2551 return remoteSystem->reliabilityLayer.GetTimeoutTime();
2552 }
2553 return defaultTimeoutTime;
2554 }
2555
2556
2557 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2558 // Description:
2559 // Returns the current MTU size
2560 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2561 int RakPeer::GetMTUSize( const SystemAddress target ) const
2562 {
2563 if (target!=UNASSIGNED_SYSTEM_ADDRESS)
2564 {
2565 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(target, false, true);
2566 if (rss)
2567 return rss->MTUSize;
2568 }
2569 return defaultMTUSize;
2570 }
2571 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2572 // Description:
2573 // Returns the number of IP addresses we have
2574 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2575 unsigned int RakPeer::GetNumberOfAddresses( void )
2576 {
2577 if (IsActive() == false) {
2578 FillIPList();
2579 }
2580
2581 for (int i = 0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS && ipList[i] != UNASSIGNED_SYSTEM_ADDRESS; i++) {
2582 if (ipList[i] == UNASSIGNED_SYSTEM_ADDRESS) {
2583 return i; // first unassigned address entry found -> end of address list reached
2584 }
2585 }
2586
2587 return MAXIMUM_NUMBER_OF_INTERNAL_IDS;
2588 }
2589
2590 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2591 // Returns an IP address at index 0 to GetNumberOfAddresses-1
2592 // \param[in] index index into the list of IP addresses
2593 // \return The local IP address at this index
2594 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2595 const char* RakPeer::GetLocalIP( unsigned int index )
2596 {
2597 if (IsActive()==false)
2598 {
2599 // Fill out ipList structure
2600
2601 FillIPList();
2602
2603 }
2604
2605
2606 static char str[128];
2607 ipList[index].ToString(false,str,static_cast<size_t>(128));
2608 return str;
2609
2610
2611
2612
2613 }
2614
2615 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2616 // Is this a local IP?
2617 // \param[in] An IP address to check
2618 // \return True if this is one of the IP addresses returned by GetLocalIP
2619 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2620 bool RakPeer::IsLocalIP( const char *ip )
2621 {
2622 if (ip==0 || ip[0]==0)
2623 return false;
2624
2625
2626 if (strcmp(ip, "127.0.0.1")==0 || strcmp(ip, "localhost")==0)
2627 return true;
2628
2629 int num = GetNumberOfAddresses();
2630 int i;
2631 for (i=0; i < num; i++)
2632 {
2633 if (strcmp(ip, GetLocalIP(i))==0)
2634 return true;
2635 }
2636
2637
2638
2639
2640 return false;
2641 }
2642
2643 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2644 // Description:
2645 // Allow or disallow connection responses from any IP. Normally this should be false, but may be necessary
2646 // when connection to servers with multiple IP addresses
2647 //
2648 // Parameters:
2649 // allow - True to allow this behavior, false to not allow. Defaults to false. Value persists between connections
2650 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2651 void RakPeer::AllowConnectionResponseIPMigration( bool allow )
2652 {
2653 allowConnectionResponseIPMigration = allow;
2654 }
2655
2656 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2657 // Description:
2658 // Sends a message ID_ADVERTISE_SYSTEM to the remote unconnected system.
2659 // This will tell the remote system our external IP outside the LAN, and can be used for NAT punch through
2660 //
2661 // Requires:
2662 // The sender and recipient must already be started via a successful call to Initialize
2663 //
2664 // host: Either a dotted IP address or a domain name
2665 // remotePort: Which port to connect to on the remote machine.
2666 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2667 bool RakPeer::AdvertiseSystem( const char *host, unsigned short remotePort, const char *data, int dataLength, unsigned connectionSocketIndex )
2668 {
2669 SLNet::BitStream bs;
2670 bs.Write((MessageID)ID_ADVERTISE_SYSTEM);
2671 bs.WriteAlignedBytes((const unsigned char*) data,dataLength);
2672 return SendOutOfBand(host, remotePort, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), connectionSocketIndex );
2673 }
2674
2675 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2676 // Controls how often to return ID_DOWNLOAD_PROGRESS for large message downloads.
2677 // ID_DOWNLOAD_PROGRESS is returned to indicate a new partial message chunk, roughly the MTU size, has arrived
2678 // As it can be slow or cumbersome to get this notification for every chunk, you can set the interval at which it is returned.
2679 // Defaults to 0 (never return this notification)
2680 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2681 void RakPeer::SetSplitMessageProgressInterval(int interval)
2682 {
2683 RakAssert(interval>=0);
2684 splitMessageProgressInterval=interval;
2685 for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
2686 remoteSystemList[ i ].reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval);
2687 }
2688
2689 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2690 // Returns what was passed to SetSplitMessageProgressInterval()
2691 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2692 int RakPeer::GetSplitMessageProgressInterval(void) const
2693 {
2694 return splitMessageProgressInterval;
2695 }
2696
2697 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2698 // Set how long to wait before giving up on sending an unreliable message
2699 // Useful if the network is clogged up.
2700 // Set to 0 or less to never timeout. Defaults to 0.
2701 // timeoutMS How many ms to wait before simply not sending an unreliable message.
2702 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2703 void RakPeer::SetUnreliableTimeout(SLNet::TimeMS timeoutMS)
2704 {
2705 unreliableTimeout=timeoutMS;
2706 for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
2707 remoteSystemList[ i ].reliabilityLayer.SetUnreliableTimeout(unreliableTimeout);
2708 }
2709
2710 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2711 // Send a message to host, with the IP socket option TTL set to 3
2712 // This message will not reach the host, but will open the router.
2713 // Used for NAT-Punchthrough
2714 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2715 void RakPeer::SendTTL( const char* host, unsigned short remotePort, int ttl, unsigned connectionSocketIndex )
2716 {
2717 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
2718 char fakeData[2];
2719 fakeData[0]=0;
2720 fakeData[1]=1;
2721 unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
2722 if (socketList[realIndex]->IsBerkleySocket())
2723 {
2724 RNS2_SendParameters bsp;
2725 bsp.data = (char*) fakeData;
2726 bsp.length = 2;
2727 bsp.systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
2728 bsp.systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
2729 bsp.ttl=ttl;
2730 unsigned i;
2731 for (i=0; i < pluginListNTS.Size(); i++)
2732 pluginListNTS[i]->OnDirectSocketSend((const char*)bsp.data, BYTES_TO_BITS(bsp.length), bsp.systemAddress);
2733 socketList[realIndex]->Send(&bsp, _FILE_AND_LINE_);
2734 }
2735 #endif
2736 }
2737
2738
2739 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2740 // Attatches a Plugin interface to run code automatically on message receipt in the Receive call
2741 //
2742 // \param messageHandler Pointer to a plugin to attach
2743 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2744 void RakPeer::AttachPlugin( PluginInterface2 *plugin )
2745 {
2746 bool isNotThreadsafe = plugin->UsesReliabilityLayer();
2747 if (isNotThreadsafe)
2748 {
2749 if (pluginListNTS.GetIndexOf(plugin)==MAX_UNSIGNED_LONG)
2750 {
2751 plugin->SetRakPeerInterface(this);
2752 plugin->OnAttach();
2753 pluginListNTS.Insert(plugin, _FILE_AND_LINE_);
2754 }
2755 }
2756 else
2757 {
2758 if (pluginListTS.GetIndexOf(plugin)==MAX_UNSIGNED_LONG)
2759 {
2760 plugin->SetRakPeerInterface(this);
2761 plugin->OnAttach();
2762 pluginListTS.Insert(plugin, _FILE_AND_LINE_);
2763 }
2764 }
2765 }
2766
2767 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2768 // Detaches a Plugin interface to run code automatically on message receipt
2769 //
2770 // \param messageHandler Pointer to a plugin to detach
2771 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2772 void RakPeer::DetachPlugin( PluginInterface2 *plugin )
2773 {
2774 if (plugin==0)
2775 return;
2776
2777 unsigned int index;
2778
2779 bool isNotThreadsafe = plugin->UsesReliabilityLayer();
2780 if (isNotThreadsafe)
2781 {
2782 index = pluginListNTS.GetIndexOf(plugin);
2783 if (index!=MAX_UNSIGNED_LONG)
2784 {
2785 // Unordered list so delete from end for speed
2786 pluginListNTS[index]=pluginListNTS[pluginListNTS.Size()-1];
2787 pluginListNTS.RemoveFromEnd();
2788 }
2789 }
2790 else
2791 {
2792 index = pluginListTS.GetIndexOf(plugin);
2793 if (index!=MAX_UNSIGNED_LONG)
2794 {
2795 // Unordered list so delete from end for speed
2796 pluginListTS[index]=pluginListTS[pluginListTS.Size()-1];
2797 pluginListTS.RemoveFromEnd();
2798 }
2799 }
2800 plugin->OnDetach();
2801 plugin->SetRakPeerInterface(0);
2802 }
2803
2804 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2805 // Put a packet back at the end of the receive queue in case you don't want to deal with it immediately
2806 //
2807 // packet The packet you want to push back.
2808 // 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)
2809 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2810 void RakPeer::PushBackPacket( Packet *packet, bool pushAtHead)
2811 {
2812 if (packet==0)
2813 return;
2814
2815 unsigned i;
2816 for (i=0; i < pluginListTS.Size(); i++)
2817 pluginListTS[i]->OnPushBackPacket((const char*) packet->data, packet->bitSize, packet->systemAddress);
2818 for (i=0; i < pluginListNTS.Size(); i++)
2819 pluginListNTS[i]->OnPushBackPacket((const char*) packet->data, packet->bitSize, packet->systemAddress);
2820
2821 packetReturnMutex.Lock();
2822 if (pushAtHead)
2823 packetReturnQueue.PushAtHead(packet,0,_FILE_AND_LINE_);
2824 else
2825 packetReturnQueue.Push(packet,_FILE_AND_LINE_);
2826 packetReturnMutex.Unlock();
2827 }
2828
2829 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2830 void RakPeer::ChangeSystemAddress(RakNetGUID guid, const SystemAddress &systemAddress)
2831 {
2832 BufferedCommandStruct *bcs;
2833
2834 bcs=bufferedCommands.Allocate( _FILE_AND_LINE_ );
2835 bcs->data = 0;
2836 bcs->systemIdentifier.systemAddress=systemAddress;
2837 bcs->systemIdentifier.rakNetGuid=guid;
2838 bcs->command=BufferedCommandStruct::BCS_CHANGE_SYSTEM_ADDRESS;
2839 bufferedCommands.Push(bcs);
2840 }
2841 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2842 Packet* RakPeer::AllocatePacket(unsigned dataSize)
2843 {
2844 return AllocPacket(dataSize, _FILE_AND_LINE_);
2845 }
2846 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2847 RakNetSocket2* RakPeer::GetSocket( const SystemAddress target )
2848 {
2849 // Send a query to the thread to get the socket, and return when we got it
2850 BufferedCommandStruct *bcs;
2851 bcs=bufferedCommands.Allocate( _FILE_AND_LINE_ );
2852 bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
2853 bcs->systemIdentifier=target;
2854 bcs->data=0;
2855 bufferedCommands.Push(bcs);
2856
2857 // Block up to one second to get the socket, although it should actually take virtually no time
2858 SocketQueryOutput *sqo;
2859 SLNet::TimeMS stopWaiting = SLNet::GetTimeMS()+1000;
2860 DataStructures::List<RakNetSocket2* > output;
2861 while (SLNet::GetTimeMS() < stopWaiting)
2862 {
2863 if (isMainLoopThreadActive==false)
2864 return 0;
2865
2866 RakSleep(0);
2867
2868 sqo = socketQueryOutput.Pop();
2869 if (sqo)
2870 {
2871 output=sqo->sockets;
2872 sqo->sockets.Clear(false, _FILE_AND_LINE_);
2873 socketQueryOutput.Deallocate(sqo, _FILE_AND_LINE_);
2874 if (output.Size())
2875 return output[0];
2876 break;
2877 }
2878 }
2879 return 0;
2880 }
2881 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2882 void RakPeer::GetSockets( DataStructures::List<RakNetSocket2* > &sockets )
2883 {
2884 sockets.Clear(false, _FILE_AND_LINE_);
2885
2886 // Send a query to the thread to get the socket, and return when we got it
2887 BufferedCommandStruct *bcs;
2888
2889 bcs=bufferedCommands.Allocate( _FILE_AND_LINE_ );
2890 bcs->command=BufferedCommandStruct::BCS_GET_SOCKET;
2891 bcs->systemIdentifier=UNASSIGNED_SYSTEM_ADDRESS;
2892 bcs->data=0;
2893 bufferedCommands.Push(bcs);
2894
2895 // Block up to one second to get the socket, although it should actually take virtually no time
2896 SocketQueryOutput *sqo;
2897 // RakNetSocket2* output;
2898 for(;;)
2899 {
2900 if (isMainLoopThreadActive==false)
2901 return;
2902
2903 RakSleep(0);
2904
2905 sqo = socketQueryOutput.Pop();
2906 if (sqo)
2907 {
2908 sockets=sqo->sockets;
2909 sqo->sockets.Clear(false, _FILE_AND_LINE_);
2910 socketQueryOutput.Deallocate(sqo, _FILE_AND_LINE_);
2911 return;
2912 }
2913 }
2914 return;
2915 }
2916 void RakPeer::ReleaseSockets( DataStructures::List<RakNetSocket2* > &sockets )
2917 {
2918 sockets.Clear(false,_FILE_AND_LINE_);
2919 }
2920 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2921
2922 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2923 // Adds simulated ping and packet loss to the outgoing data flow.
2924 // 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.
2925 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2926 void RakPeer::ApplyNetworkSimulator( float packetloss, unsigned short minExtraPing, unsigned short extraPingVariance)
2927 {
2928 #ifdef _DEBUG
2929 if (remoteSystemList)
2930 {
2931 unsigned short i;
2932 for (i=0; i < maximumNumberOfPeers; i++)
2933 //for (i=0; i < remoteSystemListSize; i++)
2934 remoteSystemList[i].reliabilityLayer.ApplyNetworkSimulator(packetloss, minExtraPing, extraPingVariance);
2935 }
2936
2937 _packetloss=packetloss;
2938 _minExtraPing=minExtraPing;
2939 _extraPingVariance=extraPingVariance;
2940 #endif
2941 }
2942
2943 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2944
2945 void RakPeer::SetPerConnectionOutgoingBandwidthLimit( unsigned maxBitsPerSecond )
2946 {
2947 maxOutgoingBPS=maxBitsPerSecond;
2948 }
2949
2950 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2951 // Returns if you previously called ApplyNetworkSimulator
2952 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2953 bool RakPeer::IsNetworkSimulatorActive( void )
2954 {
2955 #ifdef _DEBUG
2956 return _packetloss>0 || _minExtraPing>0 || _extraPingVariance>0;
2957 #else
2958 return false;
2959 #endif
2960 }
2961
2962 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2963 void RakPeer::WriteOutOfBandHeader(SLNet::BitStream *bitStream)
2964 {
2965 bitStream->Write((MessageID)ID_OUT_OF_BAND_INTERNAL);
2966 bitStream->Write(myGuid);
2967 bitStream->WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
2968 }
2969 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2970 void RakPeer::SetUserUpdateThread(void (*_userUpdateThreadPtr)(RakPeerInterface *, void *), void *_userUpdateThreadData)
2971 {
2972 userUpdateThreadPtr=_userUpdateThreadPtr;
2973 userUpdateThreadData=_userUpdateThreadData;
2974 }
2975 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2976 void RakPeer::SetIncomingDatagramEventHandler( bool (*_incomingDatagramEventHandler)(RNS2RecvStruct *) )
2977 {
2978 incomingDatagramEventHandler=_incomingDatagramEventHandler;
2979 }
2980 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2981 bool RakPeer::SendOutOfBand(const char *host, unsigned short remotePort, const char *data, BitSize_t dataLength, unsigned connectionSocketIndex )
2982 {
2983 if ( IsActive() == false )
2984 return false;
2985
2986 if (host==0 || host[0]==0)
2987 return false;
2988
2989 // If this assert hits then Startup wasn't called or the call failed.
2990 RakAssert(connectionSocketIndex < socketList.Size());
2991
2992 // This is a security measure. Don't send data longer than this value
2993 RakAssert(dataLength <= (MAX_OFFLINE_DATA_LENGTH + sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID)));
2994
2995 if (host==0)
2996 return false;
2997
2998 // 34 bytes
2999 SLNet::BitStream bitStream;
3000 WriteOutOfBandHeader(&bitStream);
3001
3002 if (dataLength>0)
3003 {
3004 bitStream.Write(data, dataLength);
3005 }
3006
3007 unsigned int realIndex = GetRakNetSocketFromUserConnectionSocketIndex(connectionSocketIndex);
3008
3009 /*
3010 SystemAddress systemAddress;
3011 systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
3012 systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
3013
3014 unsigned i;
3015 for (i=0; i < pluginListNTS.Size(); i++)
3016 pluginListNTS[i]->OnDirectSocketSend((const char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), systemAddress);
3017
3018 SocketLayer::SendTo( socketList[realIndex], (const char*)bitStream.GetData(), (int) bitStream.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
3019 */
3020
3021 RNS2_SendParameters bsp;
3022 bsp.data = (char*) bitStream.GetData();
3023 bsp.length = bitStream.GetNumberOfBytesUsed();
3024 bsp.systemAddress.FromStringExplicitPort(host,remotePort, socketList[realIndex]->GetBoundAddress().GetIPVersion());
3025 bsp.systemAddress.FixForIPVersion(socketList[realIndex]->GetBoundAddress());
3026 unsigned i;
3027 for (i=0; i < pluginListNTS.Size(); i++)
3028 pluginListNTS[i]->OnDirectSocketSend((const char*)bsp.data, BYTES_TO_BITS(bsp.length), bsp.systemAddress);
3029 socketList[realIndex]->Send(&bsp, _FILE_AND_LINE_);
3030
3031 return true;
3032 }
3033
3034 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3035 RakNetStatistics * RakPeer::GetStatistics( const SystemAddress systemAddress, RakNetStatistics *rns )
3036 {
3037 static RakNetStatistics staticStatistics;
3038 RakNetStatistics *systemStats;
3039 if (rns==0)
3040 systemStats=&staticStatistics;
3041 else
3042 systemStats=rns;
3043
3044 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
3045 {
3046 bool firstWrite=false;
3047 // Return a crude sum
3048 for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ )
3049 {
3050 if (remoteSystemList[ i ].isActive)
3051 {
3052 RakNetStatistics rnsTemp;
3053 remoteSystemList[ i ].reliabilityLayer.GetStatistics(&rnsTemp);
3054
3055 if (firstWrite==false)
3056 {
3057 memcpy(systemStats, &rnsTemp, sizeof(RakNetStatistics));
3058 firstWrite=true;
3059 }
3060 else
3061 (*systemStats)+=rnsTemp;
3062 }
3063 }
3064 return systemStats;
3065 }
3066 else
3067 {
3068 RemoteSystemStruct * rss;
3069 rss = GetRemoteSystemFromSystemAddress( systemAddress, false, false );
3070 if ( rss && endThreads==false )
3071 {
3072 rss->reliabilityLayer.GetStatistics(systemStats);
3073 return systemStats;
3074 }
3075 }
3076
3077 return 0;
3078 }
3079 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3080 void RakPeer::GetStatisticsList(DataStructures::List<SystemAddress> &addresses, DataStructures::List<RakNetGUID> &guids, DataStructures::List<RakNetStatistics> &statistics)
3081 {
3082 addresses.Clear(false, _FILE_AND_LINE_);
3083 guids.Clear(false, _FILE_AND_LINE_);
3084 statistics.Clear(false, _FILE_AND_LINE_);
3085
3086 if ( remoteSystemList == 0 || endThreads == true )
3087 return;
3088
3089 unsigned int i;
3090 for (i=0; i < activeSystemListSize; i++)
3091 {
3092 if ((activeSystemList[i])->isActive &&
3093 (activeSystemList[i])->connectMode==RakPeer::RemoteSystemStruct::CONNECTED)
3094 {
3095 addresses.Push((activeSystemList[i])->systemAddress, _FILE_AND_LINE_ );
3096 guids.Push((activeSystemList[i])->guid, _FILE_AND_LINE_ );
3097 RakNetStatistics rns;
3098 (activeSystemList[i])->reliabilityLayer.GetStatistics(&rns);
3099 statistics.Push(rns, _FILE_AND_LINE_);
3100 }
3101 }
3102 }
3103 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3104 bool RakPeer::GetStatistics( const unsigned int index, RakNetStatistics *rns )
3105 {
3106 if (index < maximumNumberOfPeers && remoteSystemList[ index ].isActive)
3107 {
3108 remoteSystemList[ index ].reliabilityLayer.GetStatistics(rns);
3109 return true;
3110 }
3111 return false;
3112 }
3113 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3114 unsigned int RakPeer::GetReceiveBufferSize(void)
3115 {
3116 unsigned int size;
3117 packetReturnMutex.Lock();
3118 size=packetReturnQueue.Size();
3119 packetReturnMutex.Unlock();
3120 return size;
3121 }
3122 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3123 int RakPeer::GetIndexFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread ) const
3124 {
3125 unsigned i;
3126
3127 if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
3128 return -1;
3129
3130 if (systemAddress.systemIndex!=(SystemIndex)-1 && systemAddress.systemIndex < maximumNumberOfPeers && remoteSystemList[systemAddress.systemIndex].systemAddress==systemAddress && remoteSystemList[ systemAddress.systemIndex ].isActive)
3131 return systemAddress.systemIndex;
3132
3133 if (calledFromNetworkThread)
3134 {
3135 return GetRemoteSystemIndex(systemAddress);
3136 }
3137 else
3138 {
3139 // remoteSystemList in user and network thread
3140 for ( i = 0; i < maximumNumberOfPeers; i++ )
3141 if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].systemAddress == systemAddress )
3142 return i;
3143
3144 // If no active results found, try previously active results.
3145 for ( i = 0; i < maximumNumberOfPeers; i++ )
3146 if ( remoteSystemList[ i ].systemAddress == systemAddress )
3147 return i;
3148 }
3149
3150 return -1;
3151 }
3152 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3153 int RakPeer::GetIndexFromGuid( const RakNetGUID guid )
3154 {
3155 unsigned i;
3156
3157 if ( guid == UNASSIGNED_RAKNET_GUID )
3158 return -1;
3159
3160 if (guid.systemIndex!=(SystemIndex)-1 && guid.systemIndex < maximumNumberOfPeers && remoteSystemList[guid.systemIndex].guid==guid && remoteSystemList[ guid.systemIndex ].isActive)
3161 return guid.systemIndex;
3162
3163 // remoteSystemList in user and network thread
3164 for ( i = 0; i < maximumNumberOfPeers; i++ )
3165 if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].guid == guid )
3166 return i;
3167
3168 // If no active results found, try previously active results.
3169 for ( i = 0; i < maximumNumberOfPeers; i++ )
3170 if ( remoteSystemList[ i ].guid == guid )
3171 return i;
3172
3173 return -1;
3174 }
3175 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3176 #if LIBCAT_SECURITY==1
3177 bool RakPeer::GenerateConnectionRequestChallenge(RequestedConnectionStruct *rcs,PublicKey *publicKey)
3178 {
3179 CAT_AUDIT_PRINTF("AUDIT: In GenerateConnectionRequestChallenge()\n");
3180
3181 rcs->client_handshake = 0;
3182 rcs->publicKeyMode = PKM_INSECURE_CONNECTION;
3183
3184 if (!publicKey) return true;
3185
3186 switch (publicKey->publicKeyMode)
3187 {
3188 default:
3189 case PKM_INSECURE_CONNECTION:
3190 break;
3191
3192 case PKM_ACCEPT_ANY_PUBLIC_KEY:
3193 CAT_OBJCLR(rcs->remote_public_key);
3194 rcs->client_handshake = SLNet::OP_NEW<cat::ClientEasyHandshake>(_FILE_AND_LINE_);
3195
3196 rcs->publicKeyMode = PKM_ACCEPT_ANY_PUBLIC_KEY;
3197 break;
3198
3199 case PKM_USE_TWO_WAY_AUTHENTICATION:
3200 if (publicKey->myPublicKey == 0 || publicKey->myPrivateKey == 0 ||
3201 publicKey->remoteServerPublicKey == 0)
3202 {
3203 return false;
3204 }
3205
3206 rcs->client_handshake = SLNet::OP_NEW<cat::ClientEasyHandshake>(_FILE_AND_LINE_);
3207 memcpy(rcs->remote_public_key, publicKey->remoteServerPublicKey, cat::EasyHandshake::PUBLIC_KEY_BYTES);
3208
3209 if (!rcs->client_handshake->Initialize(publicKey->remoteServerPublicKey) ||
3210 !rcs->client_handshake->SetIdentity(publicKey->myPublicKey, publicKey->myPrivateKey) ||
3211 !rcs->client_handshake->GenerateChallenge(rcs->handshakeChallenge))
3212 {
3213 CAT_AUDIT_PRINTF("AUDIT: Failure initializing new client_handshake object with identity for this RequestedConnectionStruct\n");
3214 SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3215 rcs->client_handshake=0;
3216 return false;
3217 }
3218
3219 CAT_AUDIT_PRINTF("AUDIT: Success initializing new client handshake object with identity for this RequestedConnectionStruct -- pre-generated challenge\n");
3220
3221 rcs->publicKeyMode = PKM_USE_TWO_WAY_AUTHENTICATION;
3222 break;
3223
3224 case PKM_USE_KNOWN_PUBLIC_KEY:
3225 if (publicKey->remoteServerPublicKey == 0)
3226 return false;
3227
3228 rcs->client_handshake = SLNet::OP_NEW<cat::ClientEasyHandshake>(_FILE_AND_LINE_);
3229 memcpy(rcs->remote_public_key, publicKey->remoteServerPublicKey, cat::EasyHandshake::PUBLIC_KEY_BYTES);
3230
3231 if (!rcs->client_handshake->Initialize(publicKey->remoteServerPublicKey) ||
3232 !rcs->client_handshake->GenerateChallenge(rcs->handshakeChallenge))
3233 {
3234 CAT_AUDIT_PRINTF("AUDIT: Failure initializing new client_handshake object for this RequestedConnectionStruct\n");
3235 SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3236 rcs->client_handshake=0;
3237 return false;
3238 }
3239
3240 CAT_AUDIT_PRINTF("AUDIT: Success initializing new client handshake object for this RequestedConnectionStruct -- pre-generated challenge\n");
3241
3242 rcs->publicKeyMode = PKM_USE_KNOWN_PUBLIC_KEY;
3243 break;
3244 }
3245
3246 return true;
3247 }
3248 #endif
3249 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3250 ConnectionAttemptResult RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, PublicKey *publicKey, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime )
3251 {
3252 RakAssert(passwordDataLength <= 256);
3253 RakAssert(remotePort!=0);
3254 SystemAddress systemAddress;
3255 if (!systemAddress.FromStringExplicitPort(host,remotePort,socketList[connectionSocketIndex]->GetBoundAddress().GetIPVersion()))
3256 return CANNOT_RESOLVE_DOMAIN_NAME;
3257
3258 // Already connected?
3259 if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
3260 return ALREADY_CONNECTED_TO_ENDPOINT;
3261
3262 //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), _FILE_AND_LINE_);
3263 RequestedConnectionStruct *rcs = SLNet::OP_NEW<RequestedConnectionStruct>(_FILE_AND_LINE_);
3264
3265 rcs->systemAddress=systemAddress;
3266 rcs->nextRequestTime= SLNet::GetTimeMS();
3267 rcs->requestsMade=0;
3268 rcs->data=0;
3269 rcs->socket=0;
3270 rcs->extraData=extraData;
3271 rcs->socketIndex=connectionSocketIndex;
3272 rcs->actionToTake=RequestedConnectionStruct::CONNECT;
3273 rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
3274 rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
3275 memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
3276 rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
3277 rcs->timeoutTime=timeoutTime;
3278
3279 #if LIBCAT_SECURITY==1
3280 CAT_AUDIT_PRINTF("AUDIT: In SendConnectionRequest()\n");
3281 if (!GenerateConnectionRequestChallenge(rcs,publicKey))
3282 return SECURITY_INITIALIZATION_FAILED;
3283 #else
3284 (void) publicKey;
3285 #endif
3286
3287 // Return false if already pending, else push on queue
3288 unsigned int i=0;
3289 requestedConnectionQueueMutex.Lock();
3290 for (; i < requestedConnectionQueue.Size(); i++)
3291 {
3292 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
3293 {
3294 requestedConnectionQueueMutex.Unlock();
3295 // Not necessary
3296 //SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3297 SLNet::OP_DELETE(rcs,_FILE_AND_LINE_);
3298 return CONNECTION_ATTEMPT_ALREADY_IN_PROGRESS;
3299 }
3300 }
3301 requestedConnectionQueue.Push(rcs, _FILE_AND_LINE_ );
3302 requestedConnectionQueueMutex.Unlock();
3303
3304 return CONNECTION_ATTEMPT_STARTED;
3305 }
3306 ConnectionAttemptResult RakPeer::SendConnectionRequest( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, PublicKey *publicKey, unsigned connectionSocketIndex, unsigned int extraData, unsigned sendConnectionAttemptCount, unsigned timeBetweenSendConnectionAttemptsMS, SLNet::TimeMS timeoutTime, RakNetSocket2* socket )
3307 {
3308 RakAssert(passwordDataLength <= 256);
3309 SystemAddress systemAddress;
3310 systemAddress.FromStringExplicitPort(host,remotePort);
3311
3312 // Already connected?
3313 if (GetRemoteSystemFromSystemAddress(systemAddress, false, true))
3314 return ALREADY_CONNECTED_TO_ENDPOINT;
3315
3316 //RequestedConnectionStruct *rcs = (RequestedConnectionStruct *) rakMalloc_Ex(sizeof(RequestedConnectionStruct), _FILE_AND_LINE_);
3317 RequestedConnectionStruct *rcs = SLNet::OP_NEW<RequestedConnectionStruct>(_FILE_AND_LINE_);
3318
3319 rcs->systemAddress=systemAddress;
3320 rcs->nextRequestTime= SLNet::GetTimeMS();
3321 rcs->requestsMade=0;
3322 rcs->data=0;
3323 rcs->socket=0;
3324 rcs->extraData=extraData;
3325 rcs->socketIndex=connectionSocketIndex;
3326 rcs->actionToTake=RequestedConnectionStruct::CONNECT;
3327 rcs->sendConnectionAttemptCount=sendConnectionAttemptCount;
3328 rcs->timeBetweenSendConnectionAttemptsMS=timeBetweenSendConnectionAttemptsMS;
3329 memcpy(rcs->outgoingPassword, passwordData, passwordDataLength);
3330 rcs->outgoingPasswordLength=(unsigned char) passwordDataLength;
3331 rcs->timeoutTime=timeoutTime;
3332 rcs->socket=socket;
3333
3334 #if LIBCAT_SECURITY==1
3335 if (!GenerateConnectionRequestChallenge(rcs,publicKey))
3336 return SECURITY_INITIALIZATION_FAILED;
3337 #else
3338 (void) publicKey;
3339 #endif
3340
3341 // Return false if already pending, else push on queue
3342 unsigned int i=0;
3343 requestedConnectionQueueMutex.Lock();
3344 for (; i < requestedConnectionQueue.Size(); i++)
3345 {
3346 if (requestedConnectionQueue[i]->systemAddress==systemAddress)
3347 {
3348 requestedConnectionQueueMutex.Unlock();
3349 // Not necessary
3350 //SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
3351 SLNet::OP_DELETE(rcs,_FILE_AND_LINE_);
3352 return CONNECTION_ATTEMPT_ALREADY_IN_PROGRESS;
3353 }
3354 }
3355 requestedConnectionQueue.Push(rcs, _FILE_AND_LINE_ );
3356 requestedConnectionQueueMutex.Unlock();
3357
3358 return CONNECTION_ATTEMPT_STARTED;
3359 }
3360 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3361 void RakPeer::ValidateRemoteSystemLookup(void) const
3362 {
3363 }
3364 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3365 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystem( const AddressOrGUID systemIdentifier, bool calledFromNetworkThread, bool onlyActive ) const
3366 {
3367 if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
3368 return GetRemoteSystemFromGUID(systemIdentifier.rakNetGuid, onlyActive);
3369 else
3370 return GetRemoteSystemFromSystemAddress(systemIdentifier.systemAddress, calledFromNetworkThread, onlyActive);
3371 }
3372 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3373 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromSystemAddress( const SystemAddress systemAddress, bool calledFromNetworkThread, bool onlyActive ) const
3374 {
3375 unsigned i;
3376
3377 if ( systemAddress == UNASSIGNED_SYSTEM_ADDRESS )
3378 return 0;
3379
3380 if (calledFromNetworkThread)
3381 {
3382 unsigned int index = GetRemoteSystemIndex(systemAddress);
3383 if (index!=(unsigned int) -1)
3384 {
3385 if (onlyActive==false || remoteSystemList[ index ].isActive==true )
3386 {
3387 RakAssert(remoteSystemList[index].systemAddress==systemAddress);
3388 return remoteSystemList + index;
3389 }
3390 }
3391 }
3392 else
3393 {
3394 int deadConnectionIndex=-1;
3395
3396 // Active connections take priority. But if there are no active connections, return the first systemAddress match found
3397 for ( i = 0; i < maximumNumberOfPeers; i++ )
3398 {
3399 if (remoteSystemList[ i ].systemAddress == systemAddress)
3400 {
3401 if ( remoteSystemList[ i ].isActive )
3402 return remoteSystemList + i;
3403 else if (deadConnectionIndex==-1)
3404 deadConnectionIndex=i;
3405 }
3406 }
3407
3408 if (deadConnectionIndex!=-1 && onlyActive==false)
3409 return remoteSystemList + deadConnectionIndex;
3410 }
3411
3412 return 0;
3413 }
3414 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3415 RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromGUID( const RakNetGUID guid, bool onlyActive ) const
3416 {
3417 if (guid==UNASSIGNED_RAKNET_GUID)
3418 return 0;
3419
3420 unsigned i;
3421 for ( i = 0; i < maximumNumberOfPeers; i++ )
3422 {
3423 if (remoteSystemList[ i ].guid == guid && (onlyActive==false || remoteSystemList[ i ].isActive))
3424 {
3425 return remoteSystemList + i;
3426 }
3427 }
3428 return 0;
3429 }
3430 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3431 void RakPeer::ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, const SystemAddress &systemAddress, const char *data, int byteSize )
3432 {
3433 SLNet::BitStream bs((unsigned char*) data,byteSize,false);
3434 bs.IgnoreBytes(sizeof(MessageID));
3435 RakNetGUID guid;
3436 bs.Read(guid);
3437 SLNet::Time incomingTimestamp;
3438 bs.Read(incomingTimestamp);
3439 unsigned char doSecurity;
3440 bs.Read(doSecurity);
3441
3442 #if LIBCAT_SECURITY==1
3443 unsigned char doClientKey;
3444 if (_using_security)
3445 {
3446 // Ignore message on bad state
3447 if (doSecurity != 1 || !remoteSystem->reliabilityLayer.GetAuthenticatedEncryption())
3448 return;
3449
3450 // Validate client proof of key
3451 unsigned char proof[cat::EasyHandshake::PROOF_BYTES];
3452 bs.ReadAlignedBytes(proof, sizeof(proof));
3453 if (!remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()->ValidateProof(proof, sizeof(proof)))
3454 {
3455 remoteSystem->connectMode = RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
3456 return;
3457 }
3458
3459 CAT_OBJCLR(remoteSystem->client_public_key);
3460
3461 bs.Read(doClientKey);
3462
3463 // Check if client wants to prove identity
3464 if (doClientKey == 1)
3465 {
3466 // Read identity proof
3467 unsigned char ident[cat::EasyHandshake::IDENTITY_BYTES];
3468 bs.ReadAlignedBytes(ident, sizeof(ident));
3469
3470 // If we are listening to these proofs,
3471 if (_require_client_public_key)
3472 {
3473 // Validate client identity
3474 if (!_server_handshake->VerifyInitiatorIdentity(remoteSystem->answer, ident, remoteSystem->client_public_key))
3475 {
3476 SLNet::BitStream bitStream;
3477 bitStream.Write((MessageID)ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY); // Report an error since the client is not providing an identity when it is necessary to connect
3478 bitStream.Write((unsigned char)2); // Indicate client identity is invalid
3479 SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3480 remoteSystem->connectMode = RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
3481 return;
3482 }
3483 }
3484
3485 // Otherwise ignore the client public key
3486 }
3487 else
3488 {
3489 // If no client key was provided but it is required,
3490 if (_require_client_public_key)
3491 {
3492 SLNet::BitStream bitStream;
3493 bitStream.Write((MessageID)ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY); // Report an error since the client is not providing an identity when it is necessary to connect
3494 bitStream.Write((unsigned char)1); // Indicate client identity is missing
3495 SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3496 remoteSystem->connectMode = RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
3497 return;
3498 }
3499 }
3500 }
3501 #endif // LIBCAT_SECURITY
3502
3503 unsigned char *password = bs.GetData()+BITS_TO_BYTES(bs.GetReadOffset());
3504 int passwordLength = byteSize - BITS_TO_BYTES(bs.GetReadOffset());
3505 if ( incomingPasswordLength != passwordLength ||
3506 memcmp( password, incomingPassword, incomingPasswordLength ) != 0 )
3507 {
3508 CAT_AUDIT_PRINTF("AUDIT: Invalid password\n");
3509 // This one we only send once since we don't care if it arrives.
3510 SLNet::BitStream bitStream;
3511 bitStream.Write((MessageID)ID_INVALID_PASSWORD);
3512 bitStream.Write(GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
3513 SendImmediate((char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3514 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
3515 return;
3516 }
3517
3518 // OK
3519 remoteSystem->connectMode=RemoteSystemStruct::HANDLING_CONNECTION_REQUEST;
3520
3521 OnConnectionRequest( remoteSystem, incomingTimestamp );
3522 }
3523 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3524 void RakPeer::OnConnectionRequest( RakPeer::RemoteSystemStruct *remoteSystem, SLNet::Time incomingTimestamp )
3525 {
3526 SLNet::BitStream bitStream;
3527 bitStream.Write((MessageID)ID_CONNECTION_REQUEST_ACCEPTED);
3528 bitStream.Write(remoteSystem->systemAddress);
3529 SystemIndex systemIndex = (SystemIndex) GetIndexFromSystemAddress( remoteSystem->systemAddress, true );
3530 RakAssert(systemIndex!=65535);
3531 bitStream.Write(systemIndex);
3532 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
3533 bitStream.Write(ipList[i]);
3534 bitStream.Write(incomingTimestamp);
3535 bitStream.Write(SLNet::GetTime());
3536
3537 SendImmediate((char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, remoteSystem->systemAddress, false, false, SLNet::GetTimeUS(), 0);
3538 }
3539
3540 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3541 void RakPeer::NotifyAndFlagForShutdown( const SystemAddress systemAddress, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
3542 {
3543 SLNet::BitStream temp( sizeof(unsigned char) );
3544 temp.Write( (MessageID)ID_DISCONNECTION_NOTIFICATION );
3545 if (performImmediate)
3546 {
3547 SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, false, SLNet::GetTimeUS(), 0);
3548 RemoteSystemStruct *rss=GetRemoteSystemFromSystemAddress(systemAddress, true, true);
3549 rss->connectMode=RemoteSystemStruct::DISCONNECT_ASAP;
3550 }
3551 else
3552 {
3553 SendBuffered((const char*)temp.GetData(), temp.GetNumberOfBitsUsed(), disconnectionNotificationPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false, RemoteSystemStruct::DISCONNECT_ASAP, 0);
3554 }
3555 }
3556 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3557 unsigned int RakPeer::GetNumberOfRemoteInitiatedConnections( void ) const
3558 {
3559 if ( remoteSystemList == 0 || endThreads == true )
3560 return 0;
3561
3562 unsigned int numberOfIncomingConnections;
3563 numberOfIncomingConnections = 0;
3564 unsigned int i;
3565 for (i=0; i < activeSystemListSize; i++)
3566 {
3567 if ((activeSystemList[i])->isActive &&
3568 (activeSystemList[i])->connectMode==RakPeer::RemoteSystemStruct::CONNECTED &&
3569 (activeSystemList[i])->weInitiatedTheConnection==false
3570 )
3571 {
3572 numberOfIncomingConnections++;
3573 }
3574 }
3575 return numberOfIncomingConnections;
3576 }
3577
3578 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3579 RakPeer::RemoteSystemStruct * RakPeer::AssignSystemAddressToRemoteSystemList( const SystemAddress systemAddress, RemoteSystemStruct::ConnectMode connectionMode, RakNetSocket2* incomingRakNetSocket, bool *thisIPConnectedRecently, SystemAddress bindingAddress, int incomingMTU, RakNetGUID guid, bool useSecurity )
3580 {
3581 RemoteSystemStruct * remoteSystem;
3582 unsigned i,j,assignedIndex;
3583 SLNet::TimeMS time = SLNet::GetTimeMS();
3584 #ifdef _DEBUG
3585 RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
3586 #endif
3587
3588 if (limitConnectionFrequencyFromTheSameIP)
3589 {
3590 if (IsLoopbackAddress(systemAddress,false)==false)
3591 {
3592 for ( i = 0; i < maximumNumberOfPeers; i++ )
3593 {
3594 if ( remoteSystemList[ i ].isActive==true &&
3595 remoteSystemList[ i ].systemAddress.EqualsExcludingPort(systemAddress) &&
3596 time >= remoteSystemList[ i ].connectionTime &&
3597 time - remoteSystemList[ i ].connectionTime < 100
3598 )
3599 {
3600 // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
3601 // Ignore connection attempts if this IP address connected within the last 100 milliseconds
3602 *thisIPConnectedRecently=true;
3603 ValidateRemoteSystemLookup();
3604 return 0;
3605 }
3606 }
3607 }
3608 }
3609
3610 // Don't use a different port than what we received on
3611 bindingAddress.CopyPort(incomingRakNetSocket->GetBoundAddress());
3612
3613 *thisIPConnectedRecently=false;
3614 for ( assignedIndex = 0; assignedIndex < maximumNumberOfPeers; assignedIndex++ )
3615 {
3616 if ( remoteSystemList[ assignedIndex ].isActive==false )
3617 {
3618 // printf("--- Address %s has become active\n", systemAddress.ToString());
3619
3620 remoteSystem=remoteSystemList+assignedIndex;
3621 ReferenceRemoteSystem(systemAddress, assignedIndex);
3622 remoteSystem->MTUSize=defaultMTUSize;
3623 remoteSystem->guid=guid;
3624 remoteSystem->isActive = true; // This one line causes future incoming packets to go through the reliability layer
3625 // Reserve this reliability layer for ourselves.
3626 if (incomingMTU > remoteSystem->MTUSize)
3627 remoteSystem->MTUSize=incomingMTU;
3628 RakAssert(remoteSystem->MTUSize <= MAXIMUM_MTU_SIZE);
3629 remoteSystem->reliabilityLayer.Reset(true, remoteSystem->MTUSize, useSecurity);
3630 remoteSystem->reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval);
3631 remoteSystem->reliabilityLayer.SetUnreliableTimeout(unreliableTimeout);
3632 remoteSystem->reliabilityLayer.SetTimeoutTime(defaultTimeoutTime);
3633 AddToActiveSystemList(assignedIndex);
3634 if (incomingRakNetSocket->GetBoundAddress()==bindingAddress)
3635 {
3636 remoteSystem->rakNetSocket=incomingRakNetSocket;
3637 }
3638 else
3639 {
3640 char str[256];
3641 bindingAddress.ToString(true,str,static_cast<size_t>(256));
3642 // See if this is an internal IP address.
3643 // If so, force binding on it so we reply on the same IP address as they sent to.
3644 unsigned int ipListIndex, foundIndex=(unsigned int)-1;
3645
3646 for (ipListIndex=0; ipListIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ipListIndex++)
3647 {
3648 if (ipList[ipListIndex]==UNASSIGNED_SYSTEM_ADDRESS)
3649 break;
3650
3651 if (bindingAddress.EqualsExcludingPort(ipList[ipListIndex]))
3652 {
3653 foundIndex=ipListIndex;
3654 break;
3655 }
3656 }
3657
3658 // 06/26/09 Unconfirmed report that Vista firewall blocks the reply if we force a binding
3659 // For now use the incoming socket only
3660 // Originally this code was to force a machine with multiple IP addresses to reply back on the IP
3661 // that the datagram came in on
3662 //if (1 || foundIndex==(unsigned int)-1)
3663 //{
3664 // Must not be an internal LAN address. Just use whatever socket it came in on
3665 remoteSystem->rakNetSocket=incomingRakNetSocket;
3666 //}
3667 //else
3668 //{
3669 /*
3670 // Force binding
3671 unsigned int socketListIndex;
3672 for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
3673 {
3674 if (socketList[socketListIndex]->GetBoundAddress()==bindingAddress)
3675 {
3676 // Force binding with existing socket
3677 remoteSystem->rakNetSocket=socketList[socketListIndex];
3678 break;
3679 }
3680 }
3681
3682 if (socketListIndex==socketList.Size())
3683 {
3684 char ipListFoundIndexStr[128];
3685 ipList[foundIndex].ToString(false,str);
3686
3687 // Force binding with new socket
3688 RakNetSocket* rns(SLNet::OP_NEW<RakNetSocket>(_FILE_AND_LINE_));
3689 if (incomingRakNetSocket->GetRemotePortRakNetWasStartedOn()==0)
3690 rns = SocketLayer::CreateBoundSocket( this, bindingAddress.GetPort(), incomingRakNetSocket->GetBlockingSocket(), ipListFoundIndexStr, 0, incomingRakNetSocket->GetExtraSocketOptions(), incomingRakNetSocket->GetSocketFamily(), incomingRakNetSocket->GetChromeInstance() );
3691 else
3692 rns = SocketLayer::CreateBoundSocket_PS3Lobby( bindingAddress.GetPort(), incomingRakNetSocket->GetBlockingSocket(), ipListFoundIndexStr, incomingRakNetSocket->GetSocketFamily() );
3693
3694
3695 if (rns==0)
3696 {
3697 // Can't bind. Just use whatever socket it came in on
3698 remoteSystem->rakNetSocket=incomingRakNetSocket;
3699 }
3700 else
3701 {
3702 rns->GetBoundAddress()=bindingAddress;
3703 rns->SetUserConnectionSocketIndex((unsigned int)-1);
3704 socketList.Push(rns, _FILE_AND_LINE_ );
3705 remoteSystem->rakNetSocket=rns;
3706
3707
3708 #ifdef _WIN32
3709 int highPriority=THREAD_PRIORITY_ABOVE_NORMAL;
3710 #else
3711 int highPriority=-10;
3712 #endif
3713
3714 highPriority=0;
3715
3716
3717 }
3718 }
3719
3720 */
3721 //}
3722 }
3723
3724 for ( j = 0; j < (unsigned) PING_TIMES_ARRAY_SIZE; j++ )
3725 {
3726 remoteSystem->pingAndClockDifferential[ j ].pingTime = 65535;
3727 remoteSystem->pingAndClockDifferential[ j ].clockDifferential = 0;
3728 }
3729
3730 remoteSystem->connectMode=connectionMode;
3731 remoteSystem->pingAndClockDifferentialWriteIndex = 0;
3732 remoteSystem->lowestPing = 65535;
3733 remoteSystem->nextPingTime = 0; // Ping immediately
3734 remoteSystem->weInitiatedTheConnection = false;
3735 remoteSystem->connectionTime = time;
3736 remoteSystem->myExternalSystemAddress = UNASSIGNED_SYSTEM_ADDRESS;
3737 remoteSystem->lastReliableSend=time;
3738
3739 #ifdef _DEBUG
3740 int indexLoopupCheck=GetIndexFromSystemAddress( systemAddress, true );
3741 if ((int) indexLoopupCheck!=(int) assignedIndex)
3742 {
3743 RakAssert((int) indexLoopupCheck==(int) assignedIndex);
3744 }
3745 #endif
3746
3747 return remoteSystem;
3748 }
3749 }
3750
3751 return 0;
3752 }
3753
3754 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3755 // Adjust the first four bytes (treated as unsigned int) of the pointer
3756 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3757 void RakPeer::ShiftIncomingTimestamp( unsigned char *data, const SystemAddress &systemAddress ) const
3758 {
3759 #ifdef _DEBUG
3760 RakAssert( IsActive() );
3761 RakAssert( data );
3762 #endif
3763
3764 SLNet::BitStream timeBS( data, sizeof(SLNet::Time), false);
3765 SLNet::Time encodedTimestamp;
3766 timeBS.Read(encodedTimestamp);
3767
3768 encodedTimestamp = encodedTimestamp - GetBestClockDifferential( systemAddress );
3769 timeBS.SetWriteOffset(0);
3770 timeBS.Write(encodedTimestamp);
3771 }
3772
3773 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3774 // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
3775 SLNet::Time RakPeer::GetBestClockDifferential( const SystemAddress systemAddress ) const
3776 {
3777 RemoteSystemStruct *remoteSystem = GetRemoteSystemFromSystemAddress( systemAddress, true, true );
3778
3779 if ( remoteSystem == 0 )
3780 return 0;
3781
3782 return GetClockDifferentialInt(remoteSystem);
3783 }
3784 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3785 unsigned int RakPeer::RemoteSystemLookupHashIndex(const SystemAddress &sa) const
3786 {
3787 return SystemAddress::ToInteger(sa) % ((unsigned int) maximumNumberOfPeers * REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE);
3788 }
3789 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3790 void RakPeer::ReferenceRemoteSystem(const SystemAddress &sa, unsigned int remoteSystemListIndex)
3791 {
3792 // #ifdef _DEBUG
3793 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
3794 // {
3795 // if (remoteSystemList[remoteSystemIndex].isActive )
3796 // {
3797 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
3798 // RakAssert(hashIndex==remoteSystemIndex);
3799 // }
3800 // }
3801 // #endif
3802
3803
3804 SystemAddress oldAddress = remoteSystemList[remoteSystemListIndex].systemAddress;
3805 if (oldAddress!=UNASSIGNED_SYSTEM_ADDRESS)
3806 {
3807 // The system might be active if rerouting
3808 // RakAssert(remoteSystemList[remoteSystemListIndex].isActive==false);
3809
3810 // Remove the reference if the reference is pointing to this inactive system
3811 if (GetRemoteSystem(oldAddress)==&remoteSystemList[remoteSystemListIndex])
3812 DereferenceRemoteSystem(oldAddress);
3813 }
3814 DereferenceRemoteSystem(sa);
3815
3816 // #ifdef _DEBUG
3817 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
3818 // {
3819 // if (remoteSystemList[remoteSystemIndex].isActive )
3820 // {
3821 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
3822 // if (hashIndex!=remoteSystemIndex)
3823 // {
3824 // RakAssert(hashIndex==remoteSystemIndex);
3825 // }
3826 // }
3827 // }
3828 // #endif
3829
3830
3831 remoteSystemList[remoteSystemListIndex].systemAddress=sa;
3832
3833 unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
3834 RemoteSystemIndex *rsi;
3835 rsi = remoteSystemIndexPool.Allocate(_FILE_AND_LINE_);
3836 if (remoteSystemLookup[hashIndex]==0)
3837 {
3838 rsi->next=0;
3839 rsi->index=remoteSystemListIndex;
3840 remoteSystemLookup[hashIndex]=rsi;
3841 }
3842 else
3843 {
3844 RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
3845 while (cur->next!=0)
3846 {
3847 cur=cur->next;
3848 }
3849
3850 rsi = remoteSystemIndexPool.Allocate(_FILE_AND_LINE_);
3851 rsi->next=0;
3852 rsi->index=remoteSystemListIndex;
3853 cur->next=rsi;
3854 }
3855
3856 // #ifdef _DEBUG
3857 // for ( int remoteSystemIndex = 0; remoteSystemIndex < maximumNumberOfPeers; ++remoteSystemIndex )
3858 // {
3859 // if (remoteSystemList[remoteSystemIndex].isActive )
3860 // {
3861 // unsigned int hashIndex = GetRemoteSystemIndex(remoteSystemList[remoteSystemIndex].systemAddress);
3862 // RakAssert(hashIndex==remoteSystemIndex);
3863 // }
3864 // }
3865 // #endif
3866
3867
3868 RakAssert(GetRemoteSystemIndex(sa)==remoteSystemListIndex);
3869 }
3870 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3871 void RakPeer::DereferenceRemoteSystem(const SystemAddress &sa)
3872 {
3873 unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
3874 RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
3875 RemoteSystemIndex *last = 0;
3876 while (cur!=0)
3877 {
3878 if (remoteSystemList[cur->index].systemAddress==sa)
3879 {
3880 if (last==0)
3881 {
3882 remoteSystemLookup[hashIndex]=cur->next;
3883 }
3884 else
3885 {
3886 last->next=cur->next;
3887 }
3888 remoteSystemIndexPool.Release(cur,_FILE_AND_LINE_);
3889 break;
3890 }
3891 last=cur;
3892 cur=cur->next;
3893 }
3894 }
3895 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3896 unsigned int RakPeer::GetRemoteSystemIndex(const SystemAddress &sa) const
3897 {
3898 unsigned int hashIndex = RemoteSystemLookupHashIndex(sa);
3899 RemoteSystemIndex *cur = remoteSystemLookup[hashIndex];
3900 while (cur!=0)
3901 {
3902 if (remoteSystemList[cur->index].systemAddress==sa)
3903 return cur->index;
3904 cur=cur->next;
3905 }
3906 return (unsigned int) -1;
3907 }
3908 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3909 RakPeer::RemoteSystemStruct* RakPeer::GetRemoteSystem(const SystemAddress &sa) const
3910 {
3911 unsigned int remoteSystemIndex = GetRemoteSystemIndex(sa);
3912 if (remoteSystemIndex==(unsigned int)-1)
3913 return 0;
3914 return remoteSystemList + remoteSystemIndex;
3915 }
3916 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3917 void RakPeer::ClearRemoteSystemLookup(void)
3918 {
3919 remoteSystemIndexPool.Clear(_FILE_AND_LINE_);
3920 SLNet::OP_DELETE_ARRAY(remoteSystemLookup,_FILE_AND_LINE_);
3921 remoteSystemLookup=0;
3922 }
3923 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3924 void RakPeer::AddToActiveSystemList(unsigned int remoteSystemListIndex)
3925 {
3926 activeSystemList[activeSystemListSize++]=remoteSystemList+remoteSystemListIndex;
3927 }
3928 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3929 void RakPeer::RemoveFromActiveSystemList(const SystemAddress &sa)
3930 {
3931 unsigned int i;
3932 for (i=0; i < activeSystemListSize; i++)
3933 {
3934 RemoteSystemStruct *rss=activeSystemList[i];
3935 if (rss->systemAddress==sa)
3936 {
3937 activeSystemList[i]=activeSystemList[activeSystemListSize-1];
3938 activeSystemListSize--;
3939 return;
3940 }
3941 }
3942 RakAssert("activeSystemList invalid, entry not found in RemoveFromActiveSystemList. Ensure that AddToActiveSystemList and RemoveFromActiveSystemList are called by the same thread." && 0);
3943 }
3944 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3945 /*
3946 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3947 unsigned int RakPeer::LookupIndexUsingHashIndex(const SystemAddress &sa) const
3948 {
3949 unsigned int scanCount=0;
3950 unsigned int index = RemoteSystemLookupHashIndex(sa);
3951 if (remoteSystemLookup[index].index==(unsigned int)-1)
3952 return (unsigned int) -1;
3953 while (remoteSystemList[remoteSystemLookup[index].index].systemAddress!=sa)
3954 {
3955 if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
3956 index=0;
3957 if (++scanCount>(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
3958 return (unsigned int) -1;
3959 if (remoteSystemLookup[index].index==-1)
3960 return (unsigned int) -1;
3961 }
3962 return index;
3963 }
3964 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3965 unsigned int RakPeer::RemoteSystemListIndexUsingHashIndex(const SystemAddress &sa) const
3966 {
3967 unsigned int index = LookupIndexUsingHashIndex(sa);
3968 if (index!=(unsigned int) -1)
3969 {
3970 return remoteSystemLookup[index].index;
3971 }
3972 return (unsigned int) -1;
3973 }
3974 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3975 unsigned int RakPeer::FirstFreeRemoteSystemLookupIndex(const SystemAddress &sa) const
3976 {
3977 // unsigned int collisionCount=0;
3978 unsigned int index = RemoteSystemLookupHashIndex(sa);
3979 while (remoteSystemLookup[index].index!=(unsigned int)-1)
3980 {
3981 if (++index==(unsigned int) maximumNumberOfPeers*REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE)
3982 index=0;
3983 // collisionCount++;
3984 }
3985 // printf("%i collisions. Using index %i\n", collisionCount, index);
3986 return index;
3987 }
3988 */
3989 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3990 bool RakPeer::IsLoopbackAddress(const AddressOrGUID &systemIdentifier, bool matchPort) const
3991 {
3992 if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
3993 return systemIdentifier.rakNetGuid==myGuid;
3994
3995 for (int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS && ipList[i]!=UNASSIGNED_SYSTEM_ADDRESS; i++)
3996 {
3997 if (matchPort)
3998 {
3999 if (ipList[i]==systemIdentifier.systemAddress)
4000 return true;
4001 }
4002 else
4003 {
4004 if (ipList[i].EqualsExcludingPort(systemIdentifier.systemAddress))
4005 return true;
4006 }
4007 }
4008
4009 return (matchPort==true && systemIdentifier.systemAddress==firstExternalID) ||
4010 (matchPort==false && systemIdentifier.systemAddress.EqualsExcludingPort(firstExternalID));
4011 }
4012 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4013 SystemAddress RakPeer::GetLoopbackAddress(void) const
4014 {
4015
4016 return ipList[0];
4017
4018
4019
4020 }
4021 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4022 bool RakPeer::AllowIncomingConnections(void) const
4023 {
4024 return GetNumberOfRemoteInitiatedConnections() < GetMaximumIncomingConnections();
4025 }
4026 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4027 void RakPeer::DeallocRNS2RecvStruct(RNS2RecvStruct *s, const char *file, unsigned int line)
4028 {
4029 bufferedPacketsFreePoolMutex.Lock();
4030 bufferedPacketsFreePool.Push(s, file, line);
4031 bufferedPacketsFreePoolMutex.Unlock();
4032 }
4033 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4034 RNS2RecvStruct *RakPeer::AllocRNS2RecvStruct(const char *file, unsigned int line)
4035 {
4036 bufferedPacketsFreePoolMutex.Lock();
4037 if (bufferedPacketsFreePool.Size()>0)
4038 {
4039 RNS2RecvStruct *s = bufferedPacketsFreePool.Pop();
4040 bufferedPacketsFreePoolMutex.Unlock();
4041 return s;
4042 }
4043 else
4044 {
4045 bufferedPacketsFreePoolMutex.Unlock();
4046 return SLNet::OP_NEW<RNS2RecvStruct>(file,line);
4047 }
4048 }
4049 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4050 void RakPeer::ClearBufferedPackets(void)
4051 {
4052 bufferedPacketsFreePoolMutex.Lock();
4053 while (bufferedPacketsFreePool.Size()>0)
4054 SLNet::OP_DELETE(bufferedPacketsFreePool.Pop(), _FILE_AND_LINE_);
4055 bufferedPacketsFreePoolMutex.Unlock();
4056
4057 bufferedPacketsQueueMutex.Lock();
4058 while (bufferedPacketsQueue.Size()>0)
4059 SLNet::OP_DELETE(bufferedPacketsQueue.Pop(), _FILE_AND_LINE_);
4060 bufferedPacketsQueueMutex.Unlock();
4061 }
4062 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4063 void RakPeer::SetupBufferedPackets(void)
4064 {
4065 }
4066 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4067 void RakPeer::PushBufferedPacket(RNS2RecvStruct * p)
4068 {
4069 bufferedPacketsQueueMutex.Lock();
4070 bufferedPacketsQueue.Push(p, _FILE_AND_LINE_);
4071 bufferedPacketsQueueMutex.Unlock();
4072 }
4073 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4074 RNS2RecvStruct *RakPeer::PopBufferedPacket(void)
4075 {
4076 bufferedPacketsQueueMutex.Lock();
4077 if (bufferedPacketsQueue.Size()>0)
4078 {
4079 RNS2RecvStruct *s = bufferedPacketsQueue.Pop();
4080 bufferedPacketsQueueMutex.Unlock();
4081 return s;
4082 }
4083 bufferedPacketsQueueMutex.Unlock();
4084 return 0;
4085 }
4086 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4087 void RakPeer::PingInternal( const SystemAddress target, bool performImmediate, PacketReliability reliability )
4088 {
4089 if ( IsActive() == false )
4090 return ;
4091
4092 SLNet::BitStream bitStream(sizeof(unsigned char)+sizeof(SLNet::Time));
4093 bitStream.Write((MessageID)ID_CONNECTED_PING);
4094 bitStream.Write(SLNet::GetTime());
4095 if (performImmediate)
4096 SendImmediate( (char*)bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, reliability, 0, target, false, false, SLNet::GetTimeUS(), 0 );
4097 else
4098 Send( &bitStream, IMMEDIATE_PRIORITY, reliability, 0, target, false );
4099 }
4100 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4101 void RakPeer::CloseConnectionInternal( const AddressOrGUID& systemIdentifier, bool sendDisconnectionNotification, bool performImmediate, unsigned char orderingChannel, PacketPriority disconnectionNotificationPriority )
4102 {
4103 #ifdef _DEBUG
4104 RakAssert(orderingChannel < 32);
4105 #endif
4106
4107 if (systemIdentifier.IsUndefined())
4108 return;
4109
4110 if ( remoteSystemList == 0 || endThreads == true )
4111 return;
4112
4113 SystemAddress target;
4114 if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
4115 {
4116 target=systemIdentifier.systemAddress;
4117 }
4118 else
4119 {
4120 target=GetSystemAddressFromGuid(systemIdentifier.rakNetGuid);
4121 }
4122
4123 if (target!=UNASSIGNED_SYSTEM_ADDRESS && performImmediate)
4124 target.FixForIPVersion(socketList[0]->GetBoundAddress());
4125
4126 if (sendDisconnectionNotification)
4127 {
4128 NotifyAndFlagForShutdown(target, performImmediate, orderingChannel, disconnectionNotificationPriority);
4129 }
4130 else
4131 {
4132 if (performImmediate)
4133 {
4134 unsigned int index = GetRemoteSystemIndex(target);
4135 if (index!=(unsigned int) -1)
4136 {
4137 if ( remoteSystemList[index].isActive )
4138 {
4139 RemoveFromActiveSystemList(target);
4140
4141 // Found the index to stop
4142 // printf("--- Address %s has become inactive\n", remoteSystemList[index].systemAddress.ToString());
4143 remoteSystemList[index].isActive = false;
4144
4145 remoteSystemList[index].guid=UNASSIGNED_RAKNET_GUID;
4146
4147 // Reserve this reliability layer for ourselves
4148 //remoteSystemList[ remoteSystemLookup[index].index ].systemAddress = UNASSIGNED_SYSTEM_ADDRESS;
4149
4150 // Clear any remaining messages
4151 RakAssert(remoteSystemList[index].MTUSize <= MAXIMUM_MTU_SIZE);
4152 remoteSystemList[index].reliabilityLayer.Reset(false, remoteSystemList[index].MTUSize, false);
4153
4154 // Not using this socket
4155 remoteSystemList[index].rakNetSocket = 0;
4156 }
4157 }
4158 }
4159 else
4160 {
4161 BufferedCommandStruct *bcs;
4162 bcs=bufferedCommands.Allocate( _FILE_AND_LINE_ );
4163 bcs->command=BufferedCommandStruct::BCS_CLOSE_CONNECTION;
4164 bcs->systemIdentifier=target;
4165 bcs->data=0;
4166 bcs->orderingChannel=orderingChannel;
4167 bcs->priority=disconnectionNotificationPriority;
4168 bufferedCommands.Push(bcs);
4169 }
4170 }
4171 }
4172 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4173 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 )
4174 {
4175 BufferedCommandStruct *bcs;
4176
4177 bcs=bufferedCommands.Allocate( _FILE_AND_LINE_ );
4178 bcs->data = (char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES(numberOfBitsToSend), _FILE_AND_LINE_ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
4179 if (bcs->data==0)
4180 {
4181 notifyOutOfMemory(_FILE_AND_LINE_);
4182 bufferedCommands.Deallocate(bcs, _FILE_AND_LINE_);
4183 return;
4184 }
4185
4186 RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
4187 RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
4188 RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
4189
4190 memcpy(bcs->data, data, (size_t) BITS_TO_BYTES(numberOfBitsToSend));
4191 bcs->numberOfBitsToSend=numberOfBitsToSend;
4192 bcs->priority=priority;
4193 bcs->reliability=reliability;
4194 bcs->orderingChannel=orderingChannel;
4195 bcs->systemIdentifier=systemIdentifier;
4196 bcs->broadcast=broadcast;
4197 bcs->connectionMode=connectionMode;
4198 bcs->receipt=receipt;
4199 bcs->command=BufferedCommandStruct::BCS_SEND;
4200 bufferedCommands.Push(bcs);
4201
4202 if (priority==IMMEDIATE_PRIORITY)
4203 {
4204 // Forces pending sends to go out now, rather than waiting to the next update interval
4205 quitAndDataEvents.SetEvent();
4206 }
4207 }
4208 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4209 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 )
4210 {
4211 BufferedCommandStruct *bcs;
4212 unsigned int totalLength=0;
4213 unsigned int lengthOffset;
4214 int i;
4215 for (i=0; i < numParameters; i++)
4216 {
4217 if (lengths[i]>0)
4218 totalLength+=lengths[i];
4219 }
4220 if (totalLength==0)
4221 return;
4222
4223 char *dataAggregate;
4224 dataAggregate = (char*) rakMalloc_Ex( (size_t) totalLength, _FILE_AND_LINE_ ); // Making a copy doesn't lose efficiency because I tell the reliability layer to use this allocation for its own copy
4225 if (dataAggregate==0)
4226 {
4227 notifyOutOfMemory(_FILE_AND_LINE_);
4228 return;
4229 }
4230 for (i=0, lengthOffset=0; i < numParameters; i++)
4231 {
4232 if (lengths[i]>0)
4233 {
4234 memcpy(dataAggregate+lengthOffset, data[i], lengths[i]);
4235 lengthOffset+=lengths[i];
4236 }
4237 }
4238
4239 if (broadcast==false && IsLoopbackAddress(systemIdentifier,true))
4240 {
4241 SendLoopback(dataAggregate,totalLength);
4242 rakFree_Ex(dataAggregate,_FILE_AND_LINE_);
4243 return;
4244 }
4245
4246 RakAssert( !( reliability >= NUMBER_OF_RELIABILITIES || reliability < 0 ) );
4247 RakAssert( !( priority > NUMBER_OF_PRIORITIES || priority < 0 ) );
4248 RakAssert( !( orderingChannel >= NUMBER_OF_ORDERED_STREAMS ) );
4249
4250 bcs=bufferedCommands.Allocate( _FILE_AND_LINE_ );
4251 bcs->data = dataAggregate;
4252 bcs->numberOfBitsToSend=BYTES_TO_BITS(totalLength);
4253 bcs->priority=priority;
4254 bcs->reliability=reliability;
4255 bcs->orderingChannel=orderingChannel;
4256 bcs->systemIdentifier=systemIdentifier;
4257 bcs->broadcast=broadcast;
4258 bcs->connectionMode=connectionMode;
4259 bcs->receipt=receipt;
4260 bcs->command=BufferedCommandStruct::BCS_SEND;
4261 bufferedCommands.Push(bcs);
4262
4263 if (priority==IMMEDIATE_PRIORITY)
4264 {
4265 // Forces pending sends to go out now, rather than waiting to the next update interval
4266 quitAndDataEvents.SetEvent();
4267 }
4268 }
4269 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4270 bool RakPeer::SendImmediate( char *data, BitSize_t numberOfBitsToSend, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, bool useCallerDataAllocation, SLNet::TimeUS currentTime, uint32_t receipt )
4271 {
4272 unsigned *sendList;
4273 unsigned sendListSize;
4274 bool callerDataAllocationUsed;
4275 unsigned int remoteSystemIndex, sendListIndex; // Iterates into the list of remote systems
4276 // unsigned numberOfBytesUsed = (unsigned) BITS_TO_BYTES(numberOfBitsToSend);
4277 callerDataAllocationUsed=false;
4278
4279 sendListSize=0;
4280
4281 if (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
4282 remoteSystemIndex=GetIndexFromSystemAddress( systemIdentifier.systemAddress, true );
4283 else if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
4284 remoteSystemIndex=GetSystemIndexFromGuid(systemIdentifier.rakNetGuid);
4285 else
4286 remoteSystemIndex=(unsigned int) -1;
4287
4288 // 03/06/06 - If broadcast is false, use the optimized version of GetIndexFromSystemAddress
4289 if (broadcast==false)
4290 {
4291 if (remoteSystemIndex==(unsigned int) -1)
4292 {
4293 #ifdef _DEBUG
4294 // int debugIndex = GetRemoteSystemIndex(systemIdentifier.systemAddress);
4295 #endif
4296 return false;
4297 }
4298
4299 #if USE_ALLOCA==1
4300 sendList=(unsigned *)alloca(sizeof(unsigned));
4301 #else
4302 sendList = (unsigned *) rakMalloc_Ex(sizeof(unsigned), _FILE_AND_LINE_);
4303 #endif
4304
4305 if (remoteSystemList[remoteSystemIndex].isActive &&
4306 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP &&
4307 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY &&
4308 remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
4309 {
4310 sendList[0]=remoteSystemIndex;
4311 sendListSize=1;
4312 }
4313 }
4314 else
4315 {
4316 #if USE_ALLOCA==1
4317 sendList=(unsigned *)alloca(sizeof(unsigned)*maximumNumberOfPeers);
4318 #else
4319 sendList = (unsigned *) rakMalloc_Ex(sizeof(unsigned)*maximumNumberOfPeers, _FILE_AND_LINE_);
4320 #endif
4321
4322 // remoteSystemList in network thread
4323 unsigned int idx;
4324 for ( idx = 0; idx < maximumNumberOfPeers; idx++ )
4325 {
4326 if (remoteSystemIndex!=(unsigned int) -1 && idx==remoteSystemIndex)
4327 continue;
4328
4329 if ( remoteSystemList[ idx ].isActive && remoteSystemList[ idx ].systemAddress != UNASSIGNED_SYSTEM_ADDRESS )
4330 sendList[sendListSize++]=idx;
4331 }
4332 }
4333
4334 if (sendListSize==0)
4335 {
4336 #if !defined(USE_ALLOCA)
4337 rakFree_Ex(sendList, _FILE_AND_LINE_ );
4338 #endif
4339
4340 return false;
4341 }
4342
4343 for (sendListIndex=0; sendListIndex < sendListSize; sendListIndex++)
4344 {
4345 // Send may split the packet and thus deallocate data. Don't assume data is valid if we use the callerAllocationData
4346 bool useData = useCallerDataAllocation && callerDataAllocationUsed==false && sendListIndex+1==sendListSize;
4347 remoteSystemList[sendList[sendListIndex]].reliabilityLayer.Send( data, numberOfBitsToSend, priority, reliability, orderingChannel, useData==false, remoteSystemList[sendList[sendListIndex]].MTUSize, currentTime, receipt );
4348 if (useData)
4349 callerDataAllocationUsed=true;
4350
4351 if (reliability==RELIABLE ||
4352 reliability==RELIABLE_ORDERED ||
4353 reliability==RELIABLE_SEQUENCED ||
4354 reliability==RELIABLE_WITH_ACK_RECEIPT ||
4355 reliability==RELIABLE_ORDERED_WITH_ACK_RECEIPT
4356 // ||
4357 // reliability==RELIABLE_SEQUENCED_WITH_ACK_RECEIPT
4358 )
4359 remoteSystemList[sendList[sendListIndex]].lastReliableSend=(SLNet::TimeMS)(currentTime/(SLNet::TimeUS)1000);
4360 }
4361
4362 #if !defined(USE_ALLOCA)
4363 rakFree_Ex(sendList, _FILE_AND_LINE_ );
4364 #endif
4365
4366 // 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
4367 return callerDataAllocationUsed;
4368 }
4369 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4370 void RakPeer::ResetSendReceipt(void)
4371 {
4372 sendReceiptSerialMutex.Lock();
4373 sendReceiptSerial=1;
4374 sendReceiptSerialMutex.Unlock();
4375 }
4376 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4377 void RakPeer::OnConnectedPong(SLNet::Time sendPingTime, SLNet::Time sendPongTime, RemoteSystemStruct *remoteSystem)
4378 {
4379 SLNet::Time ping;
4380 // SLNet::TimeMS lastPing;
4381 SLNet::Time time = SLNet::GetTime(); // Update the time value to be accurate
4382 if (time > sendPingTime)
4383 ping = time - sendPingTime;
4384 else
4385 ping=0;
4386
4387 // lastPing = remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime;
4388
4389 remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime = ( unsigned short ) ping;
4390 // Thanks to Chris Taylor (cat02e@fsu.edu) for the improved timestamping algorithm
4391 // Divide each integer by 2, rather than the sum by 2, to prevent overflow
4392 remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].clockDifferential = sendPongTime - ( time/2 + sendPingTime/2 );
4393
4394 if ( remoteSystem->lowestPing == (unsigned short)-1 || remoteSystem->lowestPing > (int) ping )
4395 remoteSystem->lowestPing = (unsigned short) ping;
4396
4397 if ( ++( remoteSystem->pingAndClockDifferentialWriteIndex ) == (SLNet::Time) PING_TIMES_ARRAY_SIZE )
4398 remoteSystem->pingAndClockDifferentialWriteIndex = 0;
4399 }
4400 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4401 void RakPeer::ClearBufferedCommands(void)
4402 {
4403 BufferedCommandStruct *bcs;
4404
4405 while ((bcs=bufferedCommands.Pop())!=0)
4406 {
4407 if (bcs->data)
4408 rakFree_Ex(bcs->data, _FILE_AND_LINE_ );
4409
4410 bufferedCommands.Deallocate(bcs, _FILE_AND_LINE_);
4411 }
4412 bufferedCommands.Clear(_FILE_AND_LINE_);
4413 }
4414 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4415 void RakPeer::ClearSocketQueryOutput(void)
4416 {
4417 socketQueryOutput.Clear(_FILE_AND_LINE_);
4418 }
4419 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4420 void RakPeer::ClearRequestedConnectionList(void)
4421 {
4422 DataStructures::Queue<RequestedConnectionStruct*> freeQueue;
4423 requestedConnectionQueueMutex.Lock();
4424 while (requestedConnectionQueue.Size())
4425 freeQueue.Push(requestedConnectionQueue.Pop(), _FILE_AND_LINE_ );
4426 requestedConnectionQueueMutex.Unlock();
4427 unsigned i;
4428 for (i=0; i < freeQueue.Size(); i++)
4429 {
4430 #if LIBCAT_SECURITY==1
4431 CAT_AUDIT_PRINTF("AUDIT: In ClearRequestedConnectionList(), Deleting freeQueue index %i client_handshake %x\n", i, freeQueue[i]->client_handshake);
4432 SLNet::OP_DELETE(freeQueue[i]->client_handshake,_FILE_AND_LINE_);
4433 #endif
4434 SLNet::OP_DELETE(freeQueue[i], _FILE_AND_LINE_ );
4435 }
4436 }
4437 inline void RakPeer::AddPacketToProducer(SLNet::Packet *p)
4438 {
4439 packetReturnMutex.Lock();
4440 packetReturnQueue.Push(p,_FILE_AND_LINE_);
4441 packetReturnMutex.Unlock();
4442 }
4443 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4444 union Buff6AndBuff8
4445 {
4446 unsigned char buff6[6];
4447 uint64_t buff8;
4448 };
4449 uint64_t RakPeerInterface::Get64BitUniqueRandomNumber(void)
4450 {
4451 // Mac address is a poor solution because you can't have multiple connections from the same system
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482 #if defined(_WIN32)
4483 uint64_t g= SLNet::GetTimeUS();
4484
4485 SLNet::TimeUS lastTime, thisTime;
4486 int j;
4487 // Sleep a small random time, then use the last 4 bits as a source of randomness
4488 for (j=0; j < 8; j++)
4489 {
4490 lastTime = SLNet::GetTimeUS();
4491 RakSleep(1);
4492 RakSleep(0);
4493 thisTime = SLNet::GetTimeUS();
4494 SLNet::TimeUS diff = thisTime-lastTime;
4495 unsigned int diff4Bits = (unsigned int) (diff & 15);
4496 diff4Bits <<= 32-4;
4497 diff4Bits >>= j*4;
4498 ((char*)&g)[j] ^= diff4Bits;
4499 }
4500 return g;
4501
4502 #else
4503 struct timeval tv;
4504 gettimeofday(&tv, NULL);
4505 return tv.tv_usec + tv.tv_sec * 1000000;
4506 #endif
4507 }
4508 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4509 void RakPeer::GenerateGUID(void)
4510 {
4511 myGuid.g=Get64BitUniqueRandomNumber();
4512
4513 }
4514 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4515 // void SLNet::ProcessPortUnreachable( SystemAddress systemAddress, RakPeer *rakPeer )
4516 // {
4517 // (void) binaryAddress;
4518 // (void) port;
4519 // (void) rakPeer;
4520 //
4521 // }
4522 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4523 namespace SLNet {
4524 bool ProcessOfflineNetworkPacket( SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSocket2* rakNetSocket, bool *isOfflineMessage, SLNet::TimeUS timeRead )
4525 {
4526 (void) timeRead;
4527 RakPeer::RemoteSystemStruct *remoteSystem;
4528 SLNet::Packet *packet;
4529 unsigned i;
4530
4531
4532 char str1[64];
4533 systemAddress.ToString(false, str1,static_cast<size_t>(64));
4534 if (rakPeer->IsBanned( str1 ))
4535 {
4536 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4537 rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4538
4539 SLNet::BitStream bs;
4540 bs.Write((MessageID)ID_CONNECTION_BANNED);
4541 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
4542 bs.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
4543
4544
4545 RNS2_SendParameters bsp;
4546 bsp.data = (char*) bs.GetData();
4547 bsp.length = bs.GetNumberOfBytesUsed();
4548 bsp.systemAddress = systemAddress;
4549 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4550 rakPeer->pluginListNTS[i]->OnDirectSocketSend((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
4551 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
4552
4553 /*
4554 unsigned i;
4555 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4556 rakPeer->pluginListNTS[i]->OnDirectSocketSend((char*) bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
4557 SocketLayer::SendTo( rakNetSocket, (char*) bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
4558 */
4559
4560 return true;
4561 }
4562
4563
4564
4565 // 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,
4566 // and a regular encoding. So I insert OFFLINE_MESSAGE_DATA_ID into the stream, the encoding of which is essentially impossible to hit by chance
4567 if (length <=2)
4568 {
4569 *isOfflineMessage=true;
4570 }
4571 else if (
4572 ((unsigned char)data[0] == ID_UNCONNECTED_PING ||
4573 (unsigned char)data[0] == ID_UNCONNECTED_PING_OPEN_CONNECTIONS) &&
4574 length >= sizeof(unsigned char) + sizeof(SLNet::Time) + sizeof(OFFLINE_MESSAGE_DATA_ID))
4575 {
4576 *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(SLNet::Time), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4577 }
4578 else if ((unsigned char)data[0] == ID_UNCONNECTED_PONG && (size_t) length >= sizeof(unsigned char) + sizeof(SLNet::TimeMS) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
4579 {
4580 *isOfflineMessage=memcmp(data+sizeof(unsigned char) + sizeof(SLNet::Time) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4581 }
4582 else if (
4583 (unsigned char)data[0] == ID_OUT_OF_BAND_INTERNAL &&
4584 (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
4585 {
4586 *isOfflineMessage=memcmp(data+sizeof(MessageID) + RakNetGUID::size(), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4587 }
4588 else if (
4589 (
4590 (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY_1 ||
4591 (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY_2 ||
4592 (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST_1 ||
4593 (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST_2 ||
4594 (unsigned char)data[0] == ID_CONNECTION_ATTEMPT_FAILED ||
4595 (unsigned char)data[0] == ID_NO_FREE_INCOMING_CONNECTIONS ||
4596 (unsigned char)data[0] == ID_CONNECTION_BANNED ||
4597 (unsigned char)data[0] == ID_ALREADY_CONNECTED ||
4598 (unsigned char)data[0] == ID_IP_RECENTLY_CONNECTED) &&
4599 (size_t) length >= sizeof(MessageID) + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID))
4600 {
4601 *isOfflineMessage=memcmp(data+sizeof(MessageID), OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4602 }
4603 else if (((unsigned char)data[0] == ID_INCOMPATIBLE_PROTOCOL_VERSION&&
4604 (size_t) length == sizeof(MessageID)*2 + RakNetGUID::size() + sizeof(OFFLINE_MESSAGE_DATA_ID)))
4605 {
4606 *isOfflineMessage=memcmp(data+sizeof(MessageID)*2, OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID))==0;
4607 }
4608 else
4609 {
4610 *isOfflineMessage=false;
4611 }
4612
4613 if (*isOfflineMessage)
4614 {
4615 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4616 rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4617
4618 // These are all messages from unconnected systems. Messages here can be any size, but are never processed from connected systems.
4619 if ( ( (unsigned char) data[ 0 ] == ID_UNCONNECTED_PING_OPEN_CONNECTIONS
4620 || (unsigned char)(data)[0] == ID_UNCONNECTED_PING) && length >= sizeof(unsigned char)+sizeof(SLNet::Time)+sizeof(OFFLINE_MESSAGE_DATA_ID) )
4621 {
4622 if ( (unsigned char)(data)[0] == ID_UNCONNECTED_PING ||
4623 rakPeer->AllowIncomingConnections() ) // Open connections with players
4624 {
4625 SLNet::BitStream inBitStream( (unsigned char *) data, length, false );
4626 inBitStream.IgnoreBits(8);
4627 SLNet::Time sendPingTime;
4628 inBitStream.Read(sendPingTime);
4629 inBitStream.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
4630 RakNetGUID remoteGuid=UNASSIGNED_RAKNET_GUID;
4631 inBitStream.Read(remoteGuid);
4632
4633 SLNet::BitStream outBitStream;
4634 outBitStream.Write((MessageID)ID_UNCONNECTED_PONG); // Should be named ID_UNCONNECTED_PONG eventually
4635 outBitStream.Write(sendPingTime);
4636 outBitStream.Write(rakPeer->myGuid);
4637 outBitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
4638
4639 rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Lock();
4640 // They are connected, so append offline ping data
4641 outBitStream.Write( (char*)rakPeer->offlinePingResponse.GetData(), rakPeer->offlinePingResponse.GetNumberOfBytesUsed() );
4642 rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Unlock();
4643
4644 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4645 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*)outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), systemAddress);
4646
4647 RNS2_SendParameters bsp;
4648 bsp.data = (char*) outBitStream.GetData();
4649 bsp.length = outBitStream.GetNumberOfBytesUsed();
4650 bsp.systemAddress = systemAddress;
4651 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
4652
4653 // SocketLayer::SendTo( rakNetSocket, (const char*)outBitStream.GetData(), (unsigned int) outBitStream.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
4654
4655 packet=rakPeer->AllocPacket(sizeof(MessageID), _FILE_AND_LINE_);
4656 packet->data[0]=data[0];
4657 packet->systemAddress = systemAddress;
4658 packet->guid=remoteGuid;
4659 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
4660 packet->guid.systemIndex=packet->systemAddress.systemIndex;
4661 rakPeer->AddPacketToProducer(packet);
4662 }
4663 }
4664 // UNCONNECTED MESSAGE Pong with no data.
4665 else if ((unsigned char) data[ 0 ] == ID_UNCONNECTED_PONG && (size_t) length >= sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID) && (size_t) length < sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID)+MAX_OFFLINE_DATA_LENGTH)
4666 {
4667 packet=rakPeer->AllocPacket((unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()-sizeof(SLNet::Time)+sizeof(SLNet::TimeMS)), _FILE_AND_LINE_);
4668 SLNet::BitStream bsIn((unsigned char*) data, length, false);
4669 bsIn.IgnoreBytes(sizeof(unsigned char));
4670 SLNet::Time ping;
4671 bsIn.Read(ping);
4672 bsIn.Read(packet->guid);
4673
4674 SLNet::BitStream bsOut((unsigned char*) packet->data, packet->length, false);
4675 bsOut.ResetWritePointer();
4676 bsOut.Write((unsigned char)ID_UNCONNECTED_PONG);
4677 SLNet::TimeMS pingMS=(SLNet::TimeMS)ping;
4678 bsOut.Write(pingMS);
4679 bsOut.WriteAlignedBytes(
4680 (const unsigned char*)data+sizeof(unsigned char)+sizeof(SLNet::Time)+RakNetGUID::size()+sizeof(OFFLINE_MESSAGE_DATA_ID),
4681 length-sizeof(unsigned char)-sizeof(SLNet::Time)-RakNetGUID::size()-sizeof(OFFLINE_MESSAGE_DATA_ID)
4682 );
4683
4684 packet->systemAddress = systemAddress;
4685 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
4686 packet->guid.systemIndex=packet->systemAddress.systemIndex;
4687 rakPeer->AddPacketToProducer(packet);
4688 }
4689 else if ((unsigned char) data[ 0 ] == ID_OUT_OF_BAND_INTERNAL &&
4690 (size_t) length > sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)+RakNetGUID::size() &&
4691 (size_t) length < MAX_OFFLINE_DATA_LENGTH+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)+RakNetGUID::size())
4692 {
4693 unsigned int dataLength = (unsigned int) (length-sizeof(OFFLINE_MESSAGE_DATA_ID)-RakNetGUID::size()-sizeof(MessageID));
4694 RakAssert(dataLength<1024);
4695 packet=rakPeer->AllocPacket(dataLength+1, _FILE_AND_LINE_);
4696 RakAssert(packet->length<1024);
4697
4698 SLNet::BitStream bs2((unsigned char*) data, length, false);
4699 bs2.IgnoreBytes(sizeof(MessageID));
4700 bs2.Read(packet->guid);
4701
4702 if (data[sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID) + RakNetGUID::size()]==ID_ADVERTISE_SYSTEM)
4703 {
4704 packet->length--;
4705 packet->bitSize=BYTES_TO_BITS(packet->length);
4706 packet->data[0]=ID_ADVERTISE_SYSTEM;
4707 memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID)*2 + RakNetGUID::size(), dataLength-1);
4708 }
4709 else
4710 {
4711 packet->data[0]=ID_OUT_OF_BAND_INTERNAL;
4712 memcpy(packet->data+1, data+sizeof(OFFLINE_MESSAGE_DATA_ID)+sizeof(MessageID) + RakNetGUID::size(), dataLength);
4713 }
4714
4715 packet->systemAddress = systemAddress;
4716 packet->systemAddress.systemIndex = ( SystemIndex ) rakPeer->GetIndexFromSystemAddress( systemAddress, true );
4717 packet->guid.systemIndex=packet->systemAddress.systemIndex;
4718 rakPeer->AddPacketToProducer(packet);
4719 }
4720 else if ((unsigned char)(data)[0] == (MessageID)ID_OPEN_CONNECTION_REPLY_1)
4721 {
4722 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4723 rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4724
4725 SLNet::BitStream bsIn((unsigned char*) data,length,false);
4726 bsIn.IgnoreBytes(sizeof(MessageID));
4727 bsIn.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
4728 RakNetGUID serverGuid;
4729 bsIn.Read(serverGuid);
4730 unsigned char serverHasSecurity;
4731 uint32_t cookie;
4732 (void) cookie;
4733 bsIn.Read(serverHasSecurity);
4734 // Even if the server has security, it may not be required of us if we are in the security exception list
4735 if (serverHasSecurity)
4736 {
4737 bsIn.Read(cookie);
4738 }
4739
4740 SLNet::BitStream bsOut;
4741 bsOut.Write((MessageID)ID_OPEN_CONNECTION_REQUEST_2);
4742 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
4743 if (serverHasSecurity)
4744 bsOut.Write(cookie);
4745
4746 rakPeer->requestedConnectionQueueMutex.Lock();
4747 for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
4748 {
4749 RakPeer::RequestedConnectionStruct *rcs;
4750 rcs=rakPeer->requestedConnectionQueue[i];
4751 if (rcs->systemAddress==systemAddress)
4752 {
4753 if (serverHasSecurity)
4754 {
4755 #if LIBCAT_SECURITY==1
4756 unsigned char public_key[cat::EasyHandshake::PUBLIC_KEY_BYTES];
4757 bsIn.ReadAlignedBytes(public_key, sizeof(public_key));
4758
4759 if (rcs->publicKeyMode==PKM_ACCEPT_ANY_PUBLIC_KEY)
4760 {
4761 memcpy(rcs->remote_public_key, public_key, cat::EasyHandshake::PUBLIC_KEY_BYTES);
4762 if (!rcs->client_handshake->Initialize(public_key) ||
4763 !rcs->client_handshake->GenerateChallenge(rcs->handshakeChallenge))
4764 {
4765 CAT_AUDIT_PRINTF("AUDIT: Server passed a bad public key with PKM_ACCEPT_ANY_PUBLIC_KEY");
4766 rakPeer->requestedConnectionQueueMutex.Unlock();
4767 return true;
4768 }
4769 }
4770
4771 if (cat::SecureEqual(public_key,
4772 rcs->remote_public_key,
4773 cat::EasyHandshake::PUBLIC_KEY_BYTES)==false)
4774 {
4775 rakPeer->requestedConnectionQueueMutex.Unlock();
4776 CAT_AUDIT_PRINTF("AUDIT: Expected public key does not match what was sent by server -- Reporting back ID_PUBLIC_KEY_MISMATCH to user\n");
4777
4778 packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
4779 packet->data[ 0 ] = ID_PUBLIC_KEY_MISMATCH; // Attempted a connection and couldn't
4780 packet->bitSize = ( sizeof( char ) * 8);
4781 packet->systemAddress = rcs->systemAddress;
4782 packet->guid=serverGuid;
4783 rakPeer->AddPacketToProducer(packet);
4784 return true;
4785 }
4786
4787 if (rcs->client_handshake==0)
4788 {
4789 // Message does not contain a challenge
4790 // We might still pass if we are in the security exception list
4791 bsOut.Write((unsigned char)0);
4792 }
4793 else
4794 {
4795 // Message contains a challenge
4796 bsOut.Write((unsigned char)1);
4797 // challenge
4798 CAT_AUDIT_PRINTF("AUDIT: Sending challenge\n");
4799 bsOut.WriteAlignedBytes((const unsigned char*) rcs->handshakeChallenge,cat::EasyHandshake::CHALLENGE_BYTES);
4800 }
4801 #else // LIBCAT_SECURITY
4802 // Message does not contain a challenge
4803 bsOut.Write((unsigned char)0);
4804 #endif // LIBCAT_SECURITY
4805 }
4806 else
4807 {
4808 // Server does not need security
4809 #if LIBCAT_SECURITY==1
4810 if (rcs->client_handshake!=0)
4811 {
4812 rakPeer->requestedConnectionQueueMutex.Unlock();
4813 CAT_AUDIT_PRINTF("AUDIT: Security disabled by server but we expected security (indicated by client_handshake not null) so failing!\n");
4814
4815 packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
4816 packet->data[ 0 ] = ID_OUR_SYSTEM_REQUIRES_SECURITY; // Attempted a connection and couldn't
4817 packet->bitSize = ( sizeof( char ) * 8);
4818 packet->systemAddress = rcs->systemAddress;
4819 packet->guid=serverGuid;
4820 rakPeer->AddPacketToProducer(packet);
4821 return true;
4822 }
4823 #endif // LIBCAT_SECURITY
4824
4825 }
4826
4827 uint16_t mtu;
4828 bsIn.Read(mtu);
4829
4830 // Binding address
4831 bsOut.Write(rcs->systemAddress);
4832 rakPeer->requestedConnectionQueueMutex.Unlock();
4833 // MTU
4834 bsOut.Write(mtu);
4835 // Our guid
4836 bsOut.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
4837
4838 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4839 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), rcs->systemAddress);
4840
4841 // SocketLayer::SendTo( rakPeer->socketList[rcs->socketIndex], (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), rcs->systemAddress, _FILE_AND_LINE_ );
4842
4843 RNS2_SendParameters bsp;
4844 bsp.data = (char*) bsOut.GetData();
4845 bsp.length = bsOut.GetNumberOfBytesUsed();
4846 bsp.systemAddress = systemAddress;
4847 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
4848
4849 return true;
4850 }
4851 }
4852 rakPeer->requestedConnectionQueueMutex.Unlock();
4853 }
4854 else if ((unsigned char)(data)[0] == (MessageID)ID_OPEN_CONNECTION_REPLY_2)
4855 {
4856 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
4857 rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
4858
4859 SLNet::BitStream bs((unsigned char*) data,length,false);
4860 bs.IgnoreBytes(sizeof(MessageID));
4861 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
4862 RakNetGUID guid;
4863 bs.Read(guid);
4864 SystemAddress bindingAddress;
4865 bool b = bs.Read(bindingAddress);
4866 RakAssert(b);
4867 uint16_t mtu;
4868 b=bs.Read(mtu);
4869 RakAssert(b);
4870 bool doSecurity=false;
4871 b=bs.Read(doSecurity);
4872 RakAssert(b);
4873
4874 #if LIBCAT_SECURITY==1
4875 char answer[cat::EasyHandshake::ANSWER_BYTES];
4876 CAT_AUDIT_PRINTF("AUDIT: Got ID_OPEN_CONNECTION_REPLY_2 and given doSecurity=%i\n", (int)doSecurity);
4877 if (doSecurity)
4878 {
4879 CAT_AUDIT_PRINTF("AUDIT: Reading cookie and public key\n");
4880 bs.ReadAlignedBytes((unsigned char*) answer, sizeof(answer));
4881 }
4882 cat::ClientEasyHandshake *client_handshake=0;
4883 #endif // LIBCAT_SECURITY
4884
4885 RakPeer::RequestedConnectionStruct *rcs;
4886 bool unlock=true;
4887 rakPeer->requestedConnectionQueueMutex.Lock();
4888 for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
4889 {
4890 rcs=rakPeer->requestedConnectionQueue[i];
4891
4892
4893 if (rcs->systemAddress==systemAddress)
4894 {
4895 #if LIBCAT_SECURITY==1
4896 CAT_AUDIT_PRINTF("AUDIT: System address matches an entry in the requestedConnectionQueue and doSecurity=%i\n", (int)doSecurity);
4897 if (doSecurity)
4898 {
4899 if (rcs->client_handshake==0)
4900 {
4901 CAT_AUDIT_PRINTF("AUDIT: Server wants security but we didn't set a public key -- Reporting back ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY to user\n");
4902 rakPeer->requestedConnectionQueueMutex.Unlock();
4903
4904 packet=rakPeer->AllocPacket(2, _FILE_AND_LINE_);
4905 packet->data[ 0 ] = ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY; // Attempted a connection and couldn't
4906 packet->data[ 1 ] = 0; // Indicate server public key is missing
4907 packet->bitSize = ( sizeof( char ) * 8);
4908 packet->systemAddress = rcs->systemAddress;
4909 packet->guid=guid;
4910 rakPeer->AddPacketToProducer(packet);
4911 return true;
4912 }
4913
4914 CAT_AUDIT_PRINTF("AUDIT: Looks good, preparing to send challenge to server! client_handshake = %x\n", client_handshake);
4915 }
4916
4917 #endif // LIBCAT_SECURITY
4918
4919 rakPeer->requestedConnectionQueueMutex.Unlock();
4920 unlock=false;
4921
4922 RakAssert(rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT);
4923 // You might get this when already connected because of cross-connections
4924 bool thisIPConnectedRecently=false;
4925 remoteSystem=rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
4926 if (remoteSystem==0)
4927 {
4928 if (rcs->socket == 0)
4929 {
4930 remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, mtu, guid, doSecurity);
4931 }
4932 else
4933 {
4934 remoteSystem=rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rcs->socket, &thisIPConnectedRecently, bindingAddress, mtu, guid, doSecurity);
4935 }
4936 }
4937
4938 // 4/13/09 Attackers can flood ID_OPEN_CONNECTION_REQUEST and use up all available connection slots
4939 // Ignore connection attempts if this IP address connected within the last 100 milliseconds
4940 if (thisIPConnectedRecently==false)
4941 {
4942 // Don't check GetRemoteSystemFromGUID, server will verify
4943 if (remoteSystem)
4944 {
4945 // Move pointer from RequestedConnectionStruct to RemoteSystemStruct
4946 #if LIBCAT_SECURITY==1
4947 cat::u8 ident[cat::EasyHandshake::IDENTITY_BYTES];
4948 bool doIdentity = false;
4949
4950 if (rcs->client_handshake)
4951 {
4952 CAT_AUDIT_PRINTF("AUDIT: Processing answer\n");
4953 if (rcs->publicKeyMode == PKM_USE_TWO_WAY_AUTHENTICATION)
4954 {
4955 if (!rcs->client_handshake->ProcessAnswerWithIdentity(answer, ident, remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()))
4956 {
4957 CAT_AUDIT_PRINTF("AUDIT: Processing answer -- Invalid Answer\n");
4958 return true;
4959 }
4960
4961 doIdentity = true;
4962 }
4963 else
4964 {
4965 if (!rcs->client_handshake->ProcessAnswer(answer, remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()))
4966 {
4967 CAT_AUDIT_PRINTF("AUDIT: Processing answer -- Invalid Answer\n");
4968 return true;
4969 }
4970 }
4971 CAT_AUDIT_PRINTF("AUDIT: Success!\n");
4972
4973 SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
4974 rcs->client_handshake=0;
4975 }
4976 #endif // LIBCAT_SECURITY
4977
4978 remoteSystem->weInitiatedTheConnection=true;
4979 remoteSystem->connectMode=RakPeer::RemoteSystemStruct::REQUESTED_CONNECTION;
4980 if (rcs->timeoutTime!=0)
4981 remoteSystem->reliabilityLayer.SetTimeoutTime(rcs->timeoutTime);
4982
4983 SLNet::BitStream temp;
4984 temp.Write( (MessageID)ID_CONNECTION_REQUEST);
4985 temp.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
4986 temp.Write(SLNet::GetTime());
4987
4988 #if LIBCAT_SECURITY==1
4989 temp.Write((unsigned char)(doSecurity ? 1 : 0));
4990
4991 if (doSecurity)
4992 {
4993 unsigned char proof[32];
4994 remoteSystem->reliabilityLayer.GetAuthenticatedEncryption()->GenerateProof(proof, sizeof(proof));
4995 temp.WriteAlignedBytes(proof, sizeof(proof));
4996
4997 temp.Write((unsigned char)(doIdentity ? 1 : 0));
4998
4999 if (doIdentity)
5000 {
5001 temp.WriteAlignedBytes(ident, sizeof(ident));
5002 }
5003 }
5004 #else
5005 temp.Write((unsigned char)0);
5006 #endif // LIBCAT_SECURITY
5007
5008 if ( rcs->outgoingPasswordLength > 0 )
5009 temp.Write( ( char* ) rcs->outgoingPassword, rcs->outgoingPasswordLength );
5010
5011 rakPeer->SendImmediate((char*)temp.GetData(), temp.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE, 0, systemAddress, false, false, timeRead, 0 );
5012 }
5013 else
5014 {
5015 // Failed, no connections available anymore
5016 packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5017 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
5018 packet->bitSize = ( sizeof( char ) * 8);
5019 packet->systemAddress = rcs->systemAddress;
5020 packet->guid=guid;
5021 rakPeer->AddPacketToProducer(packet);
5022 }
5023 }
5024
5025 rakPeer->requestedConnectionQueueMutex.Lock();
5026 for (unsigned int k=0; k < rakPeer->requestedConnectionQueue.Size(); k++)
5027 {
5028 if (rakPeer->requestedConnectionQueue[k]->systemAddress==systemAddress)
5029 {
5030 rakPeer->requestedConnectionQueue.RemoveAtIndex(k);
5031 break;
5032 }
5033 }
5034 rakPeer->requestedConnectionQueueMutex.Unlock();
5035
5036 #if LIBCAT_SECURITY==1
5037 CAT_AUDIT_PRINTF("AUDIT: Deleting client_handshake object %x and rcs->client_handshake object %x\n", client_handshake, rcs->client_handshake);
5038 SLNet::OP_DELETE(client_handshake,_FILE_AND_LINE_);
5039 SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
5040 #endif // LIBCAT_SECURITY
5041 SLNet::OP_DELETE(rcs,_FILE_AND_LINE_);
5042
5043 break;
5044 }
5045 }
5046
5047 if (unlock)
5048 rakPeer->requestedConnectionQueueMutex.Unlock();
5049
5050 return true;
5051
5052 }
5053 else if ((unsigned char)(data)[0] == (MessageID)ID_CONNECTION_ATTEMPT_FAILED ||
5054 (unsigned char)(data)[0] == (MessageID)ID_NO_FREE_INCOMING_CONNECTIONS ||
5055 (unsigned char)(data)[0] == (MessageID)ID_CONNECTION_BANNED ||
5056 (unsigned char)(data)[0] == (MessageID)ID_ALREADY_CONNECTED ||
5057 (unsigned char)(data)[0] == (MessageID)ID_INVALID_PASSWORD ||
5058 (unsigned char)(data)[0] == (MessageID)ID_IP_RECENTLY_CONNECTED ||
5059 (unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
5060 {
5061
5062 SLNet::BitStream bs((unsigned char*) data,length,false);
5063 bs.IgnoreBytes(sizeof(MessageID));
5064 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
5065 if ((unsigned char)(data)[0] == (MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION)
5066 bs.IgnoreBytes(sizeof(unsigned char));
5067
5068 RakNetGUID guid;
5069 bs.Read(guid);
5070
5071 RakPeer::RequestedConnectionStruct *rcs;
5072 bool connectionAttemptCancelled=false;
5073 rakPeer->requestedConnectionQueueMutex.Lock();
5074 for (i=0; i < rakPeer->requestedConnectionQueue.Size(); i++)
5075 {
5076 rcs=rakPeer->requestedConnectionQueue[i];
5077 if (rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT && rcs->systemAddress==systemAddress)
5078 {
5079 connectionAttemptCancelled=true;
5080 rakPeer->requestedConnectionQueue.RemoveAtIndex(i);
5081
5082 #if LIBCAT_SECURITY==1
5083 CAT_AUDIT_PRINTF("AUDIT: Connection attempt canceled so deleting rcs->client_handshake object %x\n", rcs->client_handshake);
5084 SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
5085 #endif // LIBCAT_SECURITY
5086 SLNet::OP_DELETE(rcs,_FILE_AND_LINE_);
5087 break;
5088 }
5089 }
5090
5091 rakPeer->requestedConnectionQueueMutex.Unlock();
5092
5093 if (connectionAttemptCancelled)
5094 {
5095 // Tell user of connection attempt failed
5096 packet=rakPeer->AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5097 packet->data[ 0 ] = data[0]; // Attempted a connection and couldn't
5098 packet->bitSize = ( sizeof( char ) * 8);
5099 packet->systemAddress = systemAddress;
5100 packet->guid=guid;
5101 rakPeer->AddPacketToProducer(packet);
5102 }
5103 }
5104 else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST_1 && length > (int) (1+sizeof(OFFLINE_MESSAGE_DATA_ID)))
5105 {/*
5106 static int x = 0;
5107 ++x;
5108
5109 SystemAddress *addr = (SystemAddress*)&systemAddress;
5110 addr->binaryAddress += x;*/
5111
5112 //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
5113 char remoteProtocol=data[1+sizeof(OFFLINE_MESSAGE_DATA_ID)];
5114 if (remoteProtocol!=RAKNET_PROTOCOL_VERSION)
5115 {
5116 SLNet::BitStream bs;
5117 bs.Write((MessageID)ID_INCOMPATIBLE_PROTOCOL_VERSION);
5118 bs.Write((unsigned char)RAKNET_PROTOCOL_VERSION);
5119 bs.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5120 bs.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5121
5122 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5123 rakPeer->pluginListNTS[i]->OnDirectSocketSend((char*)bs.GetData(), bs.GetNumberOfBitsUsed(), systemAddress);
5124
5125 // SocketLayer::SendTo( rakNetSocket, (char*)bs.GetData(), bs.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5126
5127 RNS2_SendParameters bsp;
5128 bsp.data = (char*) bs.GetData();
5129 bsp.length = bs.GetNumberOfBytesUsed();
5130 bsp.systemAddress = systemAddress;
5131
5132 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5133 return true;
5134 }
5135
5136 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5137 rakPeer->pluginListNTS[i]->OnDirectSocketReceive(data, length*8, systemAddress);
5138
5139 SLNet::BitStream bsOut;
5140 bsOut.Write((MessageID)ID_OPEN_CONNECTION_REPLY_1);
5141 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5142 bsOut.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5143 #if LIBCAT_SECURITY==1
5144 if (rakPeer->_using_security)
5145 {
5146 bsOut.Write((unsigned char) 1); // HasCookie Yes
5147 // Write cookie
5148 uint32_t cookie = rakPeer->_cookie_jar->Generate(&systemAddress.address,sizeof(systemAddress.address));
5149 CAT_AUDIT_PRINTF("AUDIT: Writing cookie %i to %i:%i\n", cookie, systemAddress);
5150 bsOut.Write(cookie);
5151 // Write my public key
5152 bsOut.WriteAlignedBytes((const unsigned char *) rakPeer->my_public_key,sizeof(rakPeer->my_public_key));
5153 }
5154 else
5155 #endif // LIBCAT_SECURITY
5156 bsOut.Write((unsigned char) 0); // HasCookie oN
5157
5158 // MTU. Lower MTU if it is exceeds our own limit
5159 if (length+UDP_HEADER_SIZE > MAXIMUM_MTU_SIZE)
5160 bsOut.WriteCasted<uint16_t>(MAXIMUM_MTU_SIZE);
5161 else
5162 bsOut.WriteCasted<uint16_t>(length+UDP_HEADER_SIZE);
5163
5164 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5165 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5166 // SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5167
5168 RNS2_SendParameters bsp;
5169 bsp.data = (char*) bsOut.GetData();
5170 bsp.length = bsOut.GetNumberOfBytesUsed();
5171 bsp.systemAddress = systemAddress;
5172 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5173 }
5174 else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST_2)
5175 {
5176 SystemAddress bindingAddress;
5177 RakNetGUID guid;
5178 SLNet::BitStream bsOut;
5179 SLNet::BitStream bs((unsigned char*) data, length, false);
5180 bs.IgnoreBytes(sizeof(MessageID));
5181 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
5182
5183 bool requiresSecurityOfThisClient=false;
5184 #if LIBCAT_SECURITY==1
5185 char remoteHandshakeChallenge[cat::EasyHandshake::CHALLENGE_BYTES];
5186
5187 if (rakPeer->_using_security)
5188 {
5189 systemAddress.ToString(false, str1, static_cast<size_t>(64));
5190 requiresSecurityOfThisClient=rakPeer->IsInSecurityExceptionList(str1)==false;
5191
5192 uint32_t cookie;
5193 bs.Read(cookie);
5194 CAT_AUDIT_PRINTF("AUDIT: Got cookie %i from %i:%i\n", cookie, systemAddress);
5195 if (rakPeer->_cookie_jar->Verify(&systemAddress.address,sizeof(systemAddress.address), cookie)==false)
5196 {
5197 return true;
5198 }
5199 CAT_AUDIT_PRINTF("AUDIT: Cookie good!\n");
5200
5201 unsigned char clientWroteChallenge;
5202 bs.Read(clientWroteChallenge);
5203
5204 if (requiresSecurityOfThisClient==true && clientWroteChallenge==0)
5205 {
5206 // Fail, client doesn't support security, and it is required
5207 return true;
5208 }
5209
5210 if (clientWroteChallenge)
5211 {
5212 bs.ReadAlignedBytes((unsigned char*) remoteHandshakeChallenge, cat::EasyHandshake::CHALLENGE_BYTES);
5213 #ifdef CAT_AUDIT
5214 printf("AUDIT: RECV CHALLENGE ");
5215 for (int ii = 0; ii < sizeof(remoteHandshakeChallenge); ++ii)
5216 {
5217 printf("%02x", (cat::u8)remoteHandshakeChallenge[ii]);
5218 }
5219 printf("\n");
5220 #endif
5221 }
5222 }
5223 #endif // LIBCAT_SECURITY
5224
5225 bs.Read(bindingAddress);
5226 uint16_t mtu;
5227 bs.Read(mtu);
5228 bs.Read(guid);
5229
5230 RakPeer::RemoteSystemStruct *rssFromSA = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
5231 bool IPAddrInUse = rssFromSA != 0 && rssFromSA->isActive;
5232 RakPeer::RemoteSystemStruct *rssFromGuid = rakPeer->GetRemoteSystemFromGUID(guid, true);
5233 bool GUIDInUse = rssFromGuid != 0 && rssFromGuid->isActive;
5234
5235 // IPAddrInUse, GuidInUse, outcome
5236 // TRUE, , TRUE , ID_OPEN_CONNECTION_REPLY if they are the same, else ID_ALREADY_CONNECTED
5237 // FALSE, , TRUE , ID_ALREADY_CONNECTED (someone else took this guid)
5238 // TRUE, , FALSE , ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
5239 // FALSE , FALSE , Allow connection
5240
5241 int outcome;
5242 if (IPAddrInUse & GUIDInUse)
5243 {
5244 if (rssFromSA==rssFromGuid && rssFromSA->connectMode==RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER)
5245 {
5246 // ID_OPEN_CONNECTION_REPLY if they are the same
5247 outcome=1;
5248
5249 // Note to self: If REQUESTED_CONNECTION, this means two systems attempted to connect to each other at the same time, and one finished first.
5250 // Returns ID)_CONNECTION_REQUEST_ACCEPTED to one system, and ID_ALREADY_CONNECTED followed by ID_NEW_INCOMING_CONNECTION to another
5251 }
5252 else
5253 {
5254 // ID_ALREADY_CONNECTED (restarted raknet, connected again from same ip, plus someone else took this guid)
5255 outcome=2;
5256 }
5257 }
5258 else if (IPAddrInUse==false && GUIDInUse==true)
5259 {
5260 // ID_ALREADY_CONNECTED (someone else took this guid)
5261 outcome=3;
5262 }
5263 else if (IPAddrInUse==true && GUIDInUse==false)
5264 {
5265 // ID_ALREADY_CONNECTED (silently disconnected, restarted rakNet)
5266 outcome=4;
5267 }
5268 else
5269 {
5270 // Allow connection
5271 outcome=0;
5272 }
5273
5274 SLNet::BitStream bsAnswer;
5275 bsAnswer.Write((MessageID)ID_OPEN_CONNECTION_REPLY_2);
5276 bsAnswer.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5277 bsAnswer.Write(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
5278 bsAnswer.Write(systemAddress);
5279 bsAnswer.Write(mtu);
5280 bsAnswer.Write(requiresSecurityOfThisClient);
5281
5282 if (outcome==1)
5283 {
5284 // Duplicate connection request packet from packetloss
5285 // Send back the same answer
5286 #if LIBCAT_SECURITY==1
5287 if (requiresSecurityOfThisClient)
5288 {
5289 CAT_AUDIT_PRINTF("AUDIT: Resending public key and answer from packetloss. Sending ID_OPEN_CONNECTION_REPLY_2\n");
5290 bsAnswer.WriteAlignedBytes((const unsigned char *) rssFromSA->answer,sizeof(rssFromSA->answer));
5291 }
5292 #endif // LIBCAT_SECURITY
5293
5294 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5295 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBitsUsed(), systemAddress);
5296 // SocketLayer::SendTo( rakNetSocket, (const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5297
5298 RNS2_SendParameters bsp;
5299 bsp.data = (char*) bsAnswer.GetData();
5300 bsp.length = bsAnswer.GetNumberOfBytesUsed();
5301 bsp.systemAddress = systemAddress;
5302 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5303
5304 return true;
5305 }
5306 else if (outcome!=0)
5307 {
5308 bsOut.Write((MessageID)ID_ALREADY_CONNECTED);
5309 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5310 bsOut.Write(rakPeer->myGuid);
5311 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5312 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5313 // SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5314 RNS2_SendParameters bsp;
5315 bsp.data = (char*) bsOut.GetData();
5316 bsp.length = bsOut.GetNumberOfBytesUsed();
5317 bsp.systemAddress = systemAddress;
5318 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5319
5320 return true;
5321 }
5322
5323 if (rakPeer->AllowIncomingConnections()==false)
5324 {
5325 bsOut.Write((MessageID)ID_NO_FREE_INCOMING_CONNECTIONS);
5326 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5327 bsOut.Write(rakPeer->myGuid);
5328 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5329 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5330 //SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5331 RNS2_SendParameters bsp;
5332 bsp.data = (char*) bsOut.GetData();
5333 bsp.length = bsOut.GetNumberOfBytesUsed();
5334 bsp.systemAddress = systemAddress;
5335 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5336
5337 return true;
5338 }
5339
5340 bool thisIPConnectedRecently=false;
5341 rssFromSA = rakPeer->AssignSystemAddressToRemoteSystemList(systemAddress, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER, rakNetSocket, &thisIPConnectedRecently, bindingAddress, mtu, guid, requiresSecurityOfThisClient);
5342
5343 if (thisIPConnectedRecently==true)
5344 {
5345 bsOut.Write((MessageID)ID_IP_RECENTLY_CONNECTED);
5346 bsOut.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5347 bsOut.Write(rakPeer->myGuid);
5348 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5349 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsOut.GetData(), bsOut.GetNumberOfBitsUsed(), systemAddress);
5350 //SocketLayer::SendTo( rakNetSocket, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5351
5352 RNS2_SendParameters bsp;
5353 bsp.data = (char*) bsOut.GetData();
5354 bsp.length = bsOut.GetNumberOfBytesUsed();
5355 bsp.systemAddress = systemAddress;
5356 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5357
5358 return true;
5359 }
5360
5361 #if LIBCAT_SECURITY==1
5362 if (requiresSecurityOfThisClient)
5363 {
5364 CAT_AUDIT_PRINTF("AUDIT: Writing public key. Sending ID_OPEN_CONNECTION_REPLY_2\n");
5365 if (rakPeer->_server_handshake->ProcessChallenge(remoteHandshakeChallenge, rssFromSA->answer, rssFromSA->reliabilityLayer.GetAuthenticatedEncryption() ))
5366 {
5367 CAT_AUDIT_PRINTF("AUDIT: Challenge good!\n");
5368 // Keep going to OK block
5369 }
5370 else
5371 {
5372 CAT_AUDIT_PRINTF("AUDIT: Challenge BAD!\n");
5373
5374 // Unassign this remote system
5375 rakPeer->DereferenceRemoteSystem(systemAddress);
5376 return true;
5377 }
5378
5379 bsAnswer.WriteAlignedBytes((const unsigned char *) rssFromSA->answer,sizeof(rssFromSA->answer));
5380 }
5381 #endif // LIBCAT_SECURITY
5382
5383 for (i=0; i < rakPeer->pluginListNTS.Size(); i++)
5384 rakPeer->pluginListNTS[i]->OnDirectSocketSend((const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBitsUsed(), systemAddress);
5385 // SocketLayer::SendTo( rakNetSocket, (const char*) bsAnswer.GetData(), bsAnswer.GetNumberOfBytesUsed(), systemAddress, _FILE_AND_LINE_ );
5386 RNS2_SendParameters bsp;
5387 bsp.data = (char*) bsAnswer.GetData();
5388 bsp.length = bsAnswer.GetNumberOfBytesUsed();
5389 bsp.systemAddress = systemAddress;
5390 rakNetSocket->Send(&bsp, _FILE_AND_LINE_);
5391 }
5392 return true;
5393 }
5394
5395 return false;
5396 }
5397 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5398 void ProcessNetworkPacket( SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, SLNet::TimeUS timeRead, BitStream &updateBitStream )
5399 {
5400 ProcessNetworkPacket(systemAddress,data,length,rakPeer,rakPeer->socketList[0],timeRead, updateBitStream);
5401 }
5402 void ProcessNetworkPacket( SystemAddress systemAddress, const char *data, const int length, RakPeer *rakPeer, RakNetSocket2* rakNetSocket, SLNet::TimeUS timeRead, BitStream &updateBitStream )
5403 {
5404 #if LIBCAT_SECURITY==1
5405 #ifdef CAT_AUDIT
5406 printf("AUDIT: RECV ");
5407 for (int ii = 0; ii < length; ++ii)
5408 {
5409 printf("%02x", (cat::u8)data[ii]);
5410 }
5411 printf("\n");
5412 #endif
5413 #endif // LIBCAT_SECURITY
5414
5415 RakAssert(systemAddress.GetPort());
5416 bool isOfflineMessage;
5417 if (ProcessOfflineNetworkPacket(systemAddress, data, length, rakPeer, rakNetSocket, &isOfflineMessage, timeRead))
5418 {
5419 return;
5420 }
5421
5422 // SLNet::Packet *packet;
5423 RakPeer::RemoteSystemStruct *remoteSystem;
5424
5425 // See if this datagram came from a connected system
5426 remoteSystem = rakPeer->GetRemoteSystemFromSystemAddress( systemAddress, true, true );
5427 if ( remoteSystem )
5428 {
5429 // Handle regular incoming data
5430 // HandleSocketReceiveFromConnectedPlayer is only safe to be called from the same thread as Update, which is this thread
5431 if ( isOfflineMessage==false)
5432 {
5433 remoteSystem->reliabilityLayer.HandleSocketReceiveFromConnectedPlayer(
5434 data, length, systemAddress, rakPeer->pluginListNTS, remoteSystem->MTUSize,
5435 rakNetSocket, &rnr, timeRead, updateBitStream);
5436 }
5437 }
5438 else
5439 {
5440 // int a=5;
5441 // printf("--- Packet from unknown system %s\n", systemAddress.ToString());
5442 }
5443 }
5444
5445 }
5446 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5447 unsigned int RakPeer::GenerateSeedFromGuid(void)
5448 {
5449 /*
5450 // Construct a random seed based on the initial guid value, and the last digits of the difference to each subsequent number
5451 // This assumes that only the last 3 bits of each guidId integer has a meaningful amount of randomness between it and the prior number
5452 unsigned int t = guid.g[0];
5453 unsigned int i;
5454 for (i=1; i < sizeof(guid.g) / sizeof(guid.g[0]); i++)
5455 {
5456 unsigned int diff = guid.g[i]-guid.g[i-1];
5457 unsigned int diff3Bits = diff & 0x0007;
5458 diff3Bits <<= 29;
5459 diff3Bits >>= (i-1)*3;
5460 t ^= diff3Bits;
5461 }
5462
5463 return t;
5464 */
5465 return (unsigned int) ((myGuid.g >> 32) ^ myGuid.g);
5466 }
5467 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5468 void RakPeer::DerefAllSockets(void)
5469 {
5470 unsigned int i;
5471 for (i=0; i < socketList.Size(); i++)
5472 {
5473 SLNet::OP_DELETE(socketList[i], _FILE_AND_LINE_);
5474 }
5475 socketList.Clear(false, _FILE_AND_LINE_);
5476 }
5477 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5478 unsigned int RakPeer::GetRakNetSocketFromUserConnectionSocketIndex(unsigned int userIndex) const
5479 {
5480 unsigned int i;
5481 for (i=0; i < socketList.Size(); i++)
5482 {
5483 if (socketList[i]->GetUserConnectionSocketIndex()==userIndex)
5484 return i;
5485 }
5486 RakAssert("GetRakNetSocketFromUserConnectionSocketIndex failed" && 0);
5487 return (unsigned int) -1;
5488 }
5489
5490 /*
5491 // DS_APR
5492 void RakPeer::ProcessChromePacket(RakNetSocket2 *s, const char *buffer, int dataSize, const SystemAddress& recvFromAddress, SLNet::TimeUS timeRead)
5493 {
5494 RakAssert(buffer);
5495 RakAssert(dataSize > 0);
5496 RakAssert(recvFromAddress.GetPort());
5497
5498 RNS2RecvStruct *recvFromStruct;
5499 recvFromStruct=bufferedPackets.Allocate( _FILE_AND_LINE_ );
5500 RakAssert(dataSize <= (int)sizeof(recvFromStruct->data));
5501 memcpy(recvFromStruct->data, buffer, dataSize);
5502 recvFromStruct->bytesRead=dataSize;
5503 recvFromStruct->systemAddress=recvFromAddress;
5504 recvFromStruct->timeRead=timeRead;
5505 bufferedPackets.Push(recvFromStruct);
5506 }
5507 */
5508
5509 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5510 /*
5511 bool RakPeer::RunRecvFromOnce( RakNetSocket *s )
5512 {
5513 RakPeer::RecvFromStruct *recvFromStruct;
5514
5515 recvFromStruct=bufferedPackets.Allocate( _FILE_AND_LINE_ );
5516 if (recvFromStruct != NULL)
5517 {
5518 recvFromStruct->s=s;
5519 SocketLayer::RecvFromBlocking(s, this, recvFromStruct->data, &recvFromStruct->bytesRead, &recvFromStruct->systemAddress, &recvFromStruct->timeRead);
5520
5521 if (recvFromStruct->bytesRead>0)
5522 {
5523 RakAssert(recvFromStruct->systemAddress.GetPort());
5524 bufferedPackets.Push(recvFromStruct);
5525 quitAndDataEvents.SetEvent();
5526
5527 // Got data
5528 return true;
5529 }
5530 else
5531 {
5532 bufferedPackets.Deallocate(recvFromStruct, _FILE_AND_LINE_);
5533 }
5534 }
5535 // No data
5536 return false;
5537 }
5538 */
5539 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5540 bool RakPeer::RunUpdateCycle(BitStream &updateBitStream )
5541 {
5542 RakPeer::RemoteSystemStruct * remoteSystem;
5543 unsigned int activeSystemListIndex;
5544 Packet *packet;
5545 // int currentSentBytes,currentReceivedBytes;
5546 // unsigned numberOfBytesUsed;
5547 // BitSize_t numberOfBitsUsed;
5548 //SystemAddress authoritativeClientSystemAddress;
5549 BitSize_t bitSize;
5550 unsigned int byteSize;
5551 unsigned char *data;
5552 SystemAddress systemAddress;
5553 BufferedCommandStruct *bcs;
5554 bool callerDataAllocationUsed;
5555 RakNetStatistics *rnss;
5556 SLNet::TimeUS timeNS=0;
5557 SLNet::Time timeMS=0;
5558
5559 // This is here so RecvFromBlocking actually gets data from the same thread
5560
5561 #if defined(WINDOWS_STORE_RT)
5562 #elif defined(_WIN32)
5563 if (socketList[0]->GetSocketType()==RNS2T_WINDOWS && ((RNS2_Windows*)socketList[0])->GetSocketLayerOverride())
5564 {
5565 int len;
5566 SystemAddress sender;
5567 char dataOut[ MAXIMUM_MTU_SIZE ];
5568 do {
5569 len = ((RNS2_Windows*)socketList[0])->GetSocketLayerOverride()->RakNetRecvFrom(dataOut,&sender,true);
5570 if (len>0)
5571 ProcessNetworkPacket( sender, dataOut, len, this, socketList[0], SLNet::GetTimeUS(), updateBitStream );
5572 } while (len>0);
5573 }
5574 #endif
5575
5576 // unsigned int socketListIndex;
5577 RNS2RecvStruct *recvFromStruct;
5578 while ((recvFromStruct=PopBufferedPacket())!=0)
5579 {
5580 /*
5581 for (socketListIndex=0; socketListIndex < socketList.Size(); socketListIndex++)
5582 {
5583 if ((RakNetSocket*) socketList[socketListIndex]==recvFromStruct->s)
5584 break;
5585 }
5586 if (socketListIndex!=socketList.Size())
5587 */
5588 ProcessNetworkPacket(recvFromStruct->systemAddress, recvFromStruct->data, recvFromStruct->bytesRead, this, recvFromStruct->socket, recvFromStruct->timeRead, updateBitStream);
5589 DeallocRNS2RecvStruct(recvFromStruct, _FILE_AND_LINE_);
5590 }
5591
5592 while ((bcs=bufferedCommands.PopInaccurate())!=0)
5593 {
5594 if (bcs->command==BufferedCommandStruct::BCS_SEND)
5595 {
5596 // GetTime is a very slow call so do it once and as late as possible
5597 if (timeNS==0)
5598 {
5599 timeNS = SLNet::GetTimeUS();
5600 timeMS = (SLNet::TimeMS)(timeNS/(SLNet::TimeUS)1000);
5601 }
5602
5603 callerDataAllocationUsed=SendImmediate((char*)bcs->data, bcs->numberOfBitsToSend, bcs->priority, bcs->reliability, bcs->orderingChannel, bcs->systemIdentifier, bcs->broadcast, true, timeNS, bcs->receipt);
5604 if ( callerDataAllocationUsed==false )
5605 rakFree_Ex(bcs->data, _FILE_AND_LINE_ );
5606
5607 // 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
5608 if (bcs->connectionMode!=RemoteSystemStruct::NO_ACTION )
5609 {
5610 remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
5611 if (remoteSystem)
5612 remoteSystem->connectMode=bcs->connectionMode;
5613 }
5614 }
5615 else if (bcs->command==BufferedCommandStruct::BCS_CLOSE_CONNECTION)
5616 {
5617 CloseConnectionInternal(bcs->systemIdentifier, false, true, bcs->orderingChannel, bcs->priority);
5618 }
5619 else if (bcs->command==BufferedCommandStruct::BCS_CHANGE_SYSTEM_ADDRESS)
5620 {
5621 // Reroute
5622 RakPeer::RemoteSystemStruct *rssFromGuid = GetRemoteSystem(bcs->systemIdentifier.rakNetGuid,true,true);
5623 if (rssFromGuid!=0)
5624 {
5625 unsigned int existingSystemIndex = GetRemoteSystemIndex(rssFromGuid->systemAddress);
5626 ReferenceRemoteSystem(bcs->systemIdentifier.systemAddress, existingSystemIndex);
5627 }
5628 }
5629 else if (bcs->command==BufferedCommandStruct::BCS_GET_SOCKET)
5630 {
5631 SocketQueryOutput *sqo;
5632 if (bcs->systemIdentifier.IsUndefined())
5633 {
5634 sqo = socketQueryOutput.Allocate( _FILE_AND_LINE_ );
5635 sqo->sockets=socketList;
5636 socketQueryOutput.Push(sqo);
5637 }
5638 else
5639 {
5640 remoteSystem=GetRemoteSystem( bcs->systemIdentifier, true, true );
5641 sqo = socketQueryOutput.Allocate( _FILE_AND_LINE_ );
5642
5643 sqo->sockets.Clear(false, _FILE_AND_LINE_);
5644 if (remoteSystem)
5645 {
5646 sqo->sockets.Push(remoteSystem->rakNetSocket, _FILE_AND_LINE_ );
5647 }
5648 else
5649 {
5650 // Leave empty smart pointer
5651 }
5652 socketQueryOutput.Push(sqo);
5653 }
5654
5655 }
5656
5657 #ifdef _DEBUG
5658 bcs->data=0;
5659 #endif
5660
5661 bufferedCommands.Deallocate(bcs, _FILE_AND_LINE_);
5662 }
5663
5664 if (requestedConnectionQueue.IsEmpty()==false)
5665 {
5666 if (timeNS==0)
5667 {
5668 timeNS = SLNet::GetTimeUS();
5669 timeMS = (SLNet::TimeMS)(timeNS/(SLNet::TimeUS)1000);
5670 }
5671
5672 bool condition1, condition2;
5673 unsigned requestedConnectionQueueIndex=0;
5674 requestedConnectionQueueMutex.Lock();
5675 while (requestedConnectionQueueIndex < requestedConnectionQueue.Size())
5676 {
5677 RequestedConnectionStruct *rcs;
5678 rcs = requestedConnectionQueue[requestedConnectionQueueIndex];
5679 requestedConnectionQueueMutex.Unlock();
5680 if (rcs->nextRequestTime < timeMS)
5681 {
5682 condition1=rcs->requestsMade==rcs->sendConnectionAttemptCount+1;
5683 condition2=(bool)((rcs->systemAddress==UNASSIGNED_SYSTEM_ADDRESS)==1);
5684 // If too many requests made or a hole then remove this if possible, otherwise invalidate it
5685 if (condition1 || condition2)
5686 {
5687 if (rcs->data)
5688 {
5689 rakFree_Ex(rcs->data, _FILE_AND_LINE_ );
5690 rcs->data=0;
5691 }
5692
5693 if (condition1 && !condition2 && rcs->actionToTake==RequestedConnectionStruct::CONNECT)
5694 {
5695 // Tell user of connection attempt failed
5696 packet=AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5697 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
5698 packet->bitSize = ( sizeof( char ) * 8);
5699 packet->systemAddress = rcs->systemAddress;
5700 AddPacketToProducer(packet);
5701 }
5702
5703 #if LIBCAT_SECURITY==1
5704 CAT_AUDIT_PRINTF("AUDIT: Connection attempt FAILED so deleting rcs->client_handshake object %x\n", rcs->client_handshake);
5705 SLNet::OP_DELETE(rcs->client_handshake,_FILE_AND_LINE_);
5706 #endif
5707 SLNet::OP_DELETE(rcs,_FILE_AND_LINE_);
5708
5709 requestedConnectionQueueMutex.Lock();
5710 for (unsigned int k=0; k < requestedConnectionQueue.Size(); k++)
5711 {
5712 if (requestedConnectionQueue[k]==rcs)
5713 {
5714 requestedConnectionQueue.RemoveAtIndex(k);
5715 break;
5716 }
5717 }
5718 requestedConnectionQueueMutex.Unlock();
5719 }
5720 else
5721 {
5722
5723 int MTUSizeIndex = rcs->requestsMade / (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES);
5724 if (MTUSizeIndex>=NUM_MTU_SIZES)
5725 MTUSizeIndex=NUM_MTU_SIZES-1;
5726 rcs->requestsMade++;
5727 rcs->nextRequestTime=timeMS+rcs->timeBetweenSendConnectionAttemptsMS;
5728
5729 SLNet::BitStream bitStream;
5730 //WriteOutOfBandHeader(&bitStream, ID_USER_PACKET_ENUM);
5731 bitStream.Write((MessageID)ID_OPEN_CONNECTION_REQUEST_1);
5732 bitStream.WriteAlignedBytes((const unsigned char*) OFFLINE_MESSAGE_DATA_ID, sizeof(OFFLINE_MESSAGE_DATA_ID));
5733 bitStream.Write((MessageID)RAKNET_PROTOCOL_VERSION);
5734 bitStream.PadWithZeroToByteLength(mtuSizes[MTUSizeIndex]-UDP_HEADER_SIZE);
5735
5736 char str[256];
5737 rcs->systemAddress.ToString(true,str,static_cast<size_t>(256));
5738
5739 //RAKNET_DEBUG_PRINTF("%i:IOCR, ", __LINE__);
5740
5741 unsigned i;
5742 for (i=0; i < pluginListNTS.Size(); i++)
5743 pluginListNTS[i]->OnDirectSocketSend((const char*) bitStream.GetData(), bitStream.GetNumberOfBitsUsed(), rcs->systemAddress);
5744
5745 RakNetSocket2 *socketToUse;
5746 if (rcs->socket == 0)
5747 socketToUse = socketList[rcs->socketIndex];
5748 else
5749 socketToUse = rcs->socket;
5750
5751 rcs->systemAddress.FixForIPVersion(socketToUse->GetBoundAddress());
5752 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
5753 if (socketToUse->IsBerkleySocket())
5754 ((RNS2_Berkley*)socketToUse)->SetDoNotFragment(1);
5755 #endif
5756
5757 // SocketLayer::SetDoNotFragment(socketToUse, 1);
5758 SLNet::Time sendToStart= SLNet::GetTime();
5759
5760 RNS2_SendParameters bsp;
5761 bsp.data = (char*) bitStream.GetData();
5762 bsp.length = bitStream.GetNumberOfBytesUsed();
5763 bsp.systemAddress = rcs->systemAddress;
5764 if (socketToUse->Send(&bsp, _FILE_AND_LINE_) == 10040)
5765 // if (SocketLayer::SendTo( socketToUse, (const char*) bitStream.GetData(), bitStream.GetNumberOfBytesUsed(), rcs->systemAddress, _FILE_AND_LINE_ )==-10040)
5766 {
5767 // Don't use this MTU size again
5768 rcs->requestsMade = (unsigned char) ((MTUSizeIndex + 1) * (rcs->sendConnectionAttemptCount/NUM_MTU_SIZES));
5769 rcs->nextRequestTime=timeMS;
5770 }
5771 else
5772 {
5773 SLNet::Time sendToEnd= SLNet::GetTime();
5774 if (sendToEnd-sendToStart>100)
5775 {
5776 // Drop to lowest MTU
5777 int lowestMtuIndex = rcs->sendConnectionAttemptCount/NUM_MTU_SIZES * (NUM_MTU_SIZES - 1);
5778 if (lowestMtuIndex > rcs->requestsMade)
5779 {
5780 rcs->requestsMade = (unsigned char) lowestMtuIndex;
5781 rcs->nextRequestTime=timeMS;
5782 }
5783 else
5784 rcs->requestsMade=(unsigned char)(rcs->sendConnectionAttemptCount+1);
5785 }
5786 }
5787 // SocketLayer::SetDoNotFragment(socketToUse, 0);
5788 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
5789 if (socketToUse->IsBerkleySocket())
5790 ((RNS2_Berkley*)socketToUse)->SetDoNotFragment(0);
5791 #endif
5792
5793 requestedConnectionQueueIndex++;
5794 }
5795 }
5796 else
5797 requestedConnectionQueueIndex++;
5798
5799 requestedConnectionQueueMutex.Lock();
5800 }
5801 requestedConnectionQueueMutex.Unlock();
5802 }
5803
5804 // remoteSystemList in network thread
5805 for ( activeSystemListIndex = 0; activeSystemListIndex < activeSystemListSize; ++activeSystemListIndex )
5806 //for ( remoteSystemIndex = 0; remoteSystemIndex < remoteSystemListSize; ++remoteSystemIndex )
5807 {
5808 // I'm using systemAddress from remoteSystemList but am not locking it because this loop is called very frequently and it doesn't
5809 // matter if we miss or do an extra update. The reliability layers themselves never care which player they are associated with
5810 //systemAddress = remoteSystemList[ remoteSystemIndex ].systemAddress;
5811 // Allow the systemAddress for this remote system list to change. We don't care if it changes now.
5812 // remoteSystemList[ remoteSystemIndex ].allowSystemAddressAssigment=true;
5813
5814
5815 // Found an active remote system
5816 remoteSystem = activeSystemList[ activeSystemListIndex ];
5817 systemAddress = remoteSystem->systemAddress;
5818 RakAssert(systemAddress!=UNASSIGNED_SYSTEM_ADDRESS);
5819 // Update is only safe to call from the same thread that calls HandleSocketReceiveFromConnectedPlayer,
5820 // which is this thread
5821
5822 if (timeNS==0)
5823 {
5824 timeNS = SLNet::GetTimeUS();
5825 timeMS = (SLNet::TimeMS)(timeNS/(SLNet::TimeUS)1000);
5826 //RAKNET_DEBUG_PRINTF("timeNS = %I64i timeMS=%i\n", timeNS, timeMS);
5827 }
5828
5829
5830 if (timeMS > remoteSystem->lastReliableSend && timeMS-remoteSystem->lastReliableSend > remoteSystem->reliabilityLayer.GetTimeoutTime()/2 && remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
5831 {
5832 // If no reliable packets are waiting for an ack, do a one byte reliable send so that disconnections are noticed
5833 RakNetStatistics rakNetStatistics;
5834 rnss=remoteSystem->reliabilityLayer.GetStatistics(&rakNetStatistics);
5835 if (rnss->messagesInResendBuffer==0)
5836 {
5837 PingInternal( systemAddress, true, RELIABLE );
5838
5839 //remoteSystem->lastReliableSend=timeMS+remoteSystem->reliabilityLayer.GetTimeoutTime();
5840 remoteSystem->lastReliableSend=timeMS;
5841 }
5842 }
5843
5844 remoteSystem->reliabilityLayer.Update( remoteSystem->rakNetSocket, systemAddress, remoteSystem->MTUSize, timeNS, maxOutgoingBPS, pluginListNTS, &rnr, updateBitStream ); // systemAddress only used for the internet simulator test
5845
5846 // Check for failure conditions
5847 if ( remoteSystem->reliabilityLayer.IsDeadConnection() ||
5848 ((remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY) && remoteSystem->reliabilityLayer.IsOutgoingDataWaiting()==false) ||
5849 (remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK && (remoteSystem->reliabilityLayer.AreAcksWaiting()==false || remoteSystem->reliabilityLayer.AckTimeout(timeMS)==true)) ||
5850 ((
5851 (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
5852 remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
5853 remoteSystem->connectMode==RemoteSystemStruct::UNVERIFIED_SENDER)
5854 && timeMS > remoteSystem->connectionTime && timeMS - remoteSystem->connectionTime > 10000))
5855 )
5856 {
5857 // RAKNET_DEBUG_PRINTF("timeMS=%i remoteSystem->connectionTime=%i\n", timeMS, remoteSystem->connectionTime );
5858
5859 // Failed. Inform the user?
5860 // TODO - RakNet 4.0 - Return a different message identifier for DISCONNECT_ASAP_SILENTLY and DISCONNECT_ASAP than for DISCONNECT_ON_NO_ACK
5861 // The first two mean we called CloseConnection(), the last means the other system sent us ID_DISCONNECTION_NOTIFICATION
5862 if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED || remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION
5863 || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ASAP || remoteSystem->connectMode==RemoteSystemStruct::DISCONNECT_ON_NO_ACK)
5864 {
5865
5866 // SLNet::BitStream undeliveredMessages;
5867 // remoteSystem->reliabilityLayer.GetUndeliveredMessages(&undeliveredMessages,remoteSystem->MTUSize);
5868
5869 // packet=AllocPacket(sizeof( char ) + undeliveredMessages.GetNumberOfBytesUsed());
5870 packet=AllocPacket(sizeof( char ), _FILE_AND_LINE_);
5871 if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
5872 packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't
5873 else if (remoteSystem->connectMode==RemoteSystemStruct::CONNECTED)
5874 packet->data[ 0 ] = ID_CONNECTION_LOST; // DeadConnection
5875 else
5876 packet->data[ 0 ] = ID_DISCONNECTION_NOTIFICATION; // DeadConnection
5877
5878 // memcpy(packet->data+1, undeliveredMessages.GetData(), undeliveredMessages.GetNumberOfBytesUsed());
5879
5880 packet->guid = remoteSystem->guid;
5881 packet->systemAddress = systemAddress;
5882 packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
5883 packet->guid.systemIndex=packet->systemAddress.systemIndex;
5884
5885 AddPacketToProducer(packet);
5886 }
5887 // else connection shutting down, don't bother telling the user
5888
5889 #ifdef _DO_PRINTF
5890 RAKNET_DEBUG_PRINTF("Connection dropped for player %i:%i\n", systemAddress);
5891 #endif
5892 CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
5893 continue;
5894 }
5895
5896 // Ping this guy if it is time to do so
5897 if ( remoteSystem->connectMode==RemoteSystemStruct::CONNECTED && timeMS > remoteSystem->nextPingTime && ( occasionalPing || remoteSystem->lowestPing == (unsigned short)-1 ) )
5898 {
5899 remoteSystem->nextPingTime = timeMS + 5000;
5900 PingInternal( systemAddress, true, UNRELIABLE );
5901
5902 // Update again immediately after this tick so the ping goes out right away
5903 quitAndDataEvents.SetEvent();
5904 }
5905
5906 // Find whoever has the lowest player ID
5907 //if (systemAddress < authoritativeClientSystemAddress)
5908 // authoritativeClientSystemAddress=systemAddress;
5909
5910 // Does the reliability layer have any packets waiting for us?
5911 // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
5912 bitSize = remoteSystem->reliabilityLayer.Receive( &data );
5913
5914 while ( bitSize > 0 )
5915 {
5916 // These types are for internal use and should never arrive from a network packet
5917 if (data[0]==ID_CONNECTION_ATTEMPT_FAILED)
5918 {
5919 RakAssert(0);
5920 bitSize=0;
5921 continue;
5922 }
5923
5924 // Fast and easy - just use the data that was returned
5925 byteSize = (unsigned int) BITS_TO_BYTES( bitSize );
5926
5927 // For unknown senders we only accept a few specific packets
5928 if (remoteSystem->connectMode==RemoteSystemStruct::UNVERIFIED_SENDER)
5929 {
5930 if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
5931 {
5932 ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
5933 rakFree_Ex(data, _FILE_AND_LINE_ );
5934 }
5935 else
5936 {
5937 CloseConnectionInternal( systemAddress, false, true, 0, LOW_PRIORITY );
5938 #ifdef _DO_PRINTF
5939 RAKNET_DEBUG_PRINTF("Temporarily banning %i:%i for sending nonsense data\n", systemAddress);
5940 #endif
5941
5942 char str1[64];
5943 systemAddress.ToString(false, str1, static_cast<size_t>(64));
5944 AddToBanList(str1, remoteSystem->reliabilityLayer.GetTimeoutTime());
5945
5946
5947 rakFree_Ex(data, _FILE_AND_LINE_ );
5948 }
5949 }
5950 else
5951 {
5952 // However, if we are connected we still take a connection request in case both systems are trying to connect to each other
5953 // at the same time
5954 if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST )
5955 {
5956 // 04/27/06 This is wrong. With cross connections, we can both have initiated the connection are in state REQUESTED_CONNECTION
5957 // 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))
5958 if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
5959 {
5960 ParseConnectionRequestPacket(remoteSystem, systemAddress, (const char*)data, byteSize);
5961 }
5962 else
5963 {
5964
5965 SLNet::BitStream bs((unsigned char*) data,byteSize,false);
5966 bs.IgnoreBytes(sizeof(MessageID));
5967 bs.IgnoreBytes(sizeof(OFFLINE_MESSAGE_DATA_ID));
5968 bs.IgnoreBytes(RakNetGUID::size());
5969 SLNet::Time incomingTimestamp;
5970 bs.Read(incomingTimestamp);
5971
5972 // Got a connection request message from someone we are already connected to. Just reply normally.
5973 // This can happen due to race conditions with the fully connected mesh
5974 OnConnectionRequest( remoteSystem, incomingTimestamp );
5975 }
5976 rakFree_Ex(data, _FILE_AND_LINE_ );
5977 }
5978 else if ( (unsigned char) data[ 0 ] == ID_NEW_INCOMING_CONNECTION && byteSize > sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(SLNet::Time)*2 )
5979 {
5980 if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST)
5981 {
5982 remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
5983 PingInternal( systemAddress, true, UNRELIABLE );
5984
5985 // Update again immediately after this tick so the ping goes out right away
5986 quitAndDataEvents.SetEvent();
5987
5988 SLNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
5989 SystemAddress bsSystemAddress;
5990
5991 inBitStream.IgnoreBits(8);
5992 inBitStream.Read(bsSystemAddress);
5993 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
5994 inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
5995
5996 SLNet::Time sendPingTime, sendPongTime;
5997 inBitStream.Read(sendPingTime);
5998 inBitStream.Read(sendPongTime);
5999 OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
6000
6001 // Overwrite the data in the packet
6002 // NewIncomingConnectionStruct newIncomingConnectionStruct;
6003 // SLNet::BitStream nICS_BS( data, NewIncomingConnectionStruct_Size, false );
6004 // newIncomingConnectionStruct.Deserialize( nICS_BS );
6005
6006 remoteSystem->myExternalSystemAddress = bsSystemAddress;
6007
6008 // Bug: If A connects to B through R, A's firstExternalID is set to R. If A tries to send to R, sends to loopback because R==firstExternalID
6009 // Correct fix is to specify in Connect() if target is through a proxy.
6010 // However, in practice you have to connect to something else first anyway to know about the proxy. So setting once only is good enough
6011 if (firstExternalID==UNASSIGNED_SYSTEM_ADDRESS)
6012 {
6013 firstExternalID=bsSystemAddress;
6014 firstExternalID.debugPort=ntohs(firstExternalID.address.addr4.sin_port);
6015 }
6016
6017 // Send this info down to the game
6018 packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6019 packet->bitSize = bitSize;
6020 packet->systemAddress = systemAddress;
6021 packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
6022 packet->guid = remoteSystem->guid;
6023 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6024 AddPacketToProducer(packet);
6025 }
6026 else
6027 {
6028 // Send to game even if already connected. This could happen when connecting to 127.0.0.1
6029 // Ignore, already connected
6030 // rakFree_Ex(data, _FILE_AND_LINE_ );
6031 }
6032 }
6033 else if ( (unsigned char) data[ 0 ] == ID_CONNECTED_PONG && byteSize == sizeof(unsigned char)+sizeof(SLNet::Time)*2 )
6034 {
6035 SLNet::Time sendPingTime, sendPongTime;
6036
6037 // Copy into the ping times array the current time - the value returned
6038 // First extract the sent ping
6039 SLNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
6040 //PingStruct ps;
6041 //ps.Deserialize(psBS);
6042 inBitStream.IgnoreBits(8);
6043 inBitStream.Read(sendPingTime);
6044 inBitStream.Read(sendPongTime);
6045
6046 OnConnectedPong(sendPingTime,sendPongTime,remoteSystem);
6047
6048 rakFree_Ex(data, _FILE_AND_LINE_ );
6049 }
6050 else if ( (unsigned char)data[0] == ID_CONNECTED_PING && byteSize == sizeof(unsigned char)+sizeof(SLNet::Time) )
6051 {
6052 SLNet::BitStream inBitStream( (unsigned char *) data, byteSize, false );
6053 inBitStream.IgnoreBits(8);
6054 SLNet::Time sendPingTime;
6055 inBitStream.Read(sendPingTime);
6056
6057 SLNet::BitStream outBitStream;
6058 outBitStream.Write((MessageID)ID_CONNECTED_PONG);
6059 outBitStream.Write(sendPingTime);
6060 outBitStream.Write(SLNet::GetTime());
6061 SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, UNRELIABLE, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0 );
6062
6063 // Update again immediately after this tick so the ping goes out right away
6064 quitAndDataEvents.SetEvent();
6065
6066 rakFree_Ex(data, _FILE_AND_LINE_ );
6067 }
6068 else if ( (unsigned char) data[ 0 ] == ID_DISCONNECTION_NOTIFICATION )
6069 {
6070 // We shouldn't close the connection immediately because we need to ack the ID_DISCONNECTION_NOTIFICATION
6071 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ON_NO_ACK;
6072 rakFree_Ex(data, _FILE_AND_LINE_ );
6073
6074 // AddPacketToProducer(packet);
6075 }
6076 else if ( (unsigned char)(data)[0] == ID_DETECT_LOST_CONNECTIONS && byteSize == sizeof(unsigned char) )
6077 {
6078 // Do nothing
6079 rakFree_Ex(data, _FILE_AND_LINE_ );
6080 }
6081 else if ( (unsigned char)(data)[0] == ID_INVALID_PASSWORD )
6082 {
6083 if (remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION)
6084 {
6085 packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6086 packet->bitSize = bitSize;
6087 packet->systemAddress = systemAddress;
6088 packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
6089 packet->guid = remoteSystem->guid;
6090 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6091 AddPacketToProducer(packet);
6092
6093 remoteSystem->connectMode=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY;
6094 }
6095 else
6096 {
6097 rakFree_Ex(data, _FILE_AND_LINE_ );
6098 }
6099 }
6100 else if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST_ACCEPTED )
6101 {
6102 if (byteSize > sizeof(MessageID)+sizeof(unsigned int)+sizeof(unsigned short)+sizeof(SystemIndex)+sizeof(SLNet::Time)*2)
6103 {
6104 // Make sure this connection accept is from someone we wanted to connect to
6105 bool allowConnection, alreadyConnected;
6106
6107 if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST ||
6108 remoteSystem->connectMode==RemoteSystemStruct::REQUESTED_CONNECTION ||
6109 allowConnectionResponseIPMigration)
6110 allowConnection=true;
6111 else
6112 allowConnection=false;
6113
6114 if (remoteSystem->connectMode==RemoteSystemStruct::HANDLING_CONNECTION_REQUEST)
6115 alreadyConnected=true;
6116 else
6117 alreadyConnected=false;
6118
6119 if ( allowConnection )
6120 {
6121 SystemAddress externalID;
6122 SystemIndex systemIndex;
6123 // SystemAddress internalID;
6124
6125 SLNet::BitStream inBitStream((unsigned char *) data, byteSize, false);
6126 inBitStream.IgnoreBits(8);
6127 // inBitStream.Read(remotePort);
6128 inBitStream.Read(externalID);
6129 inBitStream.Read(systemIndex);
6130 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
6131 inBitStream.Read(remoteSystem->theirInternalSystemAddress[i]);
6132
6133 SLNet::Time sendPingTime, sendPongTime;
6134 inBitStream.Read(sendPingTime);
6135 inBitStream.Read(sendPongTime);
6136 OnConnectedPong(sendPingTime, sendPongTime, remoteSystem);
6137
6138 // Find a free remote system struct to use
6139 // SLNet::BitStream casBitS(data, byteSize, false);
6140 // ConnectionAcceptStruct cas;
6141 // cas.Deserialize(casBitS);
6142 // systemAddress.GetPort() = remotePort;
6143
6144 // The remote system told us our external IP, so save it
6145 remoteSystem->myExternalSystemAddress = externalID;
6146 remoteSystem->connectMode=RemoteSystemStruct::CONNECTED;
6147
6148 // Bug: If A connects to B through R, A's firstExternalID is set to R. If A tries to send to R, sends to loopback because R==firstExternalID
6149 // Correct fix is to specify in Connect() if target is through a proxy.
6150 // However, in practice you have to connect to something else first anyway to know about the proxy. So setting once only is good enough
6151 if (firstExternalID==UNASSIGNED_SYSTEM_ADDRESS)
6152 {
6153 firstExternalID=externalID;
6154 firstExternalID.debugPort=ntohs(firstExternalID.address.addr4.sin_port);
6155 }
6156
6157 // Send the connection request complete to the game
6158 packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6159 packet->bitSize = byteSize * 8;
6160 packet->systemAddress = systemAddress;
6161 packet->systemAddress.systemIndex = ( SystemIndex ) GetIndexFromSystemAddress( systemAddress, true );
6162 packet->guid = remoteSystem->guid;
6163 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6164 AddPacketToProducer(packet);
6165
6166 SLNet::BitStream outBitStream;
6167 outBitStream.Write((MessageID)ID_NEW_INCOMING_CONNECTION);
6168 outBitStream.Write(systemAddress);
6169 for (unsigned int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
6170 outBitStream.Write(ipList[i]);
6171 outBitStream.Write(sendPongTime);
6172 outBitStream.Write(SLNet::GetTime());
6173
6174 SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), IMMEDIATE_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false, false, SLNet::GetTimeUS(), 0 );
6175
6176 if (alreadyConnected==false)
6177 {
6178 PingInternal( systemAddress, true, UNRELIABLE );
6179 }
6180 }
6181 else
6182 {
6183 // Ignore, already connected
6184 rakFree_Ex(data, _FILE_AND_LINE_ );
6185 }
6186 }
6187 else
6188 {
6189 // Version mismatch error?
6190 RakAssert(0);
6191 rakFree_Ex(data, _FILE_AND_LINE_ );
6192 }
6193 }
6194 else
6195 {
6196 // What do I do if I get a message from a system, before I am fully connected?
6197 // I can either ignore it or give it to the user
6198 // It seems like giving it to the user is a better option
6199 if ((data[0]>=(MessageID)ID_TIMESTAMP || data[0]==ID_SND_RECEIPT_ACKED || data[0]==ID_SND_RECEIPT_LOSS) &&
6200 remoteSystem->isActive
6201 )
6202 {
6203 packet=AllocPacket(byteSize, data, _FILE_AND_LINE_);
6204 packet->bitSize = bitSize;
6205 packet->systemAddress = systemAddress;
6206 packet->systemAddress.systemIndex = remoteSystem->remoteSystemIndex;
6207 packet->guid = remoteSystem->guid;
6208 packet->guid.systemIndex=packet->systemAddress.systemIndex;
6209 AddPacketToProducer(packet);
6210 }
6211 else
6212 {
6213 rakFree_Ex(data, _FILE_AND_LINE_ );
6214 }
6215 }
6216 }
6217
6218 // Does the reliability layer have any more packets waiting for us?
6219 // To be thread safe, this has to be called in the same thread as HandleSocketReceiveFromConnectedPlayer
6220 bitSize = remoteSystem->reliabilityLayer.Receive( &data );
6221 }
6222
6223 }
6224
6225 return true;
6226 }
6227
6228 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6229
6230 void RakPeer::OnRNS2Recv(RNS2RecvStruct *recvStruct)
6231 {
6232 if (incomingDatagramEventHandler)
6233 {
6234 if (incomingDatagramEventHandler(recvStruct)!=true)
6235 return;
6236 }
6237
6238 PushBufferedPacket(recvStruct);
6239 quitAndDataEvents.SetEvent();
6240 }
6241
6242 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6243
6244 /*
6245 RAK_THREAD_DECLARATION(SLNet::RecvFromLoop)
6246 {
6247 #if defined(SN_TARGET_PSP2)
6248 RakPeerAndIndex *rpai = ( RakPeerAndIndex * ) RakThread::GetRealThreadArgument(callGetRealThreadArgument);
6249 #else
6250 RakPeerAndIndex *rpai = ( RakPeerAndIndex * ) arguments;
6251 #endif
6252 RakPeer * rakPeer = rpai->rakPeer;
6253 RakNetSocket *s = rpai->s;
6254 SLNet::OP_DELETE(rpai,_FILE_AND_LINE_);
6255
6256 rakPeer->isRecvFromLoopThreadActive.Increment();
6257
6258 while ( rakPeer->endThreads == false )
6259 {
6260 if (rakPeer->RunRecvFromOnce(s)==false &&
6261 s->GetBlockingSocket()==false)
6262 RakSleep(0);
6263 }
6264 rakPeer->isRecvFromLoopThreadActive.Decrement();
6265
6266 #if defined(SN_TARGET_PSP2)
6267 return sceKernelExitDeleteThread(0);
6268 #else
6269 return 0;
6270 #endif
6271 }
6272 */
6273
6274 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6275 RAK_THREAD_DECLARATION(SLNet::UpdateNetworkLoop)
6276 {
6277
6278
6279
6280 RakPeer * rakPeer = ( RakPeer * ) arguments;
6281
6282
6283 /*
6284 // 11/15/05 - this is slower than Sleep()
6285 #ifdef _WIN32
6286 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
6287 // Lets see if these timers give better performance than Sleep
6288 HANDLE timerHandle;
6289 LARGE_INTEGER dueTime;
6290
6291 if ( rakPeer->threadSleepTimer <= 0 )
6292 rakPeer->threadSleepTimer = 1;
6293
6294 // 2nd parameter of false means synchronization timer instead of manual-reset timer
6295 timerHandle = CreateWaitableTimer( NULL, FALSE, 0 );
6296
6297 RakAssert( timerHandle );
6298
6299 dueTime.QuadPart = -10000 * rakPeer->threadSleepTimer; // 10000 is 1 ms?
6300
6301 BOOL success = SetWaitableTimer( timerHandle, &dueTime, rakPeer->threadSleepTimer, NULL, NULL, FALSE );
6302 (void) success;
6303 RakAssert( success );
6304
6305 #endif
6306 #endif
6307 */
6308
6309 BitStream updateBitStream( MAXIMUM_MTU_SIZE
6310 #if LIBCAT_SECURITY==1
6311 + cat::AuthenticatedEncryption::OVERHEAD_BYTES
6312 #endif
6313 );
6314 //
6315 rakPeer->isMainLoopThreadActive = true;
6316
6317 bool running = true;
6318 while ( running )
6319 {
6320 if (rakPeer->endThreads) {
6321 // allow just one more final update-run prior to shutting down this thread to make sure that outstanding acks are still sent and the peers don't unnecessary wait for already retrieved packets
6322 // note: this fixes part of SLNET-123
6323 running = false;
6324 }
6325 // #ifdef _DEBUG
6326 // // Sanity check, make sure RunUpdateCycle does not block or not otherwise get called for a long time
6327 // RakNetTime thisCall=SLNet::GetTime();
6328 // RakAssert(thisCall-lastCall<250);
6329 // lastCall=thisCall;
6330 // #endif
6331 if (rakPeer->userUpdateThreadPtr)
6332 rakPeer->userUpdateThreadPtr(rakPeer, rakPeer->userUpdateThreadData);
6333
6334 rakPeer->RunUpdateCycle(updateBitStream);
6335
6336 // Pending sends go out this often, unless quitAndDataEvents is set
6337 rakPeer->quitAndDataEvents.WaitOnEvent(10);
6338
6339 /*
6340
6341 // #if ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) &&
6342 #if defined(USE_WAIT_FOR_MULTIPLE_EVENTS) && defined(_WIN32)
6343
6344 if (rakPeer->threadSleepTimer>0)
6345 {
6346 WSAEVENT eventArray[256];
6347 unsigned int i, eventArrayIndex;
6348 for (i=0,eventArrayIndex=0; i < rakPeer->socketList.Size(); i++)
6349 {
6350 if (rakPeer->socketList[i]->recvEvent!=INVALID_HANDLE_VALUE)
6351 {
6352 eventArray[eventArrayIndex]=rakPeer->socketList[i]->recvEvent;
6353 eventArrayIndex++;
6354 if (eventArrayIndex==256)
6355 break;
6356 }
6357 }
6358 WSAWaitForMultipleEvents(eventArrayIndex,(const HANDLE*) &eventArray,FALSE,rakPeer->threadSleepTimer,FALSE);
6359 }
6360 else
6361 {
6362 RakSleep(0);
6363 }
6364
6365 #else // ((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
6366 #pragma message("-- RakNet: Using Sleep(). Uncomment USE_WAIT_FOR_MULTIPLE_EVENTS in defines.h if you want to use WaitForSingleObject instead. --")
6367
6368 RakSleep( rakPeer->threadSleepTimer );
6369 #endif
6370 */
6371 }
6372
6373 rakPeer->isMainLoopThreadActive = false;
6374
6375 /*
6376 #ifdef _WIN32
6377 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
6378 CloseHandle(timerHandle);
6379 #endif
6380 #endif
6381 */
6382
6383
6384
6385
6386 return 0;
6387
6388 }
6389
6390 void RakPeer::CallPluginCallbacks(DataStructures::List<PluginInterface2*> &pluginList, Packet *packet)
6391 {
6392 for (unsigned int i=0; i < pluginList.Size(); i++)
6393 {
6394 switch (packet->data[0])
6395 {
6396 case ID_DISCONNECTION_NOTIFICATION:
6397 pluginList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_DISCONNECTION_NOTIFICATION);
6398 break;
6399 case ID_CONNECTION_LOST:
6400 pluginList[i]->OnClosedConnection(packet->systemAddress, packet->guid, LCR_CONNECTION_LOST);
6401 break;
6402 case ID_NEW_INCOMING_CONNECTION:
6403 pluginList[i]->OnNewConnection(packet->systemAddress, packet->guid, true);
6404 break;
6405 case ID_CONNECTION_REQUEST_ACCEPTED:
6406 pluginList[i]->OnNewConnection(packet->systemAddress, packet->guid, false);
6407 break;
6408 case ID_CONNECTION_ATTEMPT_FAILED:
6409 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_ATTEMPT_FAILED);
6410 break;
6411 case ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY:
6412 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY);
6413 break;
6414 case ID_OUR_SYSTEM_REQUIRES_SECURITY:
6415 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_OUR_SYSTEM_REQUIRES_SECURITY);
6416 break;
6417 case ID_PUBLIC_KEY_MISMATCH:
6418 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_PUBLIC_KEY_MISMATCH);
6419 break;
6420 case ID_ALREADY_CONNECTED:
6421 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_ALREADY_CONNECTED);
6422 break;
6423 case ID_NO_FREE_INCOMING_CONNECTIONS:
6424 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_NO_FREE_INCOMING_CONNECTIONS);
6425 break;
6426 case ID_CONNECTION_BANNED:
6427 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_CONNECTION_BANNED);
6428 break;
6429 case ID_INVALID_PASSWORD:
6430 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_INVALID_PASSWORD);
6431 break;
6432 case ID_INCOMPATIBLE_PROTOCOL_VERSION:
6433 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_INCOMPATIBLE_PROTOCOL);
6434 break;
6435 case ID_IP_RECENTLY_CONNECTED:
6436 pluginList[i]->OnFailedConnectionAttempt(packet, FCAR_IP_RECENTLY_CONNECTED);
6437 break;
6438 }
6439 }
6440 }
6441
6442 void RakPeer::FillIPList(void)
6443 {
6444 if (ipList[0]!=UNASSIGNED_SYSTEM_ADDRESS)
6445 return;
6446
6447 // Fill out ipList structure
6448 #if !defined(WINDOWS_STORE_RT)
6449 RakNetSocket2::GetMyIP( ipList );
6450 #endif
6451
6452 // Sort the addresses from lowest to highest
6453 int startingIdx = 0;
6454 while (startingIdx < MAXIMUM_NUMBER_OF_INTERNAL_IDS-1 && ipList[startingIdx] != UNASSIGNED_SYSTEM_ADDRESS)
6455 {
6456 int lowestIdx = startingIdx;
6457 for (int curIdx = startingIdx + 1; curIdx < MAXIMUM_NUMBER_OF_INTERNAL_IDS-1 && ipList[curIdx] != UNASSIGNED_SYSTEM_ADDRESS; curIdx++ )
6458 {
6459 if (ipList[curIdx] < ipList[startingIdx])
6460 {
6461 lowestIdx = curIdx;
6462 }
6463 }
6464 if (startingIdx != lowestIdx)
6465 {
6466 SystemAddress temp = ipList[startingIdx];
6467 ipList[startingIdx] = ipList[lowestIdx];
6468 ipList[lowestIdx] = temp;
6469 }
6470 ++startingIdx;
6471 }
6472 }
6473
6474
6475 // #if defined(RMO_NEW_UNDEF_ALLOCATING_QUEUE)
6476 // #pragma pop_macro("new")
6477 // #undef RMO_NEW_UNDEF_ALLOCATING_QUEUE
6478 // #endif
6479