SLikeNet  0.1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Router2.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-2018, 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 
17 #if _RAKNET_SUPPORT_Router2==1 && _RAKNET_SUPPORT_UDPForwarder==1
18 
19 #include "slikenet/Router2.h"
20 #include "slikenet/peerinterface.h"
21 #include "slikenet/BitStream.h"
22 #include "slikenet/time.h"
23 #include "slikenet/GetTime.h"
25 #include "slikenet/SocketLayer.h"
26 #include "slikenet/FormatString.h"
27 #include "slikenet/SocketDefines.h"
28 
29 using namespace SLNet;
30 
31 #ifndef INVALID_SOCKET
32 #define INVALID_SOCKET -1
33 #endif
34 
35 /*
36 Algorithm:
37 
38 1. Sender calls ConnectInternal(). A ConnnectRequest structure is allocated and stored in the connectionRequests list, containing a list of every system we are connected to. ID_ROUTER_2_QUERY_FORWARDING is sent to all connected systems.
39 
40 2. Upon the router getting ID_ROUTER_2_QUERY_FORWARDING, ID_ROUTER_2_REPLY_FORWARDING is sent to the sender indicating if that router is connected to the endpoint, along with the ping from the router to the endpoint.
41 
42 3. Upon the sender getting ID_ROUTER_2_REPLY_FORWARDING, the connection request structure is looked up in Router2::UpdateForwarding. The ping is stored in that structure. Once all systems have replied, the system continues to the next state. If every system in step 1 has been exhausted, and routing has occured at least once, then ID_CONNECTION_LOST is returned. If every system in step 1 has been exhausted and routing has never occured, then ID_ROUTER_2_FORWARDING_NO_PATH is returned. Otherwise, the router with the lowest ping is chosen, and RequestForwarding() is called with that system, which sends ID_ROUTER_2_REQUEST_FORWARDING to the router.
43 
44 4. When the router gets ID_ROUTER_2_REQUEST_FORWARDING, a MiniPunchRequest structure is allocated and stored in the miniPunchesInProgress list. The function SendOOBMessages() sends ID_ROUTER_2_REPLY_TO_SENDER_PORT from the routing sockets to both the sender and endpoint. It also sends ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT through the regular RakNet connection.
45 
46 5. The sender and endpoint should get ID_ROUTER_2_REPLY_TO_SENDER_PORT and/or ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT depending on what type of router they have. If ID_ROUTER_2_REPLY_TO_SENDER_PORT arrives, then this will reply back to the routing socket directly. If ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT arrives, then the reply port is modified to be the port specified by the router system. In both cases, ID_ROUTER_2_MINI_PUNCH_REPLY is sent. As the router has already setup the forwarding, ID_ROUTER_2_MINI_PUNCH_REPLY will actually arrive to the endpoint from the sender, and from the sender to the endpoint.
47 
48 6. When ID_ROUTER_2_MINI_PUNCH_REPLY arrives, ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE will be sent to the router. This is to tell the router that the forwarding has succeeded.
49 
50 7. When ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE arrives on the router, the router will find the two systems in the miniPunchesInProgress list, which was added in step 4 (See OnMiniPunchReplyBounce()). gotReplyFromSource or gotReplyFromEndpoint will be set to true, depending on the sender. When both gotReplyFromSource and gotReplyFromEndpoint have replied, then ID_ROUTER_2_REROUTE is sent to the endpoint, and ID_ROUTER_2_FORWARDING_ESTABLISHED is sent to the sender.
51 
52 8. When the endpoint gets ID_ROUTER_2_REROUTE, the system address is updated for the guid of the sender using RakPeer::ChangeSystemAddress(). This happens in OnRerouted().
53 
54 9. When the sender gets ID_ROUTER_2_FORWARDING_ESTABLISHED, then in OnForwardingSuccess() the endpoint is removed from the connectionRequest list and moved to the forwardedConnectionList.
55 
56 10. In OnClosedConnection(), for the sender, if the closed connection is the endpoint, then the endpoint is removed from the forwardedConnectionList (this is a graceful disconnect). If the connection was instead lost to the router, then ConnectInternal() gets called, which goes back to step 1. If instead this was a connection requset in progress, then UpdateForwarding() gets called, which goes back to step 3.
57 
58 11. When the user connects the endpoint and sender, then the sender will get ID_CONNECTION_REQUEST_ACCEPTED. The sender will look up the endpoint in the forwardedConnectionList, and send ID_ROUTER_2_INCREASE_TIMEOUT to the endpoint. This message will call SetTimeoutTime() on the endpoint, so that if the router disconnects, enough time is available for the reroute to complete.
59 */
60 
61 #define MIN_MINIPUNCH_TIMEOUT 5000
62 
63 
64 
65 
66 void Router2DebugInterface::ShowFailure(const char *message)
67 {
68  printf("%s", message);
69 }
70 void Router2DebugInterface::ShowDiagnostic(const char *message)
71 {
72  printf("%s", message);
73 }
74 
75 enum Router2MessageIdentifiers
76 {
77  ID_ROUTER_2_QUERY_FORWARDING,
78  ID_ROUTER_2_REPLY_FORWARDING,
79  ID_ROUTER_2_REQUEST_FORWARDING,
80  ID_ROUTER_2_INCREASE_TIMEOUT,
81 };
83 {
84 
85 }
87 {
88 
89 }
90 
92 
94 {
95  udpForwarder=0;
98  socketFamily=AF_INET;
99 }
101 {
102  ClearAll();
103 
104  if (udpForwarder)
105  {
108  }
109 }
110 void Router2::ClearMinipunches(void)
111 {
115 }
117 {
119  for (unsigned int i=0; i < connectionRequests.Size(); i++)
120  {
122  }
125 }
126 bool Router2::ConnectInternal(RakNetGUID endpointGuid, bool returnConnectionLostOnFailure)
127 {
128  int largestPing = GetLargestPingAmongConnectedSystems();
129  if (largestPing<0)
130  {
131  char buff[512];
132  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2: ConnectInternal(%I64d) failed at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
133 
134  // Not connected to anyone
135  return false;
136  }
137 
138  // ALready in progress?
140  if (GetConnectionRequestIndex(endpointGuid)!=(unsigned int)-1)
141  {
143  char buff[512];
144  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2: ConnectInternal(%I64d) failed at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
145 
146  return false;
147  }
149 
150  // StoreRequest(endpointGuid, Largest(ping*2), systemsSentTo). Set state REQUEST_STATE_QUERY_FORWARDING
151  Router2::ConnnectRequest *cr = SLNet::OP_NEW<Router2::ConnnectRequest>(_FILE_AND_LINE_);
154  rakPeerInterface->GetSystemList(addresses, guids);
155  if (guids.Size()==0)
156  {
157  char buff[512];
158  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i\n", _FILE_AND_LINE_));
159 
160  return false;
161  }
163  cr->pingTimeout= SLNet::GetTimeMS()+largestPing*2+1000;
164  cr->endpointGuid=endpointGuid;
165  cr->returnConnectionLostOnFailure=returnConnectionLostOnFailure;
166  for (unsigned int i=0; i < guids.Size(); i++)
167  {
168  ConnectionRequestSystem crs;
169  if (guids[i]!=endpointGuid)
170  {
171  crs.guid=guids[i];
172  crs.pingToEndpoint=-1;
176 
177  // Broadcast(ID_ROUTER_2_QUERY_FORWARDING, endpointGuid);
178  SLNet::BitStream bsOut;
180  bsOut.Write((unsigned char) ID_ROUTER_2_QUERY_FORWARDING);
181  bsOut.Write(endpointGuid);
182  uint32_t pack_id = rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,crs.guid,false);
183 
184  if (debugInterface)
185  {
186  char buff[512];
187  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Router2::ConnectInternal: at %s:%i, pack_id = %d", __FILE__, __LINE__,pack_id));
188  }
189 
190  }
191  else
192  {
193  if (debugInterface)
194  {
195  char buff[512];
196  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Router2::ConnectInternal: at %s:%i [else ..].: %I64d==%I64d", __FILE__, __LINE__,
197  guids[i].g,endpointGuid.g));
198  }
199  }
200  }
204 
205  if (debugInterface)
206  {
207  char buff[512];
208  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Broadcasting ID_ROUTER_2_QUERY_FORWARDING to %I64d at %s:%i\n", endpointGuid.g , __FILE__, __LINE__));
209  }
210 
211  return true;
212 }
213 void Router2::SetSocketFamily(unsigned short _socketFamily)
214 {
215  socketFamily=_socketFamily;
216 }
217 void Router2::EstablishRouting(RakNetGUID endpointGuid)
218 {
220  if (cs!=IS_DISCONNECTED && cs!=IS_NOT_CONNECTED)
221  {
222  char buff[512];
223  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i "
224  "(already connected to the %I64d)\n", __FILE__, __LINE__, endpointGuid.g ));
225  return;
226  }
227 
228  ConnectInternal(endpointGuid,false);
229 }
231 {
232  if (max>0 && maximumForwardingRequests<=0)
233  {
234  udpForwarder = SLNet::OP_NEW<UDPForwarder>(_FILE_AND_LINE_);
236  }
237  else if (max<=0 && maximumForwardingRequests>0)
238  {
241  udpForwarder=0;
242  }
243 
245 }
247 {
248  SystemAddress sa;
249  SLNet::BitStream bs(packet->data,packet->length,false);
250  if (packet->data[0]==ID_ROUTER_2_INTERNAL)
251  {
252  switch (packet->data[1])
253  {
254  case ID_ROUTER_2_QUERY_FORWARDING:
255  {
256  OnQueryForwarding(packet);
258  }
259  case ID_ROUTER_2_REPLY_FORWARDING:
260  {
261  OnQueryForwardingReply(packet);
263  }
264  case ID_ROUTER_2_REQUEST_FORWARDING:
265  {
266 
267  if (debugInterface)
268  {
269  char buff[512];
270  char buff2[32];
271  packet->systemAddress.ToString(true,buff2,static_cast<size_t>(32));
272  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REQUEST_FORWARDING on ip %s from %I64d, ",
273  buff2,packet->guid.g));
274  }
275 
276  OnRequestForwarding(packet);
278  }
279  case ID_ROUTER_2_INCREASE_TIMEOUT:
280  {
284  }
285  }
286  }
287  else if (packet->data[0]==ID_OUT_OF_BAND_INTERNAL && packet->length>=2)
288  {
289  switch (packet->data[1])
290  {
292  {
293  SLNet::BitStream bsOut;
294  bsOut.Write(packet->guid);
296 
297  if (debugInterface)
298  {
299  char buff[512];
300  char buff2[32];
301  sa.ToString(false,buff2,static_cast<size_t>(32));
302  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_TO_SENDER_PORT %i on address %s, replying with ID_ROUTER_2_MINI_PUNCH_REPLY at %s:%i\n", sa.GetPort(), buff2, _FILE_AND_LINE_));
303 
304 // packet->systemAddress.ToString(true,buff2);
305 // debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_TO_SENDER_PORT on address %s (%I64d), "
306 // "replying with ID_ROUTER_2_MINI_PUNCH_REPLY at %s:%i\n", buff2,packet->guid.g, __FILE__, __LINE__));
307  }
308 
310  }
312  {
313  SLNet::BitStream bsOut;
314  bsOut.Write(packet->guid);
315  bs.IgnoreBytes(2);
316  sa=packet->systemAddress;
317  unsigned short port;
318  bs.Read(port);
319  sa.SetPortHostOrder(port);
320  RakAssert(sa.GetPort()!=0);
322 
323  if (debugInterface)
324  {
325  char buff[512];
326  char buff2[32];
327  sa.ToString(false,buff2,static_cast<size_t>(32));
328  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT %i on address %s, "
329  "replying with ID_ROUTER_2_MINI_PUNCH_REPLY at %s:%i\n", sa.GetPort(), buff2, __FILE__, __LINE__));
330  }
331 
333  }
335  OnMiniPunchReply(packet);
338  OnMiniPunchReplyBounce(packet);
340  }
341  }
342  else if (packet->data[0]==ID_ROUTER_2_FORWARDING_ESTABLISHED)
343  {
344 // printf("Got ID_ROUTER_2_FORWARDING_ESTABLISHED\n");
345  if (OnForwardingSuccess(packet)==false)
347  }
348  else if (packet->data[0]==ID_ROUTER_2_REROUTED)
349  {
350  OnRerouted(packet);
351  }
352  else if (packet->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)
353  {
354  unsigned int forwardingIndex;
356  for (forwardingIndex=0; forwardingIndex < forwardedConnectionList.Size(); forwardingIndex++)
357  {
358  if (forwardedConnectionList[forwardingIndex].endpointGuid==packet->guid && forwardedConnectionList[forwardingIndex].weInitiatedForwarding)
359  break;
360  }
361 
362  if (forwardingIndex<forwardedConnectionList.Size())
363  {
365 
366  // We connected to this system through a forwarding system
367  // Have the endpoint take longer to drop us, in case the intermediary system drops
368  SLNet::BitStream bsOut;
369  bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
370  bsOut.Write((unsigned char) ID_ROUTER_2_INCREASE_TIMEOUT);
371  rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE,0,packet->guid,false);
372 
373  if (debugInterface)
374  {
375  char buff[512];
376  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_CONNECTION_REQUEST_ACCEPTED, "
377  "sending ID_ROUTER_2_INCREASE_TIMEOUT to the %I64d at %s:%i\n", packet->guid.g, __FILE__, __LINE__));
378  }
379 
380  // Also take longer ourselves
382  }
383  else {
384  // ~Gwynn: Fix for Receive hanging up problem on Windows XP
385  // See http://blog.delphi-jedi.net/2008/04/23/the-case-of-the-unexplained-dead-lock-in-a-single-thread/ for details
387  }
388  }
389  else if (packet->data[0]==ID_ROUTER_2_FORWARDING_NO_PATH)
390  {
391  if (packet->wasGeneratedLocally==false)
393  }
394 
395  return RR_CONTINUE_PROCESSING;
396 }
397 void Router2::Update(void)
398 {
399  SLNet::TimeMS curTime = SLNet::GetTimeMS();
400  unsigned int connectionRequestIndex=0;
402  while (connectionRequestIndex < connectionRequests.Size())
403  {
404  ConnnectRequest* connectionRequest = connectionRequests[connectionRequestIndex];
405 
406  // pingTimeout is only used with R2RS_REQUEST_STATE_QUERY_FORWARDING
407  if (connectionRequest->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING &&
408  connectionRequest->pingTimeout < curTime)
409  {
410  bool anyRemoved=false;
411  unsigned int connectionRequestGuidIndex=0;
412  connectionRequest->connectionRequestSystemsMutex.Lock();
413  while (connectionRequestGuidIndex < connectionRequest->connectionRequestSystems.Size())
414  {
415  if (connectionRequest->connectionRequestSystems[connectionRequestGuidIndex].pingToEndpoint<0)
416  {
417  anyRemoved=true;
418  connectionRequest->connectionRequestSystems.RemoveAtIndexFast(connectionRequestGuidIndex);
419  }
420  else
421  {
422  connectionRequestGuidIndex++;
423  }
424  }
425  connectionRequest->connectionRequestSystemsMutex.Unlock();
426 
427  if (anyRemoved)
428  {
429  if (connectionRequestIndex!=(unsigned int)-1)
430  {
431  // connectionRequestsMutex should be locked before calling this function
432  if (UpdateForwarding(connectionRequest)==false)
433  {
434  RemoveConnectionRequest(connectionRequestIndex);
435  }
436  else
437  {
438  connectionRequestIndex++;
439  }
440  }
441  else
442  {
443  connectionRequestIndex++;
444  }
445  }
446  else
447  {
448  connectionRequestIndex++;
449  }
450  }
451  else
452  {
453  connectionRequestIndex++;
454  }
455  }
457 
458  unsigned int i=0;
460  while (i < miniPunchesInProgress.Size())
461  {
462  if (miniPunchesInProgress[i].timeout<curTime)
463  {
466  }
467  else if (curTime>miniPunchesInProgress[i].nextAction)
468  {
469  miniPunchesInProgress[i].nextAction=curTime+100;
471  }
472  else
473  i++;
474  }
476 
477 }
478 void Router2::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
479 {
480  (void) lostConnectionReason;
481  (void) systemAddress;
482 
483 
484  unsigned int forwardedConnectionIndex=0;
486  while (forwardedConnectionIndex<forwardedConnectionList.Size())
487  {
488  if (forwardedConnectionList[forwardedConnectionIndex].endpointGuid==rakNetGUID)
489  {
490  if (debugInterface)
491  {
492  char buff[512];
493  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Closed connection to the %I64d, removing forwarding from list at %s:%i\n", rakNetGUID.g, __FILE__, __LINE__));
494  }
495 
496  // No longer need forwarding
497  forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
498  }
499  else if (forwardedConnectionList[forwardedConnectionIndex].intermediaryGuid==rakNetGUID && forwardedConnectionList[forwardedConnectionIndex].weInitiatedForwarding)
500  {
501  // Lost connection to intermediary. Restart process to connect to endpoint. If failed, push ID_CONNECTION_LOST. Also remove connection request if it already is in the list, to restart it
503  unsigned int pos = GetConnectionRequestIndex(forwardedConnectionList[forwardedConnectionIndex].endpointGuid);
504  if((unsigned int)-1 != pos) { SLNet::OP_DELETE(connectionRequests[pos], __FILE__, __LINE__); connectionRequests.RemoveAtIndexFast(pos);}
506 
507  ConnectInternal(forwardedConnectionList[forwardedConnectionIndex].endpointGuid, true);
508 
509  forwardedConnectionIndex++;
510 
511  if (debugInterface)
512  {
513  char buff[512];
514  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Closed connection %I64d, restarting forwarding at %s:%i\n",rakNetGUID.g, __FILE__, __LINE__));
515  }
516 
517  // This should not be removed - the connection is still forwarded, but perhaps through another system
518 // forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
519  }
520  else
521  forwardedConnectionIndex++;
522  }
524 
525  unsigned int connectionRequestIndex=0;
527  while (connectionRequestIndex < connectionRequests.Size())
528  {
529  ConnnectRequest *cr = connectionRequests[connectionRequestIndex];
530  cr->connectionRequestSystemsMutex.Lock();
531  unsigned int connectionRequestGuidIndex = cr->GetGuidIndex(rakNetGUID);
532  if (connectionRequestGuidIndex!=(unsigned int)-1)
533  {
534  cr->connectionRequestSystems.RemoveAtIndexFast(connectionRequestGuidIndex);
535  cr->connectionRequestSystemsMutex.Unlock();
536  if (UpdateForwarding(cr)==false) // If returns false, no connection request systems left
537  {
538  if (debugInterface)
539  {
540  char buff[512];
541  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Aborted connection to the %I64d, aborted forwarding at %s:%i\n", rakNetGUID.g, __FILE__, __LINE__));
542  }
543 
544  RemoveConnectionRequest(connectionRequestIndex);
545  }
546  else // Else a system in the connection request list dropped. If cr->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING then we are still waiting for other systems to respond.
547  {
548  if (debugInterface)
549  {
550  char buff[512];
551  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Aborted connection attempt to %I64d, restarting forwarding to %I64d at %s:%i\n", rakNetGUID.g,cr->endpointGuid.g,__FILE__, __LINE__));
552  }
553 // if(volatile bool is_my_fix_a_truth = true) { // A system in the list of potential systems to try routing to dropped. There is no need to restart the whole process.
554 // connectionRequestsMutex.Lock();
555 // connectionRequests.RemoveAtIndexFast(connectionRequestIndex);
556 // connectionRequestsMutex.Unlock();
557 //
558 // if(false == ConnectInternal(cr->endpointGuid,cr->returnConnectionLostOnFailure))
559 // if (debugInterface)
560 // {
561 // char buff[512];
562 // debugInterface->ShowDiagnostic(FormatStringTS(buff,"ConnectInternal(cr->endpointGuid,cr->returnConnectionLostOnFailure) is false. at %s:%i\n", __FILE__, __LINE__));
563 // }
564 // }
565 
566  connectionRequestIndex++;
567  }
568  }
569  else
570  {
571  cr->connectionRequestSystemsMutex.Unlock();
572  connectionRequestIndex++;
573  }
574  }
576 
577 
578  unsigned int i=0;
580  while (i < miniPunchesInProgress.Size())
581  {
582  if (miniPunchesInProgress[i].sourceGuid==rakNetGUID || miniPunchesInProgress[i].endpointGuid==rakNetGUID)
583  {
584  if (miniPunchesInProgress[i].sourceGuid!=rakNetGUID)
585  {
587  }
589  }
590  else
591  i++;
592  }
594 }
595 void Router2::OnFailedConnectionAttempt(Packet *packet, PI2_FailedConnectionAttemptReason failedConnectionAttemptReason)
596 {
597  (void) failedConnectionAttemptReason;
598  (void) packet;
599 
600  unsigned int forwardedConnectionIndex=0;
602  while (forwardedConnectionIndex<forwardedConnectionList.Size())
603  {
604  if (forwardedConnectionList[forwardedConnectionIndex].intermediaryAddress==packet->systemAddress)
605  {
606  if (debugInterface)
607  {
608  char buff[512];
609  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Failed connection attempt to forwarded system (%I64d : %s) at %s:%i\n",
610  forwardedConnectionList[forwardedConnectionIndex].endpointGuid.g, packet->systemAddress.ToString(true), __FILE__, __LINE__));
611  }
612 
613  packet->guid=forwardedConnectionList[forwardedConnectionIndex].endpointGuid;
614  forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
615  }
616  else
617  forwardedConnectionIndex++;
618  }
620 }
622 {
623  ClearAll();
624 }
625 // connectionRequestsMutex should already be locked
626 bool Router2::UpdateForwarding(ConnnectRequest* connectionRequest)
627 {
628  connectionRequest->connectionRequestSystemsMutex.Lock();
629 
630  // RAKNET_DEBUG_PRINTF(__FUNCTION__": connectionRequest->connectionRequestSystems.Size = %d", connectionRequest->connectionRequestSystems.Size());
631 
632  if (connectionRequest->connectionRequestSystems.Size()==0)
633  {
634  connectionRequest->connectionRequestSystemsMutex.Unlock();
635 
636  // printf("Router2 failed at %s:%i\n", __FILE__, __LINE__);
637  if (connectionRequest->returnConnectionLostOnFailure) {
638  ReturnToUser(ID_CONNECTION_LOST, connectionRequest->endpointGuid, UNASSIGNED_SYSTEM_ADDRESS, true); // This is a connection which was previously established. Rerouting is not possible.
639 // bool sendDisconnectionNotification = false;
640 // rakPeerInterface->CloseConnection(rakPeerInterface->GetSystemAddressFromGuid(connectionRequest->endpointGuid), sendDisconnectionNotification);
641 // RAKNET_DEBUG_PRINTF(__FUNCTION__": call rakPeerInterface->CloseConnection(%I64d)" , connectionRequest->endpointGuid.g);
642  }
643  else
644  ReturnToUser(ID_ROUTER_2_FORWARDING_NO_PATH, connectionRequest->endpointGuid, UNASSIGNED_SYSTEM_ADDRESS, false);
645 
646  if (debugInterface)
647  {
648  char buff[512];
649  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Forwarding failed, no remaining systems at %s:%i\n", _FILE_AND_LINE_));
650  }
651 
653 
654  for (unsigned int forwardedConnectionIndex=0; forwardedConnectionIndex < forwardedConnectionList.Size(); forwardedConnectionIndex++)
655  {
656  if (forwardedConnectionList[forwardedConnectionIndex].endpointGuid==connectionRequest->endpointGuid && forwardedConnectionList[forwardedConnectionIndex].weInitiatedForwarding)
657  {
658  forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
659  break;
660  }
661  }
663 
664  return false;
665  }
666  connectionRequest->connectionRequestSystemsMutex.Unlock();
667 
668  if (connectionRequest->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING)
669  {
670  connectionRequest->connectionRequestSystemsMutex.Lock();
671 
672  for (unsigned int i=0; i < connectionRequest->connectionRequestSystems.Size(); i++)
673  {
674  if (connectionRequest->connectionRequestSystems[i].pingToEndpoint<0)
675  {
676  connectionRequest->connectionRequestSystemsMutex.Unlock();
677  return true; // Forward query still in progress, just return
678  }
679  }
680  connectionRequest->connectionRequestSystemsMutex.Unlock();
681 
682  RequestForwarding(connectionRequest);
683  }
684 // else if (connectionRequest->requestState==REQUEST_STATE_REQUEST_FORWARDING)
685 // {
686 // RequestForwarding(connectionRequestIndex);
687 // }
688 
689  return true;
690 }
691 // connectionRequestsMutex should already be locked
692 void Router2::RemoveConnectionRequest(unsigned int connectionRequestIndex)
693 {
694  SLNet::OP_DELETE(connectionRequests[connectionRequestIndex],_FILE_AND_LINE_);
695  connectionRequests.RemoveAtIndexFast(connectionRequestIndex);
696 }
697 int ConnectionRequestSystemComp( const Router2::ConnectionRequestSystem & key, const Router2::ConnectionRequestSystem &data )
698 {
699  if (key.pingToEndpoint * (key.usedForwardingEntries+1) < data.pingToEndpoint * (data.usedForwardingEntries+1))
700  return -1;
701  if (key.pingToEndpoint * (key.usedForwardingEntries+1) == data.pingToEndpoint * (data.usedForwardingEntries+1))
702  return 1;
703  if (key.guid < data.guid)
704  return -1;
705  if (key.guid > data.guid)
706  return -1;
707  return 0;
708 }
709 // connectionRequestsMutex should already be locked
710 void Router2::RequestForwarding(ConnnectRequest* connectionRequest)
711 {
712  RakAssert(connectionRequest->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING);
713  connectionRequest->requestState=REQUEST_STATE_REQUEST_FORWARDING;
714 
715  if (connectionRequest->GetGuidIndex(connectionRequest->lastRequestedForwardingSystem)!=(unsigned int)-1)
716  {
717  char buff[512];
718  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i\n", _FILE_AND_LINE_));
719  return;
720  }
721 
722  // Prioritize systems to request forwarding
724  unsigned int connectionRequestGuidIndex;
725  connectionRequest->connectionRequestSystemsMutex.Lock();
726  for (connectionRequestGuidIndex=0; connectionRequestGuidIndex < connectionRequest->connectionRequestSystems.Size(); connectionRequestGuidIndex++)
727  {
728  RakAssert(connectionRequest->connectionRequestSystems[connectionRequestGuidIndex].pingToEndpoint>=0);
729  commandList.Insert(connectionRequest->connectionRequestSystems[connectionRequestGuidIndex],
730  connectionRequest->connectionRequestSystems[connectionRequestGuidIndex],
731  true,
733  }
734  connectionRequest->connectionRequestSystemsMutex.Unlock();
735 
736  connectionRequest->lastRequestedForwardingSystem=commandList[0].guid;
737 
738  SLNet::BitStream bsOut;
739  bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
740  bsOut.Write((unsigned char) ID_ROUTER_2_REQUEST_FORWARDING);
741  bsOut.Write(connectionRequest->endpointGuid);
742  rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,connectionRequest->lastRequestedForwardingSystem,false);
743 
744  if (debugInterface)
745  {
746  char buff[512];
747  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_REQUEST_FORWARDING "
748  "(connectionRequest->lastRequestedForwardingSystem = %I64d, connectionRequest->endpointGuid = %I64d) at %s:%i\n",
749  connectionRequest->lastRequestedForwardingSystem.g,connectionRequest->endpointGuid.g, __FILE__, __LINE__));
750  }
751 }
752 void Router2::SendFailureOnCannotForward(RakNetGUID sourceGuid, RakNetGUID endpointGuid)
753 {
754  SLNet::BitStream bsOut;
755  bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
756  bsOut.Write((unsigned char) ID_ROUTER_2_REPLY_FORWARDING);
757  bsOut.Write(endpointGuid);
758  bsOut.Write(false);
759  rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,sourceGuid,false);
760 }
761 int Router2::ReturnFailureOnCannotForward(RakNetGUID sourceGuid, RakNetGUID endpointGuid)
762 {
763  // If the number of systems we are currently forwarding>=maxForwarding, return ID_ROUTER_2_REPLY_FORWARDING,endpointGuid,false
765  {
766  char buff[512];
767  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d -> %I64d) at %s:%i\n",
768  sourceGuid.g, endpointGuid.g,__FILE__, __LINE__));
769  SendFailureOnCannotForward(sourceGuid,endpointGuid);
770  return -1;
771  }
772 
773  // We cannot forward connections which are themselves forwarded. Return fail in that case
775  for (unsigned int i=0; i < forwardedConnectionList.Size(); i++)
776  {
777  if ((forwardedConnectionList[i].endpointGuid==endpointGuid)
778  || (forwardedConnectionList[i].endpointGuid==sourceGuid)) // sourceGuid is here so you do not respond to routing requests from systems you are already routing through.
779  {
781 
782  char buff[512];
783  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i\n", __FILE__, __LINE__));
784  SendFailureOnCannotForward(sourceGuid,endpointGuid);
785  return -1;
786  }
787  }
789 
790  int pingToEndpoint;
791  pingToEndpoint = rakPeerInterface->GetAveragePing(endpointGuid);
792  if (pingToEndpoint==-1)
793  {
794  char buff[512];
795  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d -> %I64d) at %s:%i\n",
796  sourceGuid.g, endpointGuid.g,__FILE__, __LINE__));
797 
798  SendFailureOnCannotForward(sourceGuid,endpointGuid);
799  return -1;
800  }
801  return pingToEndpoint;
802 }
804 {
805  SLNet::BitStream bs(packet->data, packet->length, false);
806  bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
807  RakNetGUID endpointGuid;
808  // Read endpointGuid
809  bs.Read(endpointGuid);
810 
811  int pingToEndpoint = ReturnFailureOnCannotForward(packet->guid, endpointGuid);
812  if (pingToEndpoint==-1)
813  {
814  char buff[512];
815  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d) at %s:%i\n", packet->guid.g, __FILE__, __LINE__));
816  return;
817  }
818 
819  // If we are connected to endpointGuid, reply ID_ROUTER_2_REPLY_FORWARDING,endpointGuid,true,ping,numCurrentlyForwarding
820  SLNet::BitStream bsOut;
821  bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
822  bsOut.Write((unsigned char) ID_ROUTER_2_REPLY_FORWARDING);
823  bsOut.Write(endpointGuid);
824  bsOut.Write(true);
825  bsOut.Write((unsigned short) pingToEndpoint);
826  bsOut.Write((unsigned short) udpForwarder->GetUsedForwardEntries()/2);
827  rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false);
828 
829  if (debugInterface)
830  {
831  char buff[512];
832  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_REPLY_FORWARDING to the %I64d at %s:%i\n", packet->guid.g, __FILE__, __LINE__));
833  }
834 }
836 {
837  SLNet::BitStream bs(packet->data, packet->length, false);
838  bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
839  RakNetGUID endpointGuid;
840  bs.Read(endpointGuid);
841  // Find endpointGuid among stored requests
842  bool canForward=false;
843  bs.Read(canForward);
844 
845 
847  unsigned int connectionRequestIndex = GetConnectionRequestIndex(endpointGuid);
848  if (connectionRequestIndex==(unsigned int)-1)
849  {
851  char buff[512];
852  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d) at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
853  return;
854  }
855 
856  connectionRequests[connectionRequestIndex]->connectionRequestSystemsMutex.Lock();
857  unsigned int connectionRequestGuidIndex = connectionRequests[connectionRequestIndex]->GetGuidIndex(packet->guid);
858  if (connectionRequestGuidIndex==(unsigned int)-1)
859  {
860  connectionRequests[connectionRequestIndex]->connectionRequestSystemsMutex.Unlock();
862  char buff[512];
863  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d) at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
864  return;
865  }
866 
867  if (debugInterface)
868  {
869  char buff[512];
870  char buff2[512];
871  packet->systemAddress.ToString(true,buff2,static_cast<size_t>(512));
872  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_FORWARDING on address %s(%I64d -> %I64d) canForward=%i at %s:%i\n",
873  buff2, packet->guid.g, endpointGuid.g, canForward, __FILE__, __LINE__));
874  }
875 
876  if (canForward)
877  {
878  unsigned short pingToEndpoint;
879  unsigned short usedEntries;
880  bs.Read(pingToEndpoint);
881  bs.Read(usedEntries);
882  connectionRequests[connectionRequestIndex]->connectionRequestSystems[connectionRequestGuidIndex].usedForwardingEntries=usedEntries;
883  connectionRequests[connectionRequestIndex]->connectionRequestSystems[connectionRequestGuidIndex].pingToEndpoint=rakPeerInterface->GetAveragePing(packet->guid)+pingToEndpoint;
884  }
885  else
886  {
887  connectionRequests[connectionRequestIndex]->connectionRequestSystems.RemoveAtIndex(connectionRequestGuidIndex);
888  }
889  connectionRequests[connectionRequestIndex]->connectionRequestSystemsMutex.Unlock();
890 
891  if (UpdateForwarding(connectionRequests[connectionRequestIndex])==false)
892  {
893  RemoveConnectionRequest(connectionRequestIndex);
894  }
896 }
897 void Router2::SendForwardingSuccess(MessageID messageId, RakNetGUID sourceGuid, RakNetGUID endpointGuid, unsigned short sourceToDstPort)
898 {
899  SLNet::BitStream bsOut;
900  bsOut.Write(messageId);
901  bsOut.Write(endpointGuid);
902  bsOut.Write(sourceToDstPort);
903  rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,sourceGuid,false);
904 
905  if (debugInterface)
906  {
907  char buff[512];
908  if (messageId==ID_ROUTER_2_FORWARDING_ESTABLISHED)
909  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_FORWARDING_ESTABLISHED at %s:%i\n", _FILE_AND_LINE_ ));
910  else
911  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_REROUTED at %s:%i\n", _FILE_AND_LINE_ ));
912  }
913 }
915 {
916  SLNet::BitStream oobBs;
917  oobBs.Write((unsigned char)oob);
918  if (extraData)
919  {
920  extraData->ResetReadPointer();
921  oobBs.Write(*extraData);
922  }
923  char ipAddressString[32];
924  sa.ToString(false, ipAddressString,static_cast<size_t>(32));
925  rakPeerInterface->SendOutOfBand((const char*) ipAddressString,sa.GetPort(),(const char*) oobBs.GetData(),oobBs.GetNumberOfBytesUsed());
926 }
928 {
929  SLNet::BitStream bs;
931  bs.Write((unsigned char) oob);
932  // SocketLayer::SendTo_PC( socket, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), sa, __FILE__, __LINE__ );
933 
934 
935  if (sa.address.addr4.sin_family==AF_INET)
936  {
937  sendto__( socket, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), 0, ( const sockaddr* ) & sa.address.addr4, sizeof( sockaddr_in ) );
938  }
939  else
940  {
941  #if RAKNET_SUPPORT_IPV6==1
942  sendto__( socket, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), 0, ( const sockaddr* ) & sa.address.addr6, sizeof( sockaddr_in6 ) );
943  #endif
944  }
945 
946 
947 
948 
949 
950 
951 
952 
953 
954 
955 
956 
957 }
959 {
960  // Mini NAT punch
961  // Send from srcToDestPort to packet->systemAddress (source). If the message arrives, the remote system should reply.
963 
964  // Send from destToSourcePort to endpointSystemAddress (destination). If the message arrives, the remote system should reply.
966 
967 
968  if (debugInterface) {
969  char buff [512];
970 
971  char buff2[128];
972 
973  mpr->sourceAddress .ToString(true,buff2,static_cast<size_t>(128));
974 
975  debugInterface->ShowDiagnostic(FormatStringTS(buff,"call SendOOBFromSpecifiedSocket(...,%s,...)", buff2));
976 
977  mpr->endpointAddress .ToString(true,buff2,static_cast<size_t>(128));
978 
979  debugInterface->ShowDiagnostic(FormatStringTS(buff,"call SendOOBFromSpecifiedSocket(...,%s,...)", buff2));
980  }
981 
982  // Tell source to send to forwardingPort
983  SLNet::BitStream extraData;
984  extraData.Write(mpr->forwardingPort);
985  RakAssert(mpr->forwardingPort!=0);
987 
988  // Tell destination to send to forwardingPort
989  extraData.Reset();
990  extraData.Write(mpr->forwardingPort);
993 }
995 {
996  SLNet::BitStream bs(packet->data, packet->length, false);
997  bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
998  RakNetGUID endpointGuid;
999  bs.Read(endpointGuid);
1000 
1001  int pingToEndpoint = ReturnFailureOnCannotForward(packet->guid, endpointGuid);
1002  if (pingToEndpoint==-1)
1003  {
1004  char buff[512];
1005  if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (packet->guid =%I64d, endpointGuid = %I64d) at %s:%i\n",
1006  packet->guid.g, endpointGuid.g, __FILE__, __LINE__));
1007  return;
1008  }
1009 
1010  unsigned short forwardingPort=0;
1011  __UDPSOCKET__ forwardingSocket=INVALID_SOCKET;
1012  SystemAddress endpointSystemAddress = rakPeerInterface->GetSystemAddressFromGuid(endpointGuid);
1014  packet->systemAddress, endpointSystemAddress, 30000, 0, socketFamily,
1015  &forwardingPort, &forwardingSocket);
1016 
1018  {
1019  if (debugInterface)
1020  {
1021  char buff[512];
1022  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REQUEST_FORWARDING, result=UDPFORWARDER_FORWARDING_ALREADY_EXISTS "
1023  "(packet->guid =%I64d, endpointGuid = %I64d) at %s:%i\n",
1024  packet->guid.g, endpointGuid.g,__FILE__, __LINE__));
1025  }
1026 
1027  SendForwardingSuccess(ID_ROUTER_2_FORWARDING_ESTABLISHED, packet->guid, endpointGuid, forwardingPort);
1028  }
1029  else if (result==UDPFORWARDER_NO_SOCKETS)
1030  {
1031  char buff[512];
1032  char buff2[64];
1033  char buff3[64];
1034  packet->systemAddress.ToString(true,buff2,static_cast<size_t>(64));
1035  endpointSystemAddress.ToString(true,buff3,static_cast<size_t>(64));
1036  if (debugInterface)
1037  debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i with UDPFORWARDER_NO_SOCKETS, packet->systemAddress=%s, endpointSystemAddress=%s, forwardingPort=%i, forwardingSocket=%i\n",
1038  __FILE__, __LINE__, buff2, buff3, forwardingPort, forwardingSocket));
1039  SendFailureOnCannotForward(packet->guid, endpointGuid);
1040  }
1041  else if (result==UDPFORWARDER_INVALID_PARAMETERS)
1042  {
1043  char buff[512];
1044  char buff2[64];
1045  char buff3[64];
1046  packet->systemAddress.ToString(true,buff2,static_cast<size_t>(64));
1047  endpointSystemAddress.ToString(true,buff3,static_cast<size_t>(64));
1048  if (debugInterface)
1049  debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i with UDPFORWARDER_INVALID_PARAMETERS, packet->systemAddress=%s, endpointSystemAddress=%s, forwardingPort=%i, forwardingSocket=%i\n",
1050  __FILE__, __LINE__, buff2, buff3, forwardingPort, forwardingSocket));
1051  SendFailureOnCannotForward(packet->guid, endpointGuid);
1052  }
1053  else if (result==UDPFORWARDER_BIND_FAILED)
1054  {
1055  char buff[512];
1056  char buff2[64];
1057  char buff3[64];
1058  packet->systemAddress.ToString(true,buff2,static_cast<size_t>(64));
1059  endpointSystemAddress.ToString(true,buff3,static_cast<size_t>(64));
1060  if (debugInterface)
1061  debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i with UDPFORWARDER_BIND_FAILED, packet->systemAddress=%s, endpointSystemAddress=%s, forwardingPort=%i, forwardingSocket=%i\n",
1062  __FILE__, __LINE__, buff2, buff3, forwardingPort, forwardingSocket));
1063  SendFailureOnCannotForward(packet->guid, endpointGuid);
1064  }
1065  else
1066  {
1067  if (debugInterface)
1068  {
1069  char buff2[32];
1070  char buff3[32];
1071  endpointSystemAddress.ToString(true,buff2,static_cast<size_t>(32));
1072  packet->systemAddress.ToString(true,buff3,static_cast<size_t>(32));
1073  char buff[512];
1074  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REQUEST_FORWARDING.\n"
1075  "endpointAddress=%s\nsourceAddress=%s\nforwardingPort=%i\n "
1076  "calling SendOOBMessages at %s:%i\n", buff2,buff3,forwardingPort,_FILE_AND_LINE_));
1077  }
1078 
1079  // Store the punch request
1080  MiniPunchRequest miniPunchRequest;
1081  miniPunchRequest.endpointAddress=endpointSystemAddress;
1082  miniPunchRequest.endpointGuid=endpointGuid;
1083  miniPunchRequest.gotReplyFromEndpoint=false;
1084  miniPunchRequest.gotReplyFromSource=false;
1085  miniPunchRequest.sourceGuid=packet->guid;
1086  miniPunchRequest.sourceAddress=packet->systemAddress;
1087  miniPunchRequest.forwardingPort=forwardingPort;
1088  miniPunchRequest.forwardingSocket=forwardingSocket;
1089  int ping1 = rakPeerInterface->GetAveragePing(packet->guid);
1090  int ping2 = rakPeerInterface->GetAveragePing(endpointGuid);
1091  if (ping1>ping2)
1092  miniPunchRequest.timeout= SLNet::GetTimeMS() + ping1*8+300;
1093  else
1094  miniPunchRequest.timeout= SLNet::GetTimeMS() + ping2*8+300;
1095  miniPunchRequest.nextAction= SLNet::GetTimeMS()+100;
1096  SendOOBMessages(&miniPunchRequest);
1098  miniPunchesInProgress.Push(miniPunchRequest,_FILE_AND_LINE_);
1100  }
1101 }
1103 {
1104  // Find stored punch request
1105  unsigned int i=0;
1106 
1107  if (debugInterface)
1108  {
1109  char buff[512];
1110  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE from guid=%I64d (miniPunchesInProgress.Size() = %d)",
1111  packet->guid.g, miniPunchesInProgress.Size()));
1112  }
1113 
1115  while (i < miniPunchesInProgress.Size())
1116  {
1117  if (miniPunchesInProgress[i].sourceGuid==packet->guid || miniPunchesInProgress[i].endpointGuid==packet->guid)
1118  {
1119  if (miniPunchesInProgress[i].sourceGuid==packet->guid)
1120  miniPunchesInProgress[i].gotReplyFromSource=true;
1121  if (miniPunchesInProgress[i].endpointGuid==packet->guid)
1122  miniPunchesInProgress[i].gotReplyFromEndpoint=true;
1123 
1124  if (debugInterface)
1125  {
1126  char buff[512];
1127  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Processing ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE, gotReplyFromSource=%i gotReplyFromEndpoint=%i at %s:%i\n", miniPunchesInProgress[i].gotReplyFromSource, miniPunchesInProgress[i].gotReplyFromEndpoint, __FILE__, __LINE__));
1128  }
1129 
1130  if (miniPunchesInProgress[i].gotReplyFromEndpoint==true &&
1131  miniPunchesInProgress[i].gotReplyFromSource==true)
1132  {
1136  }
1137  else
1138  {
1139  i++;
1140  }
1141  }
1142  else
1143  i++;
1144  }
1146 }
1147 void Router2::OnMiniPunchReply(Packet *packet)
1148 {
1149  SLNet::BitStream bs(packet->data, packet->length, false);
1150  bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
1151  RakNetGUID routerGuid;
1152  bs.Read(routerGuid);
1154 
1155  if (debugInterface)
1156  {
1157  char buff[512];
1158 
1159  char buff2[512];
1160 
1161  rakPeerInterface->GetSystemAddressFromGuid(routerGuid).ToString(true,buff2,static_cast<size_t>(512));
1162 
1163  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE (%s) at %s:%i\n", buff2, __FILE__, __LINE__));
1164  }
1165 }
1166 void Router2::OnRerouted(Packet *packet)
1167 {
1168  SLNet::BitStream bs(packet->data, packet->length, false);
1169  bs.IgnoreBytes(sizeof(MessageID));
1170  RakNetGUID endpointGuid;
1171  bs.Read(endpointGuid);
1172  unsigned short sourceToDestPort;
1173  bs.Read(sourceToDestPort);
1174 
1175  // Return rerouted notice
1176  SystemAddress intermediaryAddress=packet->systemAddress;
1177  intermediaryAddress.SetPortHostOrder(sourceToDestPort);
1178  rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
1179 
1180  unsigned int forwardingIndex;
1182  for (forwardingIndex=0; forwardingIndex < forwardedConnectionList.Size(); forwardingIndex++)
1183  {
1184  if (forwardedConnectionList[forwardingIndex].endpointGuid==endpointGuid)
1185  break;
1186  }
1187 
1188  if (forwardingIndex<forwardedConnectionList.Size())
1189  {
1190  ForwardedConnection& ref_fc = forwardedConnectionList[forwardingIndex];
1192 
1193  ref_fc.intermediaryAddress = packet->systemAddress;
1194  ref_fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
1195  ref_fc.intermediaryGuid = packet->guid;
1196 
1197  rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
1198 
1199  if (debugInterface)
1200  {
1201  char buff[512];
1202  debugInterface->ShowDiagnostic(FormatStringTS(buff,"FIX: Got ID_ROUTER_2_REROUTE, returning ID_ROUTER_2_REROUTED,"
1203  " Calling RakPeer::ChangeSystemAddress(%I64d, %s) at %s:%i\n",endpointGuid.g, intermediaryAddress.ToString(true), __FILE__, __LINE__));
1204  }
1205  }
1206  else
1207  {
1208  ForwardedConnection fc;
1209  fc.endpointGuid=endpointGuid;
1210  fc.intermediaryAddress=packet->systemAddress;
1211  fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
1212  fc.intermediaryGuid=packet->guid;
1213  fc.weInitiatedForwarding=false;
1214  // add to forwarding list. This is only here to avoid reporting direct connections in Router2::ReturnFailureOnCannotForward
1215  forwardedConnectionList.Push (fc,__FILE__, __LINE__);
1217 
1218  rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
1219 
1220  if (debugInterface)
1221  {
1222  char buff[512];
1223  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REROUTE, returning ID_ROUTER_2_REROUTED, Calling RakPeer::ChangeSystemAddress at %s:%i\n", __FILE__, __LINE__));
1224  }
1225  }
1226 
1227 }
1229 {
1230  SLNet::BitStream bs(packet->data, packet->length, false);
1231  bs.IgnoreBytes(sizeof(MessageID));
1232  RakNetGUID endpointGuid;
1233  bs.Read(endpointGuid);
1234  unsigned short sourceToDestPort;
1235  bs.Read(sourceToDestPort);
1236 
1237  unsigned int forwardingIndex;
1239  for (forwardingIndex=0; forwardingIndex < forwardedConnectionList.Size(); forwardingIndex++)
1240  {
1241  if (forwardedConnectionList[forwardingIndex].endpointGuid==endpointGuid)
1242  break;
1243  }
1244 
1245  if (forwardingIndex<forwardedConnectionList.Size())
1246  {
1247  // Return rerouted notice
1248  SystemAddress intermediaryAddress=packet->systemAddress;
1249  intermediaryAddress.SetPortHostOrder(sourceToDestPort);
1250  rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
1251 
1253  ForwardedConnection& ref_fc = forwardedConnectionList[forwardingIndex];
1254  ref_fc.intermediaryAddress = packet->systemAddress;
1255  ref_fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
1256  ref_fc.intermediaryGuid = packet->guid;
1258 
1259  if (debugInterface)
1260  {
1261  char buff[512];
1262  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_FORWARDING_ESTABLISHED, returning ID_ROUTER_2_REROUTED, Calling RakPeer::ChangeSystemAddress at %s:%i\n", _FILE_AND_LINE_));
1263  }
1264 
1265  packet->data[0]=ID_ROUTER_2_REROUTED;
1266 
1268  return true; // Return packet to user
1269  }
1270  else
1271  {
1273 
1274  // removeFrom connectionRequests;
1275  ForwardedConnection fc;
1277  unsigned int connectionRequestIndex = GetConnectionRequestIndex(endpointGuid);
1278  fc.returnConnectionLostOnFailure=connectionRequests[connectionRequestIndex]->returnConnectionLostOnFailure;
1279  connectionRequests.RemoveAtIndexFast(connectionRequestIndex);
1281  fc.endpointGuid=endpointGuid;
1282  fc.intermediaryAddress=packet->systemAddress;
1283  fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
1284  fc.intermediaryGuid=packet->guid;
1285  fc.weInitiatedForwarding=true;
1286 
1287  // add to forwarding list
1291 
1292  if (debugInterface)
1293  {
1294  char buff[512];
1295  debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got and returning to user ID_ROUTER_2_FORWARDING_ESTABLISHED at %s:%i\n", _FILE_AND_LINE_));
1296  }
1297 
1298  }
1299  return true; // Return packet to user
1300 }
1302 {
1303  int avePing;
1304  int largestPing=-1;
1305  unsigned int maxPeers = rakPeerInterface->GetMaximumNumberOfPeers();
1306  if (maxPeers==0)
1307  return 9999;
1308  unsigned int index;
1309  for (index=0; index < rakPeerInterface->GetMaximumNumberOfPeers(); index++)
1310  {
1312  if (g!=UNASSIGNED_RAKNET_GUID)
1313  {
1315  if (avePing>largestPing)
1316  largestPing=avePing;
1317  }
1318  }
1319  return largestPing;
1320 }
1321 
1322 unsigned int Router2::GetConnectionRequestIndex(RakNetGUID endpointGuid)
1323 {
1324  unsigned int i;
1325  for (i=0; i < connectionRequests.Size(); i++)
1326  {
1327  if (connectionRequests[i]->endpointGuid==endpointGuid)
1328  return i;
1329  }
1330  return (unsigned int) -1;
1331 }
1333 {
1334  unsigned int i;
1335  for (i=0; i < connectionRequestSystems.Size(); i++)
1336  {
1337  if (connectionRequestSystems[i].guid==guid)
1338  return i;
1339  }
1340  return (unsigned int) -1;
1341 }
1342 void Router2::ReturnToUser(MessageID messageId, RakNetGUID endpointGuid, const SystemAddress &systemAddress, bool wasGeneratedLocally)
1343 {
1344  Packet *p = AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char));
1345  p->data[0]=messageId;
1346  p->systemAddress=systemAddress;
1348  p->guid=endpointGuid;
1349  p->wasGeneratedLocally=wasGeneratedLocally;
1350  rakPeerInterface->PushBackPacket(p, true);
1351 }
1353 {
1357 }
1358 void Router2::ClearAll(void)
1359 {
1361  ClearMinipunches();
1363 }
1365 {
1366  debugInterface=_debugInterface;
1367 }
1369 {
1370  return debugInterface;
1371 }
1372 
1373 #endif // _RAKNET_SUPPORT_*