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
NatPunchthroughClient.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_NatPunchthroughClient==1
18
19 #include "slikenet/NatPunchthroughClient.h"
20 #include "slikenet/BitStream.h"
21 #include "slikenet/MessageIdentifiers.h"
22 #include "slikenet/peerinterface.h"
23 #include "slikenet/GetTime.h"
24 #include "slikenet/PacketLogger.h"
25 #include "slikenet/Itoa.h"
26
27 using namespace SLNet;
28
29 void NatPunchthroughDebugInterface_Printf::OnClientMessage(const char *msg)
30 {
31 printf("%s\n", msg);
32 }
33 #if _RAKNET_SUPPORT_PacketLogger==1
34 void NatPunchthroughDebugInterface_PacketLogger::OnClientMessage(const char *msg)
35 {
36 if (pl)
37 {
38 pl->WriteMiscellaneous("Nat", msg);
39 }
40 }
41 #endif
42
43 STATIC_FACTORY_DEFINITIONS(NatPunchthroughClient,NatPunchthroughClient);
44
45 NatPunchthroughClient::NatPunchthroughClient()
46 {
47 natPunchthroughDebugInterface=0;
48 mostRecentExternalPort=0;
49 sp.nextActionTime=0;
50 portStride=0;
51 hasPortStride=UNKNOWN_PORT_STRIDE;
52 }
53 NatPunchthroughClient::~NatPunchthroughClient()
54 {
55 rakPeerInterface=0;
56 Clear();
57 }
58 void NatPunchthroughClient::FindRouterPortStride(const SystemAddress &facilitator)
59 {
60 ConnectionState cs = rakPeerInterface->GetConnectionState(facilitator);
61 if (cs!=IS_CONNECTED)
62 return;
63 if (hasPortStride!=UNKNOWN_PORT_STRIDE)
64 return;
65
66 hasPortStride=CALCULATING_PORT_STRIDE;
67 portStrideCalTimeout = SLNet::GetTime()+5000;
68
69 if (natPunchthroughDebugInterface)
70 {
71 natPunchthroughDebugInterface->OnClientMessage(RakString("Calculating port stride from %s", facilitator.ToString(true)));
72 }
73
74 SLNet::BitStream outgoingBs;
75 outgoingBs.Write((MessageID)ID_NAT_REQUEST_BOUND_ADDRESSES);
76 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,facilitator,false);
77 }
78 bool NatPunchthroughClient::OpenNAT(RakNetGUID destination, const SystemAddress &facilitator)
79 {
80 ConnectionState cs = rakPeerInterface->GetConnectionState(facilitator);
81 if (cs!=IS_CONNECTED)
82 return false;
83 if (hasPortStride==UNKNOWN_PORT_STRIDE)
84 {
85 FindRouterPortStride(facilitator);
86 QueueOpenNAT(destination, facilitator);
87 }
88 else if (hasPortStride==CALCULATING_PORT_STRIDE)
89 {
90 QueueOpenNAT(destination, facilitator);
91 }
92 else
93 {
94 SendPunchthrough(destination, facilitator);
95 }
96
97 return true;
98 }
99 /*
100 bool NatPunchthroughClient::OpenNATGroup(DataStructures::List<RakNetGUID> destinationSystems, const SystemAddress &facilitator)
101 {
102 ConnectionState cs = rakPeerInterface->GetConnectionState(facilitator);
103 if (cs!=IS_CONNECTED)
104 return false;
105
106 unsigned long i;
107 for (i=0; i < destinationSystems.Size(); i++)
108 {
109 SendPunchthrough(destinationSystems[i], facilitator);
110 }
111
112 GroupPunchRequest *gpr = SLNet::OP_NEW<GroupPunchRequest>(_FILE_AND_LINE_);
113 gpr->facilitator=facilitator;
114 gpr->pendingList=destinationSystems;
115 groupPunchRequests.Push(gpr, _FILE_AND_LINE_);
116
117 return true;
118 }
119 */
120 void NatPunchthroughClient::SetDebugInterface(NatPunchthroughDebugInterface *i)
121 {
122 natPunchthroughDebugInterface=i;
123 }
124 void NatPunchthroughClient::Update(void)
125 {
126 SLNet::Time time = SLNet::GetTime();
127
128 if (hasPortStride==CALCULATING_PORT_STRIDE && time > portStrideCalTimeout)
129 {
130 if (natPunchthroughDebugInterface)
131 {
132 natPunchthroughDebugInterface->OnClientMessage("CALCULATING_PORT_STRIDE timeout");
133 }
134
135 SendQueuedOpenNAT();
136 hasPortStride=UNKNOWN_PORT_STRIDE;
137 }
138
139 if (sp.nextActionTime && sp.nextActionTime < time)
140 {
141 SLNet::Time delta = time - sp.nextActionTime;
142 if (sp.testMode==SendPing::TESTING_INTERNAL_IPS)
143 {
144 SendOutOfBand(sp.internalIds[sp.attemptCount],ID_NAT_ESTABLISH_UNIDIRECTIONAL);
145
146 if (++sp.retryCount>=pc.UDP_SENDS_PER_PORT_INTERNAL)
147 {
148 ++sp.attemptCount;
149 sp.retryCount=0;
150 }
151
152 if (sp.attemptCount>=pc.MAXIMUM_NUMBER_OF_INTERNAL_IDS_TO_CHECK)
153 {
154 sp.testMode=SendPing::WAITING_FOR_INTERNAL_IPS_RESPONSE;
155 if (pc.INTERNAL_IP_WAIT_AFTER_ATTEMPTS>0)
156 {
157 sp.nextActionTime=time+pc.INTERNAL_IP_WAIT_AFTER_ATTEMPTS-delta;
158 }
159 else
160 {
161 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_FACILITATOR_PORT;
162 sp.attemptCount=0;
163 sp.sentTTL=false;
164 }
165 }
166 else
167 {
168 sp.nextActionTime=time+pc.TIME_BETWEEN_PUNCH_ATTEMPTS_INTERNAL-delta;
169 }
170 }
171 else if (sp.testMode==SendPing::WAITING_FOR_INTERNAL_IPS_RESPONSE)
172 {
173 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_FACILITATOR_PORT;
174 sp.attemptCount=0;
175 sp.sentTTL=false;
176 }
177 /*
178 else if (sp.testMode==SendPing::SEND_WITH_TTL)
179 {
180 // Send to unused port. We do not want the message to arrive, just to open our router's table
181 SystemAddress sa=sp.targetAddress;
182 int ttlSendIndex;
183 for (ttlSendIndex=0; ttlSendIndex <= pc.MAX_PREDICTIVE_PORT_RANGE; ttlSendIndex++)
184 {
185 sa.SetPortHostOrder((unsigned short) (sp.targetAddress.GetPort()+ttlSendIndex));
186 SendTTL(sa);
187 }
188
189 // Only do this stage once
190 // Wait 250 milliseconds for next stage. The delay is so that even with timing errors both systems send out the
191 // datagram with TTL before either sends a real one
192 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_FACILITATOR_PORT;
193 sp.nextActionTime=time-delta+250;
194 }
195 */
196 else if (sp.testMode==SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_FACILITATOR_PORT)
197 {
198 if (sp.sentTTL==false)
199 {
200 SystemAddress sa=sp.targetAddress;
201 sa.SetPortHostOrder((unsigned short) (sa.GetPort()+sp.attemptCount));
202 SendTTL(sa);
203
204 if (natPunchthroughDebugInterface)
205 {
206 natPunchthroughDebugInterface->OnClientMessage(RakString("Send with TTL 2 to %s", sa.ToString(true)));
207 }
208
209 sp.nextActionTime = time+pc.EXTERNAL_IP_WAIT_AFTER_FIRST_TTL-delta;
210 sp.sentTTL=true;
211 }
212 else
213 {
214 SystemAddress sa=sp.targetAddress;
215 sa.SetPortHostOrder((unsigned short) (sa.GetPort()+sp.attemptCount));
216 SendOutOfBand(sa,ID_NAT_ESTABLISH_UNIDIRECTIONAL);
217
218 IncrementExternalAttemptCount(time, delta);
219
220 if (sp.attemptCount>pc.MAX_PREDICTIVE_PORT_RANGE)
221 {
222 sp.testMode=SendPing::WAITING_AFTER_ALL_ATTEMPTS;
223 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_AFTER_ALL_ATTEMPTS-delta;
224
225 // Skip TESTING_EXTERNAL_IPS_1024_TO_FACILITATOR_PORT, etc.
226 /*
227 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_1024_TO_FACILITATOR_PORT;
228 sp.attemptCount=0;
229 */
230 }
231 }
232 }
233 else if (sp.testMode==SendPing::TESTING_EXTERNAL_IPS_1024_TO_FACILITATOR_PORT)
234 {
235 SystemAddress sa=sp.targetAddress;
236 if ( sp.targetGuid < rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS) )
237 sa.SetPortHostOrder((unsigned short) (1024+sp.attemptCount));
238 else
239 sa.SetPortHostOrder((unsigned short) (sa.GetPort()+sp.attemptCount));
240 SendOutOfBand(sa,ID_NAT_ESTABLISH_UNIDIRECTIONAL);
241
242 IncrementExternalAttemptCount(time, delta);
243
244 if (sp.attemptCount>pc.MAX_PREDICTIVE_PORT_RANGE)
245 {
246 // From 1024 disabled, never helps as I've seen, but slows down the process by half
247 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_1024;
248 sp.attemptCount=0;
249 }
250
251 }
252 else if (sp.testMode==SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_1024)
253 {
254 SystemAddress sa=sp.targetAddress;
255 if ( sp.targetGuid > rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS) )
256 sa.SetPortHostOrder((unsigned short) (1024+sp.attemptCount));
257 else
258 sa.SetPortHostOrder((unsigned short) (sa.GetPort()+sp.attemptCount));
259 SendOutOfBand(sa,ID_NAT_ESTABLISH_UNIDIRECTIONAL);
260
261 IncrementExternalAttemptCount(time, delta);
262
263 if (sp.attemptCount>pc.MAX_PREDICTIVE_PORT_RANGE)
264 {
265 // From 1024 disabled, never helps as I've seen, but slows down the process by half
266 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_1024_TO_1024;
267 sp.attemptCount=0;
268 }
269 }
270 else if (sp.testMode==SendPing::TESTING_EXTERNAL_IPS_1024_TO_1024)
271 {
272 SystemAddress sa=sp.targetAddress;
273 sa.SetPortHostOrder((unsigned short) (1024+sp.attemptCount));
274 SendOutOfBand(sa,ID_NAT_ESTABLISH_UNIDIRECTIONAL);
275
276 IncrementExternalAttemptCount(time, delta);
277
278 if (sp.attemptCount>pc.MAX_PREDICTIVE_PORT_RANGE)
279 {
280 if (natPunchthroughDebugInterface)
281 {
282 char ipAddressString[32];
283 sp.targetAddress.ToString(true, ipAddressString, static_cast<size_t>(32));
284 char guidString[128];
285 sp.targetGuid.ToString(guidString, 128);
286 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Likely bidirectional punchthrough failure to guid %s, system address %s.", guidString, ipAddressString));
287 }
288
289 sp.testMode=SendPing::WAITING_AFTER_ALL_ATTEMPTS;
290 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_AFTER_ALL_ATTEMPTS-delta;
291 }
292 }
293 else if (sp.testMode==SendPing::WAITING_AFTER_ALL_ATTEMPTS)
294 {
295 // Failed. Tell the user
296 OnPunchthroughFailure();
297 // UpdateGroupPunchOnNatResult(sp.facilitator, sp.targetGuid, sp.targetAddress, 1);
298 }
299
300 if (sp.testMode==SendPing::PUNCHING_FIXED_PORT)
301 {
302 SendOutOfBand(sp.targetAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);
303 if (++sp.retryCount>=sp.punchingFixedPortAttempts)
304 {
305 if (natPunchthroughDebugInterface)
306 {
307 char ipAddressString[32];
308 sp.targetAddress.ToString(true, ipAddressString, static_cast<size_t>(32));
309 char guidString[128];
310 sp.targetGuid.ToString(guidString, 128);
311 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Likely unidirectional punchthrough failure to guid %s, system address %s.", guidString, ipAddressString));
312 }
313
314 sp.testMode=SendPing::WAITING_AFTER_ALL_ATTEMPTS;
315 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_AFTER_ALL_ATTEMPTS-delta;
316 }
317 else
318 {
319 if ((sp.retryCount%pc.UDP_SENDS_PER_PORT_EXTERNAL)==0)
320 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_BETWEEN_PORTS-delta;
321 else
322 sp.nextActionTime=time+pc.TIME_BETWEEN_PUNCH_ATTEMPTS_EXTERNAL-delta;
323 }
324 }
325 }
326
327 /*
328 // Remove elapsed groupRequestsInProgress
329 unsigned int i;
330 i=0;
331 while (i < groupRequestsInProgress.Size())
332 {
333 if (time > groupRequestsInProgress[i].time)
334 groupRequestsInProgress.RemoveAtIndexFast(i);
335 else
336 i++;
337 }
338 */
339 }
340 void NatPunchthroughClient::PushFailure(void)
341 {
342 Packet *p = AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char));
343 p->data[0]=ID_NAT_PUNCHTHROUGH_FAILED;
344 p->systemAddress=sp.targetAddress;
345 p->systemAddress.systemIndex=(SystemIndex)-1;
346 p->guid=sp.targetGuid;
347 if (sp.weAreSender)
348 p->data[1]=1;
349 else
350 p->data[1]=0;
351 p->wasGeneratedLocally=true;
352 rakPeerInterface->PushBackPacket(p, true);
353 }
354 void NatPunchthroughClient::OnPunchthroughFailure(void)
355 {
356 if (pc.retryOnFailure==false)
357 {
358 if (natPunchthroughDebugInterface)
359 {
360 char ipAddressString[32];
361 sp.targetAddress.ToString(true, ipAddressString, static_cast<size_t>(32));
362 char guidString[128];
363 sp.targetGuid.ToString(guidString, 128);
364 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Failed punchthrough once. Returning failure to guid %s, system address %s to user.", guidString, ipAddressString));
365 }
366
367 PushFailure();
368 OnReadyForNextPunchthrough();
369 return;
370 }
371
372 unsigned int i;
373 for (i=0; i < failedAttemptList.Size(); i++)
374 {
375 if (failedAttemptList[i].guid==sp.targetGuid)
376 {
377 if (natPunchthroughDebugInterface)
378 {
379 char ipAddressString[32];
380 sp.targetAddress.ToString(true, ipAddressString, static_cast<size_t>(32));
381 char guidString[128];
382 sp.targetGuid.ToString(guidString, 128);
383 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Failed punchthrough twice. Returning failure to guid %s, system address %s to user.", guidString, ipAddressString));
384 }
385
386 // Failed a second time, so return failed to user
387 PushFailure();
388
389 OnReadyForNextPunchthrough();
390
391 failedAttemptList.RemoveAtIndexFast(i);
392 return;
393 }
394 }
395
396 if (rakPeerInterface->GetConnectionState(sp.facilitator)!=IS_CONNECTED)
397 {
398 if (natPunchthroughDebugInterface)
399 {
400 char ipAddressString[32];
401 sp.targetAddress.ToString(true, ipAddressString, static_cast<size_t>(32));
402 char guidString[128];
403 sp.targetGuid.ToString(guidString, 128);
404 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Not connected to facilitator, so cannot retry punchthrough after first failure. Returning failure onj guid %s, system address %s to user.", guidString, ipAddressString));
405 }
406
407 // Failed, and can't try again because no facilitator
408 PushFailure();
409 return;
410 }
411
412 if (natPunchthroughDebugInterface)
413 {
414 char ipAddressString[32];
415 sp.targetAddress.ToString(true, ipAddressString, static_cast<size_t>(32));
416 char guidString[128];
417 sp.targetGuid.ToString(guidString, 128);
418 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("First punchthrough failure on guid %s, system address %s. Reattempting.", guidString, ipAddressString));
419 }
420
421 // Failed the first time. Add to the failure queue and try again
422 AddrAndGuid aag;
423 aag.addr=sp.targetAddress;
424 aag.guid=sp.targetGuid;
425 failedAttemptList.Push(aag, _FILE_AND_LINE_);
426
427 // Tell the server we are ready
428 OnReadyForNextPunchthrough();
429
430 // If we are the sender, try again, immediately if possible, else added to the queue on the faciltiator
431 if (sp.weAreSender)
432 SendPunchthrough(sp.targetGuid, sp.facilitator);
433 }
434 PluginReceiveResult NatPunchthroughClient::OnReceive(Packet *packet)
435 {
436 switch (packet->data[0])
437 {
438 case ID_NAT_GET_MOST_RECENT_PORT:
439 {
440 OnGetMostRecentPort(packet);
441 return RR_STOP_PROCESSING_AND_DEALLOCATE;
442 }
443 case ID_NAT_PUNCHTHROUGH_FAILED:
444 case ID_NAT_PUNCHTHROUGH_SUCCEEDED:
445 if (packet->wasGeneratedLocally==false)
446 return RR_STOP_PROCESSING_AND_DEALLOCATE;
447 break;
448 case ID_NAT_RESPOND_BOUND_ADDRESSES:
449 {
450 SLNet::BitStream bs(packet->data,packet->length,false);
451 bs.IgnoreBytes(sizeof(MessageID));
452 unsigned char boundAddressCount;
453 bs.Read(boundAddressCount);
454 if (boundAddressCount<2)
455 {
456 if (natPunchthroughDebugInterface)
457 natPunchthroughDebugInterface->OnClientMessage(RakString("INCAPABLE_PORT_STRIDE. My external ID is %s", rakPeerInterface->GetExternalID(packet->systemAddress).ToString()));
458
459 hasPortStride=INCAPABLE_PORT_STRIDE;
460 SendQueuedOpenNAT();
461 }
462 SystemAddress boundAddresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS];
463 for (int i=0; i < boundAddressCount && i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
464 {
465 bs.Read(boundAddresses[i]);
466 if (boundAddresses[i]!=packet->systemAddress)
467 {
468 SLNet::BitStream outgoingBs;
469 outgoingBs.Write((MessageID)ID_NAT_PING);
470 uint16_t externalPort = rakPeerInterface->GetExternalID(packet->systemAddress).GetPort();
471 outgoingBs.Write( externalPort );
472 rakPeerInterface->SendOutOfBand((const char*) boundAddresses[i].ToString(false),boundAddresses[i].GetPort(),(const char*) outgoingBs.GetData(),outgoingBs.GetNumberOfBytesUsed());
473 break;
474 }
475 }
476 }
477 return RR_STOP_PROCESSING_AND_DEALLOCATE;
478 case ID_OUT_OF_BAND_INTERNAL:
479 if (packet->length>=2 && packet->data[1]==ID_NAT_PONG)
480 {
481 SLNet::BitStream bs(packet->data,packet->length,false);
482 bs.IgnoreBytes(sizeof(MessageID)*2);
483 uint16_t externalPort;
484 bs.Read(externalPort);
485 uint16_t externalPort2;
486 bs.Read(externalPort2);
487 portStride = externalPort2 - externalPort;
488 mostRecentExternalPort = externalPort2;
489 hasPortStride=HAS_PORT_STRIDE;
490
491 if (natPunchthroughDebugInterface)
492 natPunchthroughDebugInterface->OnClientMessage(RakString("HAS_PORT_STRIDE %i. First external port %i. Second external port %i.", portStride, externalPort, externalPort2));
493
494 SendQueuedOpenNAT();
495 return RR_STOP_PROCESSING_AND_DEALLOCATE;
496 }
497 else if (packet->length>=2 &&
498 (packet->data[1]==ID_NAT_ESTABLISH_UNIDIRECTIONAL || packet->data[1]==ID_NAT_ESTABLISH_BIDIRECTIONAL) &&
499 sp.nextActionTime!=0)
500 {
501 SLNet::BitStream bs(packet->data,packet->length,false);
502 bs.IgnoreBytes(2);
503 uint16_t sessionId;
504 bs.Read(sessionId);
505 // RakAssert(sessionId<100);
506 if (sessionId!=sp.sessionId)
507 break;
508
509 char ipAddressString[32];
510 packet->systemAddress.ToString(true,ipAddressString,static_cast<size_t>(32));
511 // sp.targetGuid==packet->guid is because the internal IP addresses reported may include loopbacks not reported by RakPeer::IsLocalIP()
512 if (packet->data[1]==ID_NAT_ESTABLISH_UNIDIRECTIONAL && sp.targetGuid==packet->guid)
513 {
514
515 if (sp.testMode!=SendPing::PUNCHING_FIXED_PORT)
516 {
517 sp.testMode=SendPing::PUNCHING_FIXED_PORT;
518 sp.retryCount+=sp.attemptCount*pc.UDP_SENDS_PER_PORT_EXTERNAL;
519 sp.targetAddress=packet->systemAddress;
520 // Keeps trying until the other side gives up too, in case it is unidirectional
521 sp.punchingFixedPortAttempts=pc.UDP_SENDS_PER_PORT_EXTERNAL*(pc.MAX_PREDICTIVE_PORT_RANGE+1);
522
523 if (natPunchthroughDebugInterface)
524 {
525 char guidString[128];
526 sp.targetGuid.ToString(guidString, 128);
527 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("PUNCHING_FIXED_PORT: Received ID_NAT_ESTABLISH_UNIDIRECTIONAL from guid %s, system address %s.", guidString, ipAddressString));
528 }
529 }
530 else {
531 if (natPunchthroughDebugInterface)
532 {
533 char guidString[128];
534 sp.targetGuid.ToString(guidString, 128);
535 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Received ID_NAT_ESTABLISH_UNIDIRECTIONAL from guid %s, system address %s.", guidString, ipAddressString));
536 }
537 }
538
539 SendOutOfBand(sp.targetAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);
540 }
541 else if (packet->data[1]==ID_NAT_ESTABLISH_BIDIRECTIONAL &&
542 sp.targetGuid==packet->guid)
543 {
544 // They send back our port
545 unsigned short ourExternalPort;
546 bs.Read(ourExternalPort);
547 if (mostRecentExternalPort==0)
548 {
549 mostRecentExternalPort=ourExternalPort;
550
551 if (natPunchthroughDebugInterface)
552 {
553 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("ID_NAT_ESTABLISH_BIDIRECTIONAL mostRecentExternalPort first time set to %i", mostRecentExternalPort));
554 }
555 }
556 else
557 {
558 if (sp.testMode!=SendPing::TESTING_INTERNAL_IPS && sp.testMode!=SendPing::WAITING_FOR_INTERNAL_IPS_RESPONSE)
559 {
560 if (hasPortStride!=HAS_PORT_STRIDE)
561 {
562 portStride = ourExternalPort - mostRecentExternalPort;
563 hasPortStride=HAS_PORT_STRIDE;
564
565 if (natPunchthroughDebugInterface)
566 {
567 natPunchthroughDebugInterface->OnClientMessage(RakString("ID_NAT_ESTABLISH_BIDIRECTIONAL: Estimated port stride from incoming connection at %i. ourExternalPort=%i mostRecentExternalPort=%i", portStride, ourExternalPort, mostRecentExternalPort));
568 }
569
570 SendQueuedOpenNAT();
571 }
572
573 //nextExternalPort += portStride * (pc.MAX_PREDICTIVE_PORT_RANGE+1);
574 mostRecentExternalPort = ourExternalPort;
575
576 if (natPunchthroughDebugInterface)
577 {
578 natPunchthroughDebugInterface->OnClientMessage(RakString("ID_NAT_ESTABLISH_BIDIRECTIONAL: New mostRecentExternalPort %i", mostRecentExternalPort));
579 }
580 }
581 }
582 SendOutOfBand(packet->systemAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);
583
584 // Tell the user about the success
585 sp.targetAddress=packet->systemAddress;
586 PushSuccess();
587 //UpdateGroupPunchOnNatResult(sp.facilitator, sp.targetGuid, sp.targetAddress, 1);
588 OnReadyForNextPunchthrough();
589 bool removedFromFailureQueue=RemoveFromFailureQueue();
590
591 if (natPunchthroughDebugInterface)
592 {
593 char guidString[128];
594 sp.targetGuid.ToString(guidString, 128);
595 if (removedFromFailureQueue)
596 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Punchthrough to guid %s, system address %s succeeded on 2nd attempt.", guidString, ipAddressString));
597 else
598 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Punchthrough to guid %s, system address %s succeeded on 1st attempt.", guidString, ipAddressString));
599 }
600 }
601
602 // mostRecentNewExternalPort=packet->systemAddress.GetPort();
603 }
604 return RR_STOP_PROCESSING_AND_DEALLOCATE;
605 case ID_NAT_ALREADY_IN_PROGRESS:
606 {
607 SLNet::BitStream incomingBs(packet->data, packet->length, false);
608 incomingBs.IgnoreBytes(sizeof(MessageID));
609 RakNetGUID targetGuid;
610 incomingBs.Read(targetGuid);
611 // Don't update group, just use later message
612 // UpdateGroupPunchOnNatResult(packet->systemAddress, targetGuid, UNASSIGNED_SYSTEM_ADDRESS, 2);
613 if (natPunchthroughDebugInterface)
614 {
615 char guidString[128];
616 targetGuid.ToString(guidString, 128);
617 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Punchthrough retry to guid %s failed due to ID_NAT_ALREADY_IN_PROGRESS. Returning failure.", guidString));
618 }
619
620 }
621 break;
622 case ID_NAT_TARGET_NOT_CONNECTED:
623 case ID_NAT_CONNECTION_TO_TARGET_LOST:
624 case ID_NAT_TARGET_UNRESPONSIVE:
625 {
626 const char *reason;
627 if (packet->data[0]==ID_NAT_TARGET_NOT_CONNECTED)
628 reason=(char *)"ID_NAT_TARGET_NOT_CONNECTED";
629 else if (packet->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST)
630 reason=(char *)"ID_NAT_CONNECTION_TO_TARGET_LOST";
631 else
632 reason=(char *)"ID_NAT_TARGET_UNRESPONSIVE";
633
634
635 SLNet::BitStream incomingBs(packet->data, packet->length, false);
636 incomingBs.IgnoreBytes(sizeof(MessageID));
637
638 RakNetGUID targetGuid;
639 incomingBs.Read(targetGuid);
640 //UpdateGroupPunchOnNatResult(packet->systemAddress, targetGuid, UNASSIGNED_SYSTEM_ADDRESS, 2);
641
642 if (packet->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST ||
643 packet->data[0]==ID_NAT_TARGET_UNRESPONSIVE)
644 {
645 uint16_t sessionId;
646 incomingBs.Read(sessionId);
647 if (sessionId!=sp.sessionId)
648 break;
649 }
650
651 unsigned int i;
652 for (i=0; i < failedAttemptList.Size(); i++)
653 {
654 if (failedAttemptList[i].guid==targetGuid)
655 {
656 if (natPunchthroughDebugInterface)
657 {
658 char guidString[128];
659 targetGuid.ToString(guidString, 128);
660 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Punchthrough retry to guid %s failed due to %s.", guidString, reason));
661
662 }
663
664 // If the retry target is not connected, or loses connection, or is not responsive, then previous failures cannot be retried.
665
666 // Don't need to return failed, the other messages indicate failure anyway
667 /*
668 Packet *p = AllocatePacketUnified(sizeof(MessageID));
669 p->data[0]=ID_NAT_PUNCHTHROUGH_FAILED;
670 p->systemAddress=failedAttemptList[i].addr;
671 p->systemAddress.systemIndex=(SystemIndex)-1;
672 p->guid=failedAttemptList[i].guid;
673 rakPeerInterface->PushBackPacket(p, false);
674 */
675
676 failedAttemptList.RemoveAtIndexFast(i);
677 break;
678 }
679 }
680
681 if (natPunchthroughDebugInterface)
682 {
683 char guidString[128];
684 targetGuid.ToString(guidString, 128);
685 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Punchthrough attempt to guid %s failed due to %s.", guidString, reason));
686 }
687
688 // Stop trying punchthrough
689 sp.nextActionTime=0;
690
691 /*
692 SLNet::BitStream bs(packet->data, packet->length, false);
693 bs.IgnoreBytes(sizeof(MessageID));
694 RakNetGUID failedSystem;
695 bs.Read(failedSystem);
696 bool deletedFirst=false;
697 unsigned int i=0;
698 while (i < pendingOpenNAT.Size())
699 {
700 if (pendingOpenNAT[i].destination==failedSystem)
701 {
702 if (i==0)
703 deletedFirst=true;
704 pendingOpenNAT.RemoveAtIndex(i);
705 }
706 else
707 i++;
708 }
709 // Failed while in progress. Go to next in attempt queue
710 if (deletedFirst && pendingOpenNAT.Size())
711 {
712 SendPunchthrough(pendingOpenNAT[0].destination, pendingOpenNAT[0].facilitator);
713 sp.nextActionTime=0;
714 }
715 */
716 }
717 break;
718 case ID_TIMESTAMP:
719 if (packet->data[sizeof(MessageID)+sizeof(SLNet::Time)]==ID_NAT_CONNECT_AT_TIME)
720 {
721 OnConnectAtTime(packet);
722 return RR_STOP_PROCESSING_AND_DEALLOCATE;
723 }
724 break;
725 }
726 return RR_CONTINUE_PROCESSING;
727 }
728 /*
729 void NatPunchthroughClient::ProcessNextPunchthroughQueue(void)
730 {
731 // Go to the next attempt
732 if (pendingOpenNAT.Size())
733 pendingOpenNAT.RemoveAtIndex(0);
734
735 // Do next punchthrough attempt
736 if (pendingOpenNAT.Size())
737 SendPunchthrough(pendingOpenNAT[0].destination, pendingOpenNAT[0].facilitator);
738
739 sp.nextActionTime=0;
740 }
741 */
742 void NatPunchthroughClient::OnConnectAtTime(Packet *packet)
743 {
744 // RakAssert(sp.nextActionTime==0);
745
746 SLNet::BitStream bs(packet->data, packet->length, false);
747 bs.IgnoreBytes(sizeof(MessageID));
748 bs.Read(sp.nextActionTime);
749 bs.IgnoreBytes(sizeof(MessageID));
750 bs.Read(sp.sessionId);
751 bs.Read(sp.targetAddress);
752 int j;
753 // int k;
754 // k=0;
755 for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++)
756 bs.Read(sp.internalIds[j]);
757
758 // Prevents local testing
759 /*
760 for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++)
761 {
762 SystemAddress id;
763 bs.Read(id);
764 char str[32];
765 id.ToString(false,str);
766 if (rakPeerInterface->IsLocalIP(str)==false)
767 sp.internalIds[k++]=id;
768 }
769 */
770 sp.attemptCount=0;
771 sp.retryCount=0;
772 if (pc.MAXIMUM_NUMBER_OF_INTERNAL_IDS_TO_CHECK>0)
773 {
774 sp.testMode=SendPing::TESTING_INTERNAL_IPS;
775 }
776 else
777 {
778 // TESTING: Try sending to unused ports on the remote system to reserve our own ports while not getting banned
779 //sp.testMode=SendPing::SEND_WITH_TTL;
780 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_FACILITATOR_PORT;
781 sp.attemptCount=0;
782 sp.sentTTL=false;
783 }
784 bs.Read(sp.targetGuid);
785 bs.Read(sp.weAreSender);
786 }
787 void NatPunchthroughClient::SendTTL(const SystemAddress &sa)
788 {
789 if (sa==UNASSIGNED_SYSTEM_ADDRESS)
790 return;
791 if (sa.GetPort()==0)
792 return;
793
794 char ipAddressString[32];
795 sa.ToString(false, ipAddressString,static_cast<size_t>(32));
796 // TTL of 1 doesn't get past the router, 2 might hit the other system on a LAN
797 rakPeerInterface->SendTTL(ipAddressString,sa.GetPort(), 2);
798 }
799
800 const char *TestModeToString(NatPunchthroughClient::SendPing::TestMode tm)
801 {
802 switch (tm)
803 {
804 case NatPunchthroughClient::SendPing::TESTING_INTERNAL_IPS:
805 return "TESTING_INTERNAL_IPS";
806 break;
807 case NatPunchthroughClient::SendPing::WAITING_FOR_INTERNAL_IPS_RESPONSE:
808 return "WAITING_FOR_INTERNAL_IPS_RESPONSE";
809 break;
810 // case NatPunchthroughClient::SendPing::SEND_WITH_TTL:
811 // return "SEND_WITH_TTL";
812 // break;
813 case NatPunchthroughClient::SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_FACILITATOR_PORT:
814 return "TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_FACILITATOR_PORT";
815 break;
816 case NatPunchthroughClient::SendPing::TESTING_EXTERNAL_IPS_1024_TO_FACILITATOR_PORT:
817 return "TESTING_EXTERNAL_IPS_1024_TO_FACILITATOR_PORT";
818 break;
819 case NatPunchthroughClient::SendPing::TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_1024:
820 return "TESTING_EXTERNAL_IPS_FACILITATOR_PORT_TO_1024";
821 break;
822 case NatPunchthroughClient::SendPing::TESTING_EXTERNAL_IPS_1024_TO_1024:
823 return "TESTING_EXTERNAL_IPS_1024_TO_1024";
824 break;
825 case NatPunchthroughClient::SendPing::WAITING_AFTER_ALL_ATTEMPTS:
826 return "WAITING_AFTER_ALL_ATTEMPTS";
827 break;
828 case NatPunchthroughClient::SendPing::PUNCHING_FIXED_PORT:
829 return "PUNCHING_FIXED_PORT";
830 break;
831 }
832 return "";
833 }
834 void NatPunchthroughClient::SendOutOfBand(SystemAddress sa, MessageID oobId)
835 {
836 if (sa==UNASSIGNED_SYSTEM_ADDRESS)
837 return;
838 if (sa.GetPort()==0)
839 return;
840
841 SLNet::BitStream oob;
842 oob.Write(oobId);
843 oob.Write(sp.sessionId);
844 // RakAssert(sp.sessionId<100);
845 if (oobId==ID_NAT_ESTABLISH_BIDIRECTIONAL)
846 oob.Write(sa.GetPort());
847 char ipAddressString[32];
848 sa.ToString(false, ipAddressString, static_cast<size_t>(32));
849 rakPeerInterface->SendOutOfBand((const char*) ipAddressString,sa.GetPort(),(const char*) oob.GetData(),oob.GetNumberOfBytesUsed());
850
851 if (natPunchthroughDebugInterface)
852 {
853 sa.ToString(true,ipAddressString,static_cast<size_t>(32));
854 char guidString[128];
855 sp.targetGuid.ToString(guidString, 128);
856
857 // server - diff = my time
858 // server = myTime + diff
859 SLNet::Time clockDifferential = rakPeerInterface->GetClockDifferential(sp.facilitator);
860 SLNet::Time serverTime = SLNet::GetTime() + clockDifferential;
861
862 if (oobId==ID_NAT_ESTABLISH_UNIDIRECTIONAL)
863 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString(RAK_TIME_FORMAT_STRING ": %s: OOB ID_NAT_ESTABLISH_UNIDIRECTIONAL to guid %s, system address %s.\n", serverTime, TestModeToString(sp.testMode), guidString, ipAddressString));
864 else
865 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString(RAK_TIME_FORMAT_STRING ": %s: OOB ID_NAT_ESTABLISH_BIDIRECTIONAL to guid %s, system address %s.\n", serverTime, TestModeToString(sp.testMode), guidString, ipAddressString));
866 }
867 }
868 void NatPunchthroughClient::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
869 {
870 (void) rakNetGUID;
871 (void) isIncoming;
872
873 // Try to track new port mappings on the router. Not reliable, but better than nothing.
874 SystemAddress ourExternalId = rakPeerInterface->GetExternalID(systemAddress);
875 if (ourExternalId!=UNASSIGNED_SYSTEM_ADDRESS && mostRecentExternalPort==0) {
876 mostRecentExternalPort=ourExternalId.GetPort();
877
878 if (natPunchthroughDebugInterface)
879 {
880 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("OnNewConnection mostRecentExternalPort first time set to %i", mostRecentExternalPort));
881 }
882 }
883
884 /*
885 unsigned int i;
886 i=0;
887 while (i < groupRequestsInProgress.Size())
888 {
889 if (groupRequestsInProgress[i].guid==rakNetGUID)
890 {
891 groupRequestsInProgress.RemoveAtIndexFast(i);
892 }
893 else
894 {
895 i++;
896 }
897 }
898 */
899 }
900
901 void NatPunchthroughClient::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
902 {
903 (void) systemAddress;
904 (void) rakNetGUID;
905 (void) lostConnectionReason;
906
907 if (sp.facilitator==systemAddress)
908 {
909 // If we lose the connection to the facilitator, all previous failures not currently in progress are returned as such
910 unsigned int i=0;
911 while (i < failedAttemptList.Size())
912 {
913 if (sp.nextActionTime!=0 && sp.targetGuid==failedAttemptList[i].guid)
914 {
915 i++;
916 continue;
917 }
918
919 PushFailure();
920
921 failedAttemptList.RemoveAtIndexFast(i);
922 }
923 }
924
925 /*
926 unsigned int i;
927 i=0;
928 while (i < groupPunchRequests.Size())
929 {
930 if (groupPunchRequests[i]->facilitator==systemAddress)
931 {
932 SLNet::OP_DELETE(groupPunchRequests[i],_FILE_AND_LINE_);
933 groupPunchRequests.RemoveAtIndexFast(i);
934 }
935 else
936 {
937 i++;
938 }
939 }
940 */
941
942 }
943 void NatPunchthroughClient::GetUPNPPortMappings(char *externalPort, char *internalPort, const SystemAddress &natPunchthroughServerAddress)
944 {
945 DataStructures::List< SLNet::RakNetSocket2* > sockets;
946 rakPeerInterface->GetSockets(sockets);
947 Itoa(sockets[0]->GetBoundAddress().GetPort(),internalPort,10);
948 if (mostRecentExternalPort==0)
949 mostRecentExternalPort=rakPeerInterface->GetExternalID(natPunchthroughServerAddress).GetPort();
950 Itoa(mostRecentExternalPort,externalPort,10);
951 }
952 void NatPunchthroughClient::OnFailureNotification(Packet *packet)
953 {
954 SLNet::BitStream incomingBs(packet->data,packet->length,false);
955 incomingBs.IgnoreBytes(sizeof(MessageID));
956 RakNetGUID senderGuid;
957 incomingBs.Read(senderGuid);
958
959 /*
960 unsigned int i;
961 i=0;
962 while (i < groupRequestsInProgress.Size())
963 {
964 if (groupRequestsInProgress[i].guid==senderGuid)
965 {
966 groupRequestsInProgress.RemoveAtIndexFast(i);
967 break;
968 }
969 else
970 {
971 i++;
972 }
973 }
974 */
975 }
976 void NatPunchthroughClient::OnGetMostRecentPort(Packet *packet)
977 {
978 SLNet::BitStream incomingBs(packet->data,packet->length,false);
979 incomingBs.IgnoreBytes(sizeof(MessageID));
980 uint16_t sessionId;
981 incomingBs.Read(sessionId);
982
983 SLNet::BitStream outgoingBs;
984 outgoingBs.Write((MessageID)ID_NAT_GET_MOST_RECENT_PORT);
985 outgoingBs.Write(sessionId);
986 if (mostRecentExternalPort==0)
987 {
988 mostRecentExternalPort=rakPeerInterface->GetExternalID(packet->systemAddress).GetPort();
989 RakAssert(mostRecentExternalPort!=0);
990
991 if (natPunchthroughDebugInterface)
992 {
993 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("OnGetMostRecentPort mostRecentExternalPort first time set to %i", mostRecentExternalPort));
994 }
995 }
996
997 unsigned short portWithStride;
998 if (hasPortStride==HAS_PORT_STRIDE)
999 portWithStride = mostRecentExternalPort + portStride;
1000 else
1001 portWithStride = mostRecentExternalPort;
1002 outgoingBs.Write(portWithStride);
1003
1004 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
1005 sp.facilitator=packet->systemAddress;
1006 }
1007 /*
1008 unsigned int NatPunchthroughClient::GetPendingOpenNATIndex(RakNetGUID destination, const SystemAddress &facilitator)
1009 {
1010 unsigned int i;
1011 for (i=0; i < pendingOpenNAT.Size(); i++)
1012 {
1013 if (pendingOpenNAT[i].destination==destination && pendingOpenNAT[i].facilitator==facilitator)
1014 return i;
1015 }
1016 return (unsigned int) -1;
1017 }
1018 */
1019 void NatPunchthroughClient::QueueOpenNAT(RakNetGUID destination, const SystemAddress &facilitator)
1020 {
1021 DSTAndFac daf;
1022 daf.destination=destination;
1023 daf.facilitator=facilitator;
1024 queuedOpenNat.Push(daf, _FILE_AND_LINE_);
1025 }
1026 void NatPunchthroughClient::SendQueuedOpenNAT(void)
1027 {
1028 while (queuedOpenNat.IsEmpty()==false)
1029 {
1030 DSTAndFac daf = queuedOpenNat.Pop();
1031 SendPunchthrough(daf.destination, daf.facilitator);
1032 }
1033 }
1034 void NatPunchthroughClient::SendPunchthrough(RakNetGUID destination, const SystemAddress &facilitator)
1035 {
1036 SLNet::BitStream outgoingBs;
1037 outgoingBs.Write((MessageID)ID_NAT_PUNCHTHROUGH_REQUEST);
1038 outgoingBs.Write(destination);
1039 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,facilitator,false);
1040
1041 // RakAssert(rakPeerInterface->GetSystemAddressFromGuid(destination)==UNASSIGNED_SYSTEM_ADDRESS);
1042
1043 if (natPunchthroughDebugInterface)
1044 {
1045 char guidString[128];
1046 destination.ToString(guidString, 128);
1047 natPunchthroughDebugInterface->OnClientMessage(SLNet::RakString("Starting ID_NAT_PUNCHTHROUGH_REQUEST to guid %s.", guidString));
1048 }
1049 }
1050 void NatPunchthroughClient::OnAttach(void)
1051 {
1052 Clear();
1053 }
1054 void NatPunchthroughClient::OnDetach(void)
1055 {
1056 Clear();
1057 }
1058 void NatPunchthroughClient::OnRakPeerShutdown(void)
1059 {
1060 Clear();
1061 }
1062 void NatPunchthroughClient::Clear(void)
1063 {
1064 OnReadyForNextPunchthrough();
1065
1066 failedAttemptList.Clear(false, _FILE_AND_LINE_);
1067
1068 queuedOpenNat.Clear(_FILE_AND_LINE_);
1069 /*
1070 groupRequestsInProgress.Clear(false, _FILE_AND_LINE_);
1071 unsigned int i;
1072 for (i=0; i < groupPunchRequests.Size(); i++)
1073 {
1074 SLNet::OP_DELETE(groupPunchRequests[i],_FILE_AND_LINE_);
1075 }
1076 groupPunchRequests.Clear(true, _FILE_AND_LINE_);
1077 */
1078 }
1079 PunchthroughConfiguration* NatPunchthroughClient::GetPunchthroughConfiguration(void)
1080 {
1081 return &pc;
1082 }
1083 void NatPunchthroughClient::OnReadyForNextPunchthrough(void)
1084 {
1085 if (rakPeerInterface==0)
1086 return;
1087
1088 sp.nextActionTime=0;
1089
1090 SLNet::BitStream outgoingBs;
1091 outgoingBs.Write((MessageID)ID_NAT_CLIENT_READY);
1092 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,sp.facilitator,false);
1093 }
1094
1095 void NatPunchthroughClient::PushSuccess(void)
1096 {
1097 Packet *p = AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char));
1098 p->data[0]=ID_NAT_PUNCHTHROUGH_SUCCEEDED;
1099 p->systemAddress=sp.targetAddress;
1100 p->systemAddress.systemIndex=(SystemIndex)-1;
1101 p->guid=sp.targetGuid;
1102 if (sp.weAreSender)
1103 p->data[1]=1;
1104 else
1105 p->data[1]=0;
1106 p->wasGeneratedLocally=true;
1107 rakPeerInterface->PushBackPacket(p, true);
1108 }
1109 bool NatPunchthroughClient::RemoveFromFailureQueue(void)
1110 {
1111 unsigned int i;
1112 for (i=0; i < failedAttemptList.Size(); i++)
1113 {
1114 if (failedAttemptList[i].guid==sp.targetGuid)
1115 {
1116 // Remove from failure queue
1117 failedAttemptList.RemoveAtIndexFast(i);
1118 return true;
1119 }
1120 }
1121 return false;
1122 }
1123
1124 void NatPunchthroughClient::IncrementExternalAttemptCount(SLNet::Time time, SLNet::Time delta)
1125 {
1126 if (++sp.retryCount>=pc.UDP_SENDS_PER_PORT_EXTERNAL)
1127 {
1128 ++sp.attemptCount;
1129 sp.retryCount=0;
1130 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_BETWEEN_PORTS-delta;
1131 sp.sentTTL=false;
1132 }
1133 else
1134 {
1135 sp.nextActionTime=time+pc.TIME_BETWEEN_PUNCH_ATTEMPTS_EXTERNAL-delta;
1136 }
1137 }
1138 /*
1139 // 0=failed, 1=success, 2=ignore
1140 void NatPunchthroughClient::UpdateGroupPunchOnNatResult(SystemAddress facilitator, RakNetGUID targetSystem, SystemAddress targetSystemAddress, int result)
1141 {
1142 GroupPunchRequest *gpr;
1143 unsigned long i,j,k;
1144 i=0;
1145 while (i < groupPunchRequests.Size())
1146 {
1147 gpr = groupPunchRequests[i];
1148 if (gpr->facilitator==facilitator)
1149 {
1150 j=0;
1151 while (j < gpr->pendingList.Size())
1152 {
1153 if (gpr->pendingList[j]==targetSystem)
1154 {
1155 if (result==0)
1156 {
1157 gpr->failedList.Push(targetSystem, _FILE_AND_LINE_);
1158 }
1159 else if (result==1)
1160 {
1161 gpr->passedListGuid.Push(targetSystem, _FILE_AND_LINE_);
1162 gpr->passedListAddress.Push(targetSystemAddress, _FILE_AND_LINE_);
1163 }
1164 else
1165 {
1166 gpr->ignoredList.Push(targetSystem, _FILE_AND_LINE_);
1167 }
1168 gpr->pendingList.RemoveAtIndex(j);
1169 }
1170 else
1171 j++;
1172 }
1173 }
1174 if (gpr->pendingList.Size()==0)
1175 {
1176 SLNet::BitStream output;
1177 if (gpr->failedList.Size()==0)
1178 {
1179 output.Write(ID_NAT_GROUP_PUNCH_SUCCEEDED);
1180 }
1181 else
1182 {
1183 output.Write(ID_NAT_GROUP_PUNCH_FAILED);
1184 }
1185
1186 output.WriteCasted<unsigned char>(gpr->passedListGuid.Size());
1187 for (k=0; k < gpr->passedListGuid.Size(); k++)
1188 {
1189 output.Write(gpr->passedListGuid[k]);
1190 output.Write(gpr->passedListAddress[k]);
1191 }
1192 output.WriteCasted<unsigned char>(gpr->ignoredList.Size());
1193 for (k=0; k < gpr->ignoredList.Size(); k++)
1194 {
1195 output.Write(gpr->ignoredList[k]);
1196 }
1197 output.WriteCasted<unsigned char>(gpr->failedList.Size());
1198 for (k=0; k < gpr->failedList.Size(); k++)
1199 {
1200 output.Write(gpr->failedList[k]);
1201 }
1202
1203 Packet *p = AllocatePacketUnified(output.GetNumberOfBytesUsed());
1204 p->systemAddress=gpr->facilitator;
1205 p->systemAddress.systemIndex=(SystemIndex)-1;
1206 p->guid=rakPeerInterface->GetGuidFromSystemAddress(gpr->facilitator);
1207 p->wasGeneratedLocally=true;
1208 memcpy(p->data, output.GetData(), output.GetNumberOfBytesUsed());
1209 rakPeerInterface->PushBackPacket(p, true);
1210
1211 groupPunchRequests.RemoveAtIndex(i);
1212 SLNet::OP_DELETE(gpr, _FILE_AND_LINE_);
1213 }
1214 else
1215 i++;
1216 }
1217 }
1218 */
1219
1220 #endif // _RAKNET_SUPPORT_*
1221