00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_NatPunchthroughClient==1
00003
00004 #include "NatPunchthroughClient.h"
00005 #include "BitStream.h"
00006 #include "MessageIdentifiers.h"
00007 #include "RakPeerInterface.h"
00008 #include "GetTime.h"
00009 #include "PacketLogger.h"
00010
00011 void NatPunchthroughDebugInterface_Printf::OnClientMessage(const char *msg)
00012 {
00013 printf("%s\n", msg);
00014 }
00015 #if _RAKNET_SUPPORT_PacketLogger==1
00016 void NatPunchthroughDebugInterface_PacketLogger::OnClientMessage(const char *msg)
00017 {
00018 if (pl)
00019 {
00020 pl->WriteMiscellaneous("Nat", msg);
00021 }
00022 }
00023 #endif
00024
00025 NatPunchthroughClient::NatPunchthroughClient()
00026 {
00027 natPunchthroughDebugInterface=0;
00028 mostRecentNewExternalPort=0;
00029 sp.nextActionTime=0;
00030 }
00031 NatPunchthroughClient::~NatPunchthroughClient()
00032 {
00033 rakPeerInterface=0;
00034 Clear();
00035 }
00036 bool NatPunchthroughClient::OpenNAT(RakNetGUID destination, SystemAddress facilitator)
00037 {
00038 if (rakPeerInterface->IsConnected(facilitator)==false)
00039 return false;
00040
00041 SystemAddress sa = rakPeerInterface->GetSystemAddressFromGuid(destination);
00042 if (sa!=UNASSIGNED_SYSTEM_ADDRESS && rakPeerInterface->IsConnected(sa,true,true) )
00043 return false;
00044
00045 SendPunchthrough(destination, facilitator);
00046 return true;
00047 }
00048 void NatPunchthroughClient::SetDebugInterface(NatPunchthroughDebugInterface *i)
00049 {
00050 natPunchthroughDebugInterface=i;
00051 }
00052 unsigned short NatPunchthroughClient::GetUPNPExternalPort(void) const
00053 {
00054 return mostRecentNewExternalPort;
00055 }
00056 unsigned short NatPunchthroughClient::GetUPNPInternalPort(void) const
00057 {
00058 return rakPeerInterface->GetInternalID(UNASSIGNED_SYSTEM_ADDRESS).port;
00059 }
00060 RakNet::RakString NatPunchthroughClient::GetUPNPInternalAddress(void) const
00061 {
00062 char dest[64];
00063 rakPeerInterface->GetInternalID(UNASSIGNED_SYSTEM_ADDRESS).ToString(false, dest);
00064 RakNet::RakString rs = dest;
00065 return rs;
00066 }
00067 void NatPunchthroughClient::Update(void)
00068 {
00069 RakNetTimeMS time = RakNet::GetTimeMS();
00070 if (sp.nextActionTime && sp.nextActionTime < time)
00071 {
00072 RakNetTimeMS delta = time - sp.nextActionTime;
00073 if (sp.testMode==SendPing::TESTING_INTERNAL_IPS)
00074 {
00075 SendOutOfBand(sp.internalIds[sp.attemptCount],ID_NAT_ESTABLISH_UNIDIRECTIONAL);
00076
00077 if (++sp.retryCount>=pc.UDP_SENDS_PER_PORT_INTERNAL)
00078 {
00079 ++sp.attemptCount;
00080 sp.retryCount=0;
00081 }
00082
00083 if (sp.attemptCount>=pc.MAXIMUM_NUMBER_OF_INTERNAL_IDS_TO_CHECK)
00084 {
00085 sp.testMode=SendPing::WAITING_FOR_INTERNAL_IPS_RESPONSE;
00086 if (pc.INTERNAL_IP_WAIT_AFTER_ATTEMPTS>0)
00087 {
00088 sp.nextActionTime=time+pc.INTERNAL_IP_WAIT_AFTER_ATTEMPTS-delta;
00089 }
00090 else
00091 {
00092 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FROM_FACILITATOR_PORT;
00093 sp.attemptCount=0;
00094 }
00095 }
00096 else
00097 {
00098 sp.nextActionTime=time+pc.TIME_BETWEEN_PUNCH_ATTEMPTS_INTERNAL-delta;
00099 }
00100 }
00101 else if (sp.testMode==SendPing::WAITING_FOR_INTERNAL_IPS_RESPONSE)
00102 {
00103 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FROM_FACILITATOR_PORT;
00104 sp.attemptCount=0;
00105 }
00106
00107 if (sp.testMode==SendPing::TESTING_EXTERNAL_IPS_FROM_FACILITATOR_PORT)
00108 {
00109 SystemAddress sa;
00110 sa=sp.targetAddress;
00111 int port = sa.port+sp.attemptCount;
00112 sa.port=(unsigned short) port;
00113 SendOutOfBand(sa,ID_NAT_ESTABLISH_UNIDIRECTIONAL);
00114
00115 if (++sp.retryCount>=pc.UDP_SENDS_PER_PORT_EXTERNAL)
00116 {
00117 ++sp.attemptCount;
00118 sp.retryCount=0;
00119 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_BETWEEN_PORTS-delta;
00120 }
00121 else
00122 {
00123 sp.nextActionTime=time+pc.TIME_BETWEEN_PUNCH_ATTEMPTS_EXTERNAL-delta;
00124 }
00125
00126 if (sp.attemptCount>=pc.MAX_PREDICTIVE_PORT_RANGE)
00127 {
00128
00129
00130
00131 sp.testMode=SendPing::WAITING_AFTER_ALL_ATTEMPTS;
00132 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_AFTER_ALL_ATTEMPTS-delta;
00133 }
00134 }
00135 else if (sp.testMode==SendPing::TESTING_EXTERNAL_IPS_FROM_1024)
00136 {
00137 SystemAddress sa;
00138 sa=sp.targetAddress;
00139 int port = 1024+sp.attemptCount;
00140 sa.port=(unsigned short) port;
00141 SendOutOfBand(sa,ID_NAT_ESTABLISH_UNIDIRECTIONAL);
00142
00143 if (++sp.retryCount>=pc.UDP_SENDS_PER_PORT_EXTERNAL)
00144 {
00145 ++sp.attemptCount;
00146 sp.retryCount=0;
00147 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_BETWEEN_PORTS-delta;
00148 }
00149 else
00150 {
00151 sp.nextActionTime=time+pc.TIME_BETWEEN_PUNCH_ATTEMPTS_EXTERNAL-delta;
00152 }
00153
00154 if (sp.attemptCount>=pc.MAX_PREDICTIVE_PORT_RANGE)
00155 {
00156 if (natPunchthroughDebugInterface)
00157 {
00158 char ipAddressString[32];
00159 sp.targetAddress.ToString(true, ipAddressString);
00160 char guidString[128];
00161 sp.targetGuid.ToString(guidString);
00162 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Likely bidirectional punchthrough failure to guid %s, system address %s.", guidString, ipAddressString));
00163 }
00164
00165 sp.testMode=SendPing::WAITING_AFTER_ALL_ATTEMPTS;
00166 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_AFTER_ALL_ATTEMPTS-delta;
00167 }
00168 }
00169 else if (sp.testMode==SendPing::WAITING_AFTER_ALL_ATTEMPTS)
00170 {
00171
00172 OnPunchthroughFailure();
00173 }
00174
00175 if (sp.testMode==SendPing::PUNCHING_FIXED_PORT)
00176 {
00177
00178 SendOutOfBand(sp.targetAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);
00179 if (++sp.retryCount>=sp.punchingFixedPortAttempts)
00180 {
00181 if (natPunchthroughDebugInterface)
00182 {
00183 char ipAddressString[32];
00184 sp.targetAddress.ToString(true, ipAddressString);
00185 char guidString[128];
00186 sp.targetGuid.ToString(guidString);
00187 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Likely unidirectional punchthrough failure to guid %s, system address %s.", guidString, ipAddressString));
00188 }
00189
00190 sp.testMode=SendPing::WAITING_AFTER_ALL_ATTEMPTS;
00191 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_AFTER_ALL_ATTEMPTS-delta;
00192 }
00193 else
00194 {
00195 if ((sp.retryCount%pc.UDP_SENDS_PER_PORT_EXTERNAL)==0)
00196 sp.nextActionTime=time+pc.EXTERNAL_IP_WAIT_BETWEEN_PORTS-delta;
00197 else
00198 sp.nextActionTime=time+pc.TIME_BETWEEN_PUNCH_ATTEMPTS_EXTERNAL-delta;
00199 }
00200 }
00201 }
00202 }
00203 void NatPunchthroughClient::PushFailure(void)
00204 {
00205 Packet *p = rakPeerInterface->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char));
00206 p->data[0]=ID_NAT_PUNCHTHROUGH_FAILED;
00207 p->systemAddress=sp.targetAddress;
00208 p->systemAddress.systemIndex=(SystemIndex)-1;
00209 p->guid=sp.targetGuid;
00210 if (sp.weAreSender)
00211 p->data[1]=1;
00212 else
00213 p->data[1]=0;
00214 rakPeerInterface->PushBackPacket(p, true);
00215 }
00216 void NatPunchthroughClient::OnPunchthroughFailure(void)
00217 {
00218 if (pc.retryOnFailure==false)
00219 {
00220 if (natPunchthroughDebugInterface)
00221 {
00222 char ipAddressString[32];
00223 sp.targetAddress.ToString(true, ipAddressString);
00224 char guidString[128];
00225 sp.targetGuid.ToString(guidString);
00226 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Failed punchthrough once. Returning failure to guid %s, system address %s to user.", guidString, ipAddressString));
00227 }
00228
00229 PushFailure();
00230 OnReadyForNextPunchthrough();
00231 return;
00232 }
00233
00234 unsigned int i;
00235 for (i=0; i < failedAttemptList.Size(); i++)
00236 {
00237 if (failedAttemptList[i].guid==sp.targetGuid)
00238 {
00239 if (natPunchthroughDebugInterface)
00240 {
00241 char ipAddressString[32];
00242 sp.targetAddress.ToString(true, ipAddressString);
00243 char guidString[128];
00244 sp.targetGuid.ToString(guidString);
00245 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Failed punchthrough twice. Returning failure to guid %s, system address %s to user.", guidString, ipAddressString));
00246 }
00247
00248
00249 PushFailure();
00250
00251 OnReadyForNextPunchthrough();
00252
00253 failedAttemptList.RemoveAtIndexFast(i);
00254 return;
00255 }
00256 }
00257
00258 if (rakPeerInterface->IsConnected(sp.facilitator)==false)
00259 {
00260 if (natPunchthroughDebugInterface)
00261 {
00262 char ipAddressString[32];
00263 sp.targetAddress.ToString(true, ipAddressString);
00264 char guidString[128];
00265 sp.targetGuid.ToString(guidString);
00266 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Not connected to facilitator, so cannot retry punchthrough after first failure. Returning failure onj guid %s, system address %s to user.", guidString, ipAddressString));
00267 }
00268
00269
00270 PushFailure();
00271 return;
00272 }
00273
00274 if (natPunchthroughDebugInterface)
00275 {
00276 char ipAddressString[32];
00277 sp.targetAddress.ToString(true, ipAddressString);
00278 char guidString[128];
00279 sp.targetGuid.ToString(guidString);
00280 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("First punchthrough failure on guid %s, system address %s. Reattempting.", guidString, ipAddressString));
00281 }
00282
00283
00284 AddrAndGuid aag;
00285 aag.addr=sp.targetAddress;
00286 aag.guid=sp.targetGuid;
00287 failedAttemptList.Push(aag, __FILE__, __LINE__);
00288
00289
00290 OnReadyForNextPunchthrough();
00291
00292
00293 if (sp.weAreSender)
00294 SendPunchthrough(sp.targetGuid, sp.facilitator);
00295 }
00296 PluginReceiveResult NatPunchthroughClient::OnReceive(Packet *packet)
00297 {
00298 switch (packet->data[0])
00299 {
00300 case ID_NAT_GET_MOST_RECENT_PORT:
00301 {
00302 OnGetMostRecentPort(packet);
00303 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00304 }
00305 case ID_OUT_OF_BAND_INTERNAL:
00306 if (packet->length>=2 &&
00307 (packet->data[1]==ID_NAT_ESTABLISH_UNIDIRECTIONAL || packet->data[1]==ID_NAT_ESTABLISH_BIDIRECTIONAL) &&
00308 sp.nextActionTime!=0)
00309 {
00310 RakNet::BitStream bs(packet->data,packet->length,false);
00311 bs.IgnoreBytes(2);
00312 uint16_t sessionId;
00313 bs.Read(sessionId);
00314
00315 if (sessionId!=sp.sessionId)
00316 break;
00317
00318 char ipAddressString[32];
00319 packet->systemAddress.ToString(true,ipAddressString);
00320 if (packet->data[1]==ID_NAT_ESTABLISH_UNIDIRECTIONAL)
00321 {
00322 if (natPunchthroughDebugInterface)
00323 {
00324 char guidString[128];
00325 sp.targetGuid.ToString(guidString);
00326 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Received ID_NAT_ESTABLISH_UNIDIRECTIONAL from guid %s, system address %s.", guidString, ipAddressString));
00327 }
00328 if (sp.testMode!=SendPing::PUNCHING_FIXED_PORT)
00329 {
00330 sp.testMode=SendPing::PUNCHING_FIXED_PORT;
00331 sp.retryCount+=sp.attemptCount*pc.UDP_SENDS_PER_PORT_EXTERNAL;
00332 sp.targetAddress=packet->systemAddress;
00333
00334
00335 sp.punchingFixedPortAttempts=pc.UDP_SENDS_PER_PORT_EXTERNAL*pc.MAX_PREDICTIVE_PORT_RANGE;
00336 }
00337
00338 SendOutOfBand(sp.targetAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);
00339 }
00340 else if (packet->data[1]==ID_NAT_ESTABLISH_BIDIRECTIONAL &&
00341 sp.targetGuid==packet->guid)
00342 {
00343
00344 bs.Read(mostRecentNewExternalPort);
00345
00346 SendOutOfBand(packet->systemAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);
00347
00348
00349 sp.targetAddress=packet->systemAddress;
00350 PushSuccess();
00351 OnReadyForNextPunchthrough();
00352
00353 bool removedFromFailureQueue=RemoveFromFailureQueue();
00354
00355 if (natPunchthroughDebugInterface)
00356 {
00357 char guidString[128];
00358 sp.targetGuid.ToString(guidString);
00359 if (removedFromFailureQueue)
00360 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough to guid %s, system address %s succeeded on 2nd attempt.", guidString, ipAddressString));
00361 else
00362 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough to guid %s, system address %s succeeded on 1st attempt.", guidString, ipAddressString));
00363 }
00364 }
00365
00366
00367 }
00368 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00369 case ID_NAT_ALREADY_IN_PROGRESS:
00370 {
00371 RakNet::BitStream incomingBs(packet->data, packet->length, false);
00372 incomingBs.IgnoreBytes(sizeof(MessageID));
00373 RakNetGUID targetGuid;
00374 incomingBs.Read(targetGuid);
00375 if (natPunchthroughDebugInterface)
00376 {
00377 char guidString[128];
00378 targetGuid.ToString(guidString);
00379 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough retry to guid %s failed due to ID_NAT_ALREADY_IN_PROGRESS. Returning failure.", guidString));
00380 }
00381
00382 }
00383 break;
00384 case ID_NAT_TARGET_NOT_CONNECTED:
00385 case ID_NAT_CONNECTION_TO_TARGET_LOST:
00386 case ID_NAT_TARGET_UNRESPONSIVE:
00387 {
00388 char *reason;
00389 if (packet->data[0]==ID_NAT_TARGET_NOT_CONNECTED)
00390 reason="ID_NAT_TARGET_NOT_CONNECTED";
00391 else if (packet->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST)
00392 reason="ID_NAT_CONNECTION_TO_TARGET_LOST";
00393 else
00394 reason="ID_NAT_TARGET_UNRESPONSIVE";
00395
00396 RakNet::BitStream incomingBs(packet->data, packet->length, false);
00397 incomingBs.IgnoreBytes(sizeof(MessageID));
00398
00399 RakNetGUID targetGuid;
00400 incomingBs.Read(targetGuid);
00401 if (packet->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST ||
00402 packet->data[0]==ID_NAT_TARGET_UNRESPONSIVE)
00403 {
00404 uint16_t sessionId;
00405 incomingBs.Read(sessionId);
00406 if (sessionId!=sp.sessionId)
00407 break;
00408 }
00409
00410 unsigned int i;
00411 for (i=0; i < failedAttemptList.Size(); i++)
00412 {
00413 if (failedAttemptList[i].guid==targetGuid)
00414 {
00415 if (natPunchthroughDebugInterface)
00416 {
00417 char guidString[128];
00418 targetGuid.ToString(guidString);
00419 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough retry to guid %s failed due to %s.", guidString, reason));
00420
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 failedAttemptList.RemoveAtIndexFast(i);
00436 break;
00437 }
00438 }
00439
00440 if (natPunchthroughDebugInterface)
00441 {
00442 char guidString[128];
00443 targetGuid.ToString(guidString);
00444 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough attempt to guid %s failed due to %s.", guidString, reason));
00445 }
00446
00447
00448 sp.nextActionTime=0;
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 }
00476 break;
00477 case ID_TIMESTAMP:
00478 if (packet->data[sizeof(MessageID)+sizeof(RakNetTime)]==ID_NAT_CONNECT_AT_TIME)
00479 {
00480 OnConnectAtTime(packet);
00481 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00482 }
00483 break;
00484 }
00485 return RR_CONTINUE_PROCESSING;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 void NatPunchthroughClient::OnConnectAtTime(Packet *packet)
00502 {
00503
00504
00505 RakNet::BitStream bs(packet->data, packet->length, false);
00506 bs.IgnoreBytes(sizeof(MessageID));
00507 bs.Read(sp.nextActionTime);
00508 bs.IgnoreBytes(sizeof(MessageID));
00509 bs.Read(sp.sessionId);
00510 bs.Read(sp.targetAddress);
00511
00512 int j;
00513 for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++)
00514 bs.Read(sp.internalIds[j]);
00515 sp.attemptCount=0;
00516 sp.retryCount=0;
00517 if (pc.MAXIMUM_NUMBER_OF_INTERNAL_IDS_TO_CHECK>0)
00518 {
00519 sp.testMode=SendPing::TESTING_INTERNAL_IPS;
00520 }
00521 else
00522 {
00523 sp.testMode=SendPing::TESTING_EXTERNAL_IPS_FROM_FACILITATOR_PORT;
00524 }
00525 bs.Read(sp.targetGuid);
00526 bs.Read(sp.weAreSender);
00527
00528
00529 }
00530 void NatPunchthroughClient::SendTTL(SystemAddress sa)
00531 {
00532 if (sa==UNASSIGNED_SYSTEM_ADDRESS)
00533 return;
00534 if (sa.port==0)
00535 return;
00536
00537 char ipAddressString[32];
00538 sa.ToString(false, ipAddressString);
00539 rakPeerInterface->SendTTL(ipAddressString,sa.port, 3);
00540 }
00541 void NatPunchthroughClient::SendOutOfBand(SystemAddress sa, MessageID oobId)
00542 {
00543 if (sa==UNASSIGNED_SYSTEM_ADDRESS)
00544 return;
00545 if (sa.port==0)
00546 return;
00547
00548
00549
00550 RakNet::BitStream oob;
00551 oob.Write(oobId);
00552 oob.Write(sp.sessionId);
00553
00554 if (oobId==ID_NAT_ESTABLISH_BIDIRECTIONAL)
00555 oob.Write(sa.port);
00556 char ipAddressString[32];
00557 sa.ToString(false, ipAddressString);
00558 rakPeerInterface->SendOutOfBand((const char*) ipAddressString,sa.port,(const char*) oob.GetData(),oob.GetNumberOfBytesUsed());
00559
00560 if (natPunchthroughDebugInterface)
00561 {
00562 sa.ToString(true,ipAddressString);
00563 char guidString[128];
00564 sp.targetGuid.ToString(guidString);
00565
00566 if (oobId==ID_NAT_ESTABLISH_UNIDIRECTIONAL)
00567 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Sent OOB ID_NAT_ESTABLISH_UNIDIRECTIONAL to guid %s, system address %s.", guidString, ipAddressString));
00568 else
00569 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Sent OOB ID_NAT_ESTABLISH_BIDIRECTIONAL to guid %s, system address %s.", guidString, ipAddressString));
00570 }
00571 }
00572 void NatPunchthroughClient::OnNewConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
00573 {
00574 (void) rakNetGUID;
00575 (void) isIncoming;
00576
00577
00578 SystemAddress ourExternalId = rakPeerInterface->GetExternalID(systemAddress);
00579 if (ourExternalId!=UNASSIGNED_SYSTEM_ADDRESS)
00580 mostRecentNewExternalPort=ourExternalId.port;
00581 }
00582
00583 void NatPunchthroughClient::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
00584 {
00585 (void) systemAddress;
00586 (void) rakNetGUID;
00587 (void) lostConnectionReason;
00588
00589 if (sp.facilitator==systemAddress)
00590 {
00591
00592 unsigned int i=0;
00593 while (i < failedAttemptList.Size())
00594 {
00595 if (sp.nextActionTime!=0 && sp.targetGuid==failedAttemptList[i].guid)
00596 {
00597 i++;
00598 continue;
00599 }
00600
00601 PushFailure();
00602
00603 failedAttemptList.RemoveAtIndexFast(i);
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 }
00649 void NatPunchthroughClient::OnGetMostRecentPort(Packet *packet)
00650 {
00651 RakNet::BitStream incomingBs(packet->data,packet->length,false);
00652 incomingBs.IgnoreBytes(sizeof(MessageID));
00653 uint16_t sessionId;
00654 incomingBs.Read(sessionId);
00655
00656 RakNet::BitStream outgoingBs;
00657 outgoingBs.Write((MessageID)ID_NAT_GET_MOST_RECENT_PORT);
00658 outgoingBs.Write(sessionId);
00659 outgoingBs.Write(mostRecentNewExternalPort);
00660 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
00661 sp.facilitator=packet->systemAddress;
00662 }
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675 void NatPunchthroughClient::SendPunchthrough(RakNetGUID destination, SystemAddress facilitator)
00676 {
00677 RakNet::BitStream outgoingBs;
00678 outgoingBs.Write((MessageID)ID_NAT_PUNCHTHROUGH_REQUEST);
00679 outgoingBs.Write(destination);
00680 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,facilitator,false);
00681
00682
00683
00684 if (natPunchthroughDebugInterface)
00685 {
00686 char guidString[128];
00687 destination.ToString(guidString);
00688 natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Starting ID_NAT_PUNCHTHROUGH_REQUEST to guid %s.", guidString));
00689 }
00690 }
00691 void NatPunchthroughClient::OnAttach(void)
00692 {
00693 Clear();
00694 }
00695 void NatPunchthroughClient::OnDetach(void)
00696 {
00697 Clear();
00698 }
00699 void NatPunchthroughClient::OnRakPeerShutdown(void)
00700 {
00701 Clear();
00702 }
00703 void NatPunchthroughClient::Clear(void)
00704 {
00705 OnReadyForNextPunchthrough();
00706
00707 failedAttemptList.Clear(false, __FILE__,__LINE__);
00708 }
00709 PunchthroughConfiguration* NatPunchthroughClient::GetPunchthroughConfiguration(void)
00710 {
00711 return &pc;
00712 }
00713 void NatPunchthroughClient::OnReadyForNextPunchthrough(void)
00714 {
00715 if (rakPeerInterface==0)
00716 return;
00717
00718 sp.nextActionTime=0;
00719
00720 RakNet::BitStream outgoingBs;
00721 outgoingBs.Write((MessageID)ID_NAT_CLIENT_READY);
00722 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,sp.facilitator,false);
00723 }
00724
00725 void NatPunchthroughClient::PushSuccess(void)
00726 {
00727
00728
00729 Packet *p = rakPeerInterface->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char));
00730 p->data[0]=ID_NAT_PUNCHTHROUGH_SUCCEEDED;
00731 p->systemAddress=sp.targetAddress;
00732 p->systemAddress.systemIndex=(SystemIndex)-1;
00733 p->guid=sp.targetGuid;
00734 if (sp.weAreSender)
00735 p->data[1]=1;
00736 else
00737 p->data[1]=0;
00738 rakPeerInterface->PushBackPacket(p, true);
00739 }
00740
00741 bool NatPunchthroughClient::RemoveFromFailureQueue(void)
00742 {
00743 unsigned int i;
00744 for (i=0; i < failedAttemptList.Size(); i++)
00745 {
00746 if (failedAttemptList[i].guid==sp.targetGuid)
00747 {
00748
00749 failedAttemptList.RemoveAtIndexFast(i);
00750 return true;
00751 }
00752 }
00753 return false;
00754 }
00755
00756 #endif // _RAKNET_SUPPORT_*
00757