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
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
16 #include "slikenet/NativeFeatureIncludes.h"
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"
24 #include "slikenet/DS_OrderedList.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 };
82 Router2::ConnnectRequest::ConnnectRequest()
83 {
84
85 }
86 Router2::ConnnectRequest::~ConnnectRequest()
87 {
88
89 }
90
91 STATIC_FACTORY_DEFINITIONS(Router2,Router2);
92
93 Router2::Router2()
94 {
95 udpForwarder=0;
96 maximumForwardingRequests=0;
97 debugInterface=0;
98 socketFamily=AF_INET;
99 }
100 Router2::~Router2()
101 {
102 ClearAll();
103
104 if (udpForwarder)
105 {
106 udpForwarder->Shutdown();
107 SLNet::OP_DELETE(udpForwarder,_FILE_AND_LINE_);
108 }
109 }
110 void Router2::ClearMinipunches(void)
111 {
112 miniPunchesInProgressMutex.Lock();
113 miniPunchesInProgress.Clear(false,_FILE_AND_LINE_);
114 miniPunchesInProgressMutex.Unlock();
115 }
116 void Router2::ClearConnectionRequests(void)
117 {
118 connectionRequestsMutex.Lock();
119 for (unsigned int i=0; i < connectionRequests.Size(); i++)
120 {
121 SLNet::OP_DELETE(connectionRequests[i],_FILE_AND_LINE_);
122 }
123 connectionRequests.Clear(false,_FILE_AND_LINE_);
124 connectionRequestsMutex.Unlock();
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?
139 connectionRequestsMutex.Lock();
140 if (GetConnectionRequestIndex(endpointGuid)!=(unsigned int)-1)
141 {
142 connectionRequestsMutex.Unlock();
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 }
148 connectionRequestsMutex.Unlock();
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_);
152 DataStructures::List<SystemAddress> addresses;
153 DataStructures::List<RakNetGUID> guids;
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 }
162 cr->requestState=R2RS_REQUEST_STATE_QUERY_FORWARDING;
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;
173 cr->connectionRequestSystemsMutex.Lock();
174 cr->connectionRequestSystems.Push(crs,_FILE_AND_LINE_);
175 cr->connectionRequestSystemsMutex.Unlock();
176
177 // Broadcast(ID_ROUTER_2_QUERY_FORWARDING, endpointGuid);
178 SLNet::BitStream bsOut;
179 bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
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 }
201 connectionRequestsMutex.Lock();
202 connectionRequests.Push(cr,_FILE_AND_LINE_);
203 connectionRequestsMutex.Unlock();
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 {
219 ConnectionState cs = rakPeerInterface->GetConnectionState(endpointGuid);
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 }
230 void Router2::SetMaximumForwardingRequests(int max)
231 {
232 if (max>0 && maximumForwardingRequests<=0)
233 {
234 udpForwarder = SLNet::OP_NEW<UDPForwarder>(_FILE_AND_LINE_);
235 udpForwarder->Startup();
236 }
237 else if (max<=0 && maximumForwardingRequests>0)
238 {
239 udpForwarder->Shutdown();
240 SLNet::OP_DELETE(udpForwarder,_FILE_AND_LINE_);
241 udpForwarder=0;
242 }
243
244 maximumForwardingRequests=max;
245 }
246 PluginReceiveResult Router2::OnReceive(Packet *packet)
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);
257 return RR_STOP_PROCESSING_AND_DEALLOCATE;
258 }
259 case ID_ROUTER_2_REPLY_FORWARDING:
260 {
261 OnQueryForwardingReply(packet);
262 return RR_STOP_PROCESSING_AND_DEALLOCATE;
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);
277 return RR_STOP_PROCESSING_AND_DEALLOCATE;
278 }
279 case ID_ROUTER_2_INCREASE_TIMEOUT:
280 {
282 rakPeerInterface->SetTimeoutTime(rakPeerInterface->GetTimeoutTime(packet->systemAddress)+10000, packet->systemAddress);
283 return RR_STOP_PROCESSING_AND_DEALLOCATE;
284 }
285 }
286 }
287 else if (packet->data[0]==ID_OUT_OF_BAND_INTERNAL && packet->length>=2)
288 {
289 switch (packet->data[1])
290 {
291 case ID_ROUTER_2_REPLY_TO_SENDER_PORT:
292 {
293 SLNet::BitStream bsOut;
294 bsOut.Write(packet->guid);
295 SendOOBFromRakNetPort(ID_ROUTER_2_MINI_PUNCH_REPLY, &bsOut, packet->systemAddress);
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
309 return RR_STOP_PROCESSING_AND_DEALLOCATE;
310 }
311 case ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT:
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);
321 SendOOBFromRakNetPort(ID_ROUTER_2_MINI_PUNCH_REPLY, &bsOut, sa);
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
332 return RR_STOP_PROCESSING_AND_DEALLOCATE;
333 }
334 case ID_ROUTER_2_MINI_PUNCH_REPLY:
335 OnMiniPunchReply(packet);
336 return RR_STOP_PROCESSING_AND_DEALLOCATE;
337 case ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE:
338 OnMiniPunchReplyBounce(packet);
339 return RR_STOP_PROCESSING_AND_DEALLOCATE;
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)
346 return RR_STOP_PROCESSING_AND_DEALLOCATE;
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;
355 forwardedConnectionListMutex.Lock();
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 {
364 forwardedConnectionListMutex.Unlock();
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
381 rakPeerInterface->SetTimeoutTime(rakPeerInterface->GetTimeoutTime(packet->systemAddress)+10000, packet->systemAddress);
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
386 forwardedConnectionListMutex.Unlock();
387 }
388 }
389 else if (packet->data[0]==ID_ROUTER_2_FORWARDING_NO_PATH)
390 {
391 if (packet->wasGeneratedLocally==false)
392 return RR_STOP_PROCESSING_AND_DEALLOCATE;
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;
401 connectionRequestsMutex.Lock();
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 }
456 connectionRequestsMutex.Unlock();
457
458 unsigned int i=0;
459 miniPunchesInProgressMutex.Lock();
460 while (i < miniPunchesInProgress.Size())
461 {
462 if (miniPunchesInProgress[i].timeout<curTime)
463 {
464 SendFailureOnCannotForward(miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].endpointGuid);
465 miniPunchesInProgress.RemoveAtIndexFast(i);
466 }
467 else if (curTime>miniPunchesInProgress[i].nextAction)
468 {
469 miniPunchesInProgress[i].nextAction=curTime+100;
470 SendOOBMessages(&miniPunchesInProgress[i]);
471 }
472 else
473 i++;
474 }
475 miniPunchesInProgressMutex.Unlock();
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;
485 forwardedConnectionListMutex.Lock();
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
502 connectionRequestsMutex.Lock();
503 unsigned int pos = GetConnectionRequestIndex(forwardedConnectionList[forwardedConnectionIndex].endpointGuid);
504 if((unsigned int)-1 != pos) { SLNet::OP_DELETE(connectionRequests[pos], __FILE__, __LINE__); connectionRequests.RemoveAtIndexFast(pos);}
505 connectionRequestsMutex.Unlock();
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 }
523 forwardedConnectionListMutex.Unlock();
524
525 unsigned int connectionRequestIndex=0;
526 connectionRequestsMutex.Lock();
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 }
575 connectionRequestsMutex.Unlock();
576
577
578 unsigned int i=0;
579 miniPunchesInProgressMutex.Lock();
580 while (i < miniPunchesInProgress.Size())
581 {
582 if (miniPunchesInProgress[i].sourceGuid==rakNetGUID || miniPunchesInProgress[i].endpointGuid==rakNetGUID)
583 {
584 if (miniPunchesInProgress[i].sourceGuid!=rakNetGUID)
585 {
586 SendFailureOnCannotForward(miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].endpointGuid);
587 }
588 miniPunchesInProgress.RemoveAtIndexFast(i);
589 }
590 else
591 i++;
592 }
593 miniPunchesInProgressMutex.Unlock();
594 }
595 void Router2::OnFailedConnectionAttempt(Packet *packet, PI2_FailedConnectionAttemptReason failedConnectionAttemptReason)
596 {
597 (void) failedConnectionAttemptReason;
598 (void) packet;
599
600 unsigned int forwardedConnectionIndex=0;
601 forwardedConnectionListMutex.Lock();
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 }
619 forwardedConnectionListMutex.Unlock();
620 }
621 void Router2::OnRakPeerShutdown(void)
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
652 forwardedConnectionListMutex.Lock();
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 }
662 forwardedConnectionListMutex.Unlock();
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
723 DataStructures::OrderedList<ConnectionRequestSystem, ConnectionRequestSystem, ConnectionRequestSystemComp> commandList;
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,
732 _FILE_AND_LINE_);
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
764 if (udpForwarder==0 || udpForwarder->GetUsedForwardEntries()/2>maximumForwardingRequests)
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
774 forwardedConnectionListMutex.Lock();
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 {
780 forwardedConnectionListMutex.Unlock();
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 }
788 forwardedConnectionListMutex.Unlock();
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 }
803 void Router2::OnQueryForwarding(Packet *packet)
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 }
835 void Router2::OnQueryForwardingReply(Packet *packet)
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
846 connectionRequestsMutex.Lock();
847 unsigned int connectionRequestIndex = GetConnectionRequestIndex(endpointGuid);
848 if (connectionRequestIndex==(unsigned int)-1)
849 {
850 connectionRequestsMutex.Unlock();
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();
861 connectionRequestsMutex.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 }
895 connectionRequestsMutex.Unlock();
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 }
914 void Router2::SendOOBFromRakNetPort(OutOfBandIdentifiers oob, BitStream *extraData, SystemAddress sa)
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 }
927 void Router2::SendOOBFromSpecifiedSocket(OutOfBandIdentifiers oob, SystemAddress sa, __UDPSOCKET__ socket)
928 {
929 SLNet::BitStream bs;
930 rakPeerInterface->WriteOutOfBandHeader(&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 }
958 void Router2::SendOOBMessages(Router2::MiniPunchRequest *mpr)
959 {
960 // Mini NAT punch
961 // Send from srcToDestPort to packet->systemAddress (source). If the message arrives, the remote system should reply.
962 SendOOBFromSpecifiedSocket(ID_ROUTER_2_REPLY_TO_SENDER_PORT, mpr->sourceAddress, mpr->forwardingSocket);
963
964 // Send from destToSourcePort to endpointSystemAddress (destination). If the message arrives, the remote system should reply.
965 SendOOBFromSpecifiedSocket(ID_ROUTER_2_REPLY_TO_SENDER_PORT, mpr->endpointAddress, mpr->forwardingSocket);
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);
986 SendOOBFromRakNetPort(ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT, &extraData, mpr->sourceAddress);
987
988 // Tell destination to send to forwardingPort
989 extraData.Reset();
990 extraData.Write(mpr->forwardingPort);
991 RakAssert(mpr->forwardingPort);
992 SendOOBFromRakNetPort(ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT, &extraData, mpr->endpointAddress);
993 }
994 void Router2::OnRequestForwarding(Packet *packet)
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);
1013 UDPForwarderResult result = udpForwarder->StartForwarding(
1014 packet->systemAddress, endpointSystemAddress, 30000, 0, socketFamily,
1015 &forwardingPort, &forwardingSocket);
1016
1017 if (result==UDPFORWARDER_FORWARDING_ALREADY_EXISTS)
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);
1097 miniPunchesInProgressMutex.Lock();
1098 miniPunchesInProgress.Push(miniPunchRequest,_FILE_AND_LINE_);
1099 miniPunchesInProgressMutex.Unlock();
1100 }
1101 }
1102 void Router2::OnMiniPunchReplyBounce(Packet *packet)
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
1114 miniPunchesInProgressMutex.Lock();
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 {
1133 SendForwardingSuccess(ID_ROUTER_2_REROUTED, miniPunchesInProgress[i].endpointGuid, miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].forwardingPort);
1134 SendForwardingSuccess(ID_ROUTER_2_FORWARDING_ESTABLISHED, miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].endpointGuid, miniPunchesInProgress[i].forwardingPort);
1135 miniPunchesInProgress.RemoveAtIndexFast(i);
1136 }
1137 else
1138 {
1139 i++;
1140 }
1141 }
1142 else
1143 i++;
1144 }
1145 miniPunchesInProgressMutex.Unlock();
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);
1153 SendOOBFromRakNetPort(ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE, 0, rakPeerInterface->GetSystemAddressFromGuid(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;
1181 forwardedConnectionListMutex.Lock();
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];
1191 forwardedConnectionListMutex.Unlock();
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__);
1216 forwardedConnectionListMutex.Unlock();
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 }
1228 bool Router2::OnForwardingSuccess(Packet *packet)
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;
1238 forwardedConnectionListMutex.Lock();
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
1267 forwardedConnectionListMutex.Unlock();
1268 return true; // Return packet to user
1269 }
1270 else
1271 {
1272 forwardedConnectionListMutex.Unlock();
1273
1274 // removeFrom connectionRequests;
1275 ForwardedConnection fc;
1276 connectionRequestsMutex.Lock();
1277 unsigned int connectionRequestIndex = GetConnectionRequestIndex(endpointGuid);
1278 fc.returnConnectionLostOnFailure=connectionRequests[connectionRequestIndex]->returnConnectionLostOnFailure;
1279 connectionRequests.RemoveAtIndexFast(connectionRequestIndex);
1280 connectionRequestsMutex.Unlock();
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
1288 forwardedConnectionListMutex.Lock();
1289 forwardedConnectionList.Push (fc,_FILE_AND_LINE_);
1290 forwardedConnectionListMutex.Unlock();
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 }
1301 int Router2::GetLargestPingAmongConnectedSystems(void) const
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 {
1311 RakNetGUID g = rakPeerInterface->GetGUIDFromIndex(index);
1312 if (g!=UNASSIGNED_RAKNET_GUID)
1313 {
1314 avePing=rakPeerInterface->GetAveragePing(rakPeerInterface->GetGUIDFromIndex(index));
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 }
1332 unsigned int Router2::ConnnectRequest::GetGuidIndex(RakNetGUID guid)
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;
1347 p->systemAddress.systemIndex=(SystemIndex)-1;
1348 p->guid=endpointGuid;
1349 p->wasGeneratedLocally=wasGeneratedLocally;
1350 rakPeerInterface->PushBackPacket(p, true);
1351 }
1352 void Router2::ClearForwardedConnections(void)
1353 {
1354 forwardedConnectionListMutex.Lock();
1355 forwardedConnectionList.Clear(false,_FILE_AND_LINE_);
1356 forwardedConnectionListMutex.Unlock();
1357 }
1358 void Router2::ClearAll(void)
1359 {
1360 ClearConnectionRequests();
1361 ClearMinipunches();
1362 ClearForwardedConnections();
1363 }
1364 void Router2::SetDebugInterface(Router2DebugInterface *_debugInterface)
1365 {
1366 debugInterface=_debugInterface;
1367 }
1368 Router2DebugInterface *Router2::GetDebugInterface(void) const
1369 {
1370 return debugInterface;
1371 }
1372
1373 #endif // _RAKNET_SUPPORT_*