NatPunchthroughServer.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. /*
  2. * 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. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "NativeFeatureIncludes.h"
  11. #if _RAKNET_SUPPORT_NatPunchthroughServer==1
  12. #include "NatPunchthroughServer.h"
  13. #include "SocketLayer.h"
  14. #include "BitStream.h"
  15. #include "MessageIdentifiers.h"
  16. #include "RakPeerInterface.h"
  17. #include "MTUSize.h"
  18. #include "GetTime.h"
  19. #include "PacketLogger.h"
  20. using namespace RakNet;
  21. void NatPunchthroughServerDebugInterface_Printf::OnServerMessage(const char *msg)
  22. {
  23. printf("%s\n", msg);
  24. }
  25. #if _RAKNET_SUPPORT_PacketLogger==1
  26. void NatPunchthroughServerDebugInterface_PacketLogger::OnServerMessage(const char *msg)
  27. {
  28. if (pl)
  29. {
  30. pl->WriteMiscellaneous("Nat", msg);
  31. }
  32. }
  33. #endif
  34. void NatPunchthroughServer::User::DeleteConnectionAttempt(NatPunchthroughServer::ConnectionAttempt *ca)
  35. {
  36. unsigned int index = connectionAttempts.GetIndexOf(ca);
  37. if ((unsigned int)index!=(unsigned int)-1)
  38. {
  39. RakNet::OP_DELETE(ca,_FILE_AND_LINE_);
  40. connectionAttempts.RemoveAtIndex(index);
  41. }
  42. }
  43. void NatPunchthroughServer::User::DerefConnectionAttempt(NatPunchthroughServer::ConnectionAttempt *ca)
  44. {
  45. unsigned int index = connectionAttempts.GetIndexOf(ca);
  46. if ((unsigned int)index!=(unsigned int)-1)
  47. {
  48. connectionAttempts.RemoveAtIndex(index);
  49. }
  50. }
  51. bool NatPunchthroughServer::User::HasConnectionAttemptToUser(User *user)
  52. {
  53. unsigned int index;
  54. for (index=0; index < connectionAttempts.Size(); index++)
  55. {
  56. if (connectionAttempts[index]->recipient->guid==user->guid ||
  57. connectionAttempts[index]->sender->guid==user->guid)
  58. return true;
  59. }
  60. return false;
  61. }
  62. void NatPunchthroughServer::User::LogConnectionAttempts(RakNet::RakString &rs)
  63. {
  64. rs.Clear();
  65. unsigned int index;
  66. char guidStr[128], ipStr[128];
  67. guid.ToString(guidStr);
  68. systemAddress.ToString(true,ipStr);
  69. rs=RakNet::RakString("User systemAddress=%s guid=%s\n", ipStr, guidStr);
  70. rs+=RakNet::RakString("%i attempts in list:\n", connectionAttempts.Size());
  71. for (index=0; index < connectionAttempts.Size(); index++)
  72. {
  73. rs+=RakNet::RakString("%i. SessionID=%i ", index+1, connectionAttempts[index]->sessionId);
  74. if (connectionAttempts[index]->sender==this)
  75. rs+="(We are sender) ";
  76. else
  77. rs+="(We are recipient) ";
  78. if (isReady)
  79. rs+="(READY TO START) ";
  80. else
  81. rs+="(NOT READY TO START) ";
  82. if (connectionAttempts[index]->attemptPhase==NatPunchthroughServer::ConnectionAttempt::NAT_ATTEMPT_PHASE_NOT_STARTED)
  83. rs+="(NOT_STARTED). ";
  84. else
  85. rs+="(GETTING_RECENT_PORTS). ";
  86. if (connectionAttempts[index]->sender==this)
  87. {
  88. connectionAttempts[index]->recipient->guid.ToString(guidStr);
  89. connectionAttempts[index]->recipient->systemAddress.ToString(true,ipStr);
  90. }
  91. else
  92. {
  93. connectionAttempts[index]->sender->guid.ToString(guidStr);
  94. connectionAttempts[index]->sender->systemAddress.ToString(true,ipStr);
  95. }
  96. rs+=RakNet::RakString("Target systemAddress=%s, guid=%s.\n", ipStr, guidStr);
  97. }
  98. }
  99. int RakNet::NatPunchthroughServer::NatPunchthroughUserComp( const RakNetGUID &key, User * const &data )
  100. {
  101. if (key < data->guid)
  102. return -1;
  103. if (key > data->guid)
  104. return 1;
  105. return 0;
  106. }
  107. STATIC_FACTORY_DEFINITIONS(NatPunchthroughServer,NatPunchthroughServer);
  108. NatPunchthroughServer::NatPunchthroughServer()
  109. {
  110. lastUpdate=0;
  111. sessionId=0;
  112. natPunchthroughServerDebugInterface=0;
  113. for (int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
  114. boundAddresses[i]=UNASSIGNED_SYSTEM_ADDRESS;
  115. boundAddressCount=0;
  116. }
  117. NatPunchthroughServer::~NatPunchthroughServer()
  118. {
  119. User *user, *otherUser;
  120. ConnectionAttempt *connectionAttempt;
  121. unsigned int j;
  122. while(users.Size())
  123. {
  124. user = users[0];
  125. for (j=0; j < user->connectionAttempts.Size(); j++)
  126. {
  127. connectionAttempt=user->connectionAttempts[j];
  128. if (connectionAttempt->sender==user)
  129. otherUser=connectionAttempt->recipient;
  130. else
  131. otherUser=connectionAttempt->sender;
  132. otherUser->DeleteConnectionAttempt(connectionAttempt);
  133. }
  134. RakNet::OP_DELETE(user,_FILE_AND_LINE_);
  135. users[0]=users[users.Size()-1];
  136. users.RemoveAtIndex(users.Size()-1);
  137. }
  138. }
  139. void NatPunchthroughServer::SetDebugInterface(NatPunchthroughServerDebugInterface *i)
  140. {
  141. natPunchthroughServerDebugInterface=i;
  142. }
  143. void NatPunchthroughServer::Update(void)
  144. {
  145. ConnectionAttempt *connectionAttempt;
  146. User *user, *recipient;
  147. unsigned int i,j;
  148. RakNet::Time time = RakNet::GetTime();
  149. if (time > lastUpdate+250)
  150. {
  151. lastUpdate=time;
  152. for (i=0; i < users.Size(); i++)
  153. {
  154. user=users[i];
  155. for (j=0; j < user->connectionAttempts.Size(); j++)
  156. {
  157. connectionAttempt=user->connectionAttempts[j];
  158. if (connectionAttempt->sender==user)
  159. {
  160. if (connectionAttempt->attemptPhase!=ConnectionAttempt::NAT_ATTEMPT_PHASE_NOT_STARTED &&
  161. time > connectionAttempt->startTime &&
  162. time > 10000 + connectionAttempt->startTime ) // Formerly 5000, but sometimes false positives
  163. {
  164. RakNet::BitStream outgoingBs;
  165. // that other system might not be running the plugin
  166. outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE);
  167. outgoingBs.Write(connectionAttempt->recipient->guid);
  168. outgoingBs.Write(connectionAttempt->sessionId);
  169. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->sender->systemAddress,false);
  170. // 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST
  171. // However, recipient may be expecting it due to external code
  172. // In that case, recipient would never get any response if the sender dropped
  173. outgoingBs.Reset();
  174. outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE);
  175. outgoingBs.Write(connectionAttempt->sender->guid);
  176. outgoingBs.Write(connectionAttempt->sessionId);
  177. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->recipient->systemAddress,false);
  178. connectionAttempt->sender->isReady=true;
  179. connectionAttempt->recipient->isReady=true;
  180. recipient=connectionAttempt->recipient;
  181. if (natPunchthroughServerDebugInterface)
  182. {
  183. char str[1024];
  184. char addr1[128], addr2[128];
  185. // 8/01/09 Fixed bug where this was after DeleteConnectionAttempt()
  186. connectionAttempt->sender->systemAddress.ToString(true,addr1);
  187. connectionAttempt->recipient->systemAddress.ToString(true,addr2);
  188. sprintf(str, "Sending ID_NAT_TARGET_UNRESPONSIVE to sender %s and recipient %s.", addr1, addr2);
  189. natPunchthroughServerDebugInterface->OnServerMessage(str);
  190. RakNet::RakString log;
  191. connectionAttempt->sender->LogConnectionAttempts(log);
  192. connectionAttempt->recipient->LogConnectionAttempts(log);
  193. }
  194. connectionAttempt->sender->DerefConnectionAttempt(connectionAttempt);
  195. connectionAttempt->recipient->DeleteConnectionAttempt(connectionAttempt);
  196. StartPunchthroughForUser(user);
  197. StartPunchthroughForUser(recipient);
  198. break;
  199. }
  200. }
  201. }
  202. }
  203. }
  204. }
  205. PluginReceiveResult NatPunchthroughServer::OnReceive(Packet *packet)
  206. {
  207. switch (packet->data[0])
  208. {
  209. case ID_NAT_PUNCHTHROUGH_REQUEST:
  210. OnNATPunchthroughRequest(packet);
  211. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  212. case ID_NAT_GET_MOST_RECENT_PORT:
  213. OnGetMostRecentPort(packet);
  214. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  215. case ID_NAT_CLIENT_READY:
  216. OnClientReady(packet);
  217. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  218. case ID_NAT_REQUEST_BOUND_ADDRESSES:
  219. {
  220. RakNet::BitStream outgoingBs;
  221. outgoingBs.Write((MessageID)ID_NAT_RESPOND_BOUND_ADDRESSES);
  222. if (boundAddresses[0]==UNASSIGNED_SYSTEM_ADDRESS)
  223. {
  224. DataStructures::List<RakNetSocket2* > sockets;
  225. rakPeerInterface->GetSockets(sockets);
  226. for (int i=0; i < sockets.Size() && i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
  227. {
  228. boundAddresses[i]=sockets[i]->GetBoundAddress();
  229. boundAddressCount++;
  230. }
  231. }
  232. outgoingBs.Write(boundAddressCount);
  233. for (int i=0; i < boundAddressCount; i++)
  234. {
  235. outgoingBs.Write(boundAddresses[i]);
  236. }
  237. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
  238. }
  239. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  240. case ID_NAT_PING:
  241. {
  242. }
  243. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  244. case ID_OUT_OF_BAND_INTERNAL:
  245. if (packet->length>=2 && packet->data[1]==ID_NAT_PING)
  246. {
  247. RakNet::BitStream bs(packet->data,packet->length,false);
  248. bs.IgnoreBytes(sizeof(MessageID)*2);
  249. uint16_t externalPort;
  250. bs.Read(externalPort);
  251. RakNet::BitStream outgoingBs;
  252. outgoingBs.Write((MessageID)ID_NAT_PONG);
  253. outgoingBs.Write(externalPort);
  254. uint16_t externalPort2 = packet->systemAddress.GetPort();
  255. outgoingBs.Write(externalPort2);
  256. rakPeerInterface->SendOutOfBand((const char*) packet->systemAddress.ToString(false),packet->systemAddress.GetPort(),(const char*) outgoingBs.GetData(),outgoingBs.GetNumberOfBytesUsed());
  257. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  258. }
  259. }
  260. return RR_CONTINUE_PROCESSING;
  261. }
  262. void NatPunchthroughServer::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
  263. {
  264. (void) lostConnectionReason;
  265. (void) systemAddress;
  266. unsigned int i=0;
  267. bool objectExists;
  268. i = users.GetIndexFromKey(rakNetGUID, &objectExists);
  269. if (objectExists)
  270. {
  271. RakNet::BitStream outgoingBs;
  272. DataStructures::List<User *> freedUpInProgressUsers;
  273. User *user = users[i];
  274. User *otherUser;
  275. unsigned int connectionAttemptIndex;
  276. ConnectionAttempt *connectionAttempt;
  277. for (connectionAttemptIndex=0; connectionAttemptIndex < user->connectionAttempts.Size(); connectionAttemptIndex++)
  278. {
  279. connectionAttempt=user->connectionAttempts[connectionAttemptIndex];
  280. outgoingBs.Reset();
  281. if (connectionAttempt->recipient==user)
  282. {
  283. otherUser=connectionAttempt->sender;
  284. }
  285. else
  286. {
  287. otherUser=connectionAttempt->recipient;
  288. }
  289. // 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST
  290. // However, recipient may be expecting it due to external code
  291. // In that case, recipient would never get any response if the sender dropped
  292. outgoingBs.Write((MessageID)ID_NAT_CONNECTION_TO_TARGET_LOST);
  293. outgoingBs.Write(rakNetGUID);
  294. outgoingBs.Write(connectionAttempt->sessionId);
  295. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,otherUser->systemAddress,false);
  296. // 4/22/09 - Bug: was checking inProgress, legacy variable not used elsewhere
  297. if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS)
  298. {
  299. otherUser->isReady=true;
  300. freedUpInProgressUsers.Insert(otherUser, _FILE_AND_LINE_ );
  301. }
  302. otherUser->DeleteConnectionAttempt(connectionAttempt);
  303. }
  304. RakNet::OP_DELETE(users[i], _FILE_AND_LINE_);
  305. users.RemoveAtIndex(i);
  306. for (i=0; i < freedUpInProgressUsers.Size(); i++)
  307. {
  308. StartPunchthroughForUser(freedUpInProgressUsers[i]);
  309. }
  310. }
  311. /*
  312. // Also remove from groupPunchthroughRequests
  313. for (i=0; i < users.Size(); i++)
  314. {
  315. bool objectExists;
  316. unsigned int gprIndex;
  317. gprIndex = users[i]->groupPunchthroughRequests.GetIndexFromKey(rakNetGUID, &objectExists);
  318. if (objectExists)
  319. {
  320. // printf("DEBUG %i\n", __LINE__);
  321. RakNet::BitStream outgoingBs;
  322. outgoingBs.Write((MessageID)ID_NAT_TARGET_NOT_CONNECTED);
  323. outgoingBs.Write(rakNetGUID);
  324. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,users[i]->systemAddress,false);
  325. users[i]->groupPunchthroughRequests.RemoveAtIndex(gprIndex);
  326. }
  327. }
  328. */
  329. }
  330. void NatPunchthroughServer::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
  331. {
  332. (void) systemAddress;
  333. (void) isIncoming;
  334. User *user = RakNet::OP_NEW<User>(_FILE_AND_LINE_);
  335. user->guid=rakNetGUID;
  336. user->mostRecentPort=0;
  337. user->systemAddress=systemAddress;
  338. user->isReady=true;
  339. users.Insert(rakNetGUID, user, true, _FILE_AND_LINE_);
  340. // printf("Adding to users %s\n", rakNetGUID.ToString());
  341. // printf("DEBUG users[0] guid=%s\n", users[0]->guid.ToString());
  342. }
  343. void NatPunchthroughServer::OnNATPunchthroughRequest(Packet *packet)
  344. {
  345. RakNet::BitStream outgoingBs;
  346. RakNet::BitStream incomingBs(packet->data, packet->length, false);
  347. incomingBs.IgnoreBytes(sizeof(MessageID));
  348. RakNetGUID recipientGuid, senderGuid;
  349. incomingBs.Read(recipientGuid);
  350. senderGuid=packet->guid;
  351. unsigned int i;
  352. bool objectExists;
  353. i = users.GetIndexFromKey(senderGuid, &objectExists);
  354. RakAssert(objectExists);
  355. ConnectionAttempt *ca = RakNet::OP_NEW<ConnectionAttempt>(_FILE_AND_LINE_);
  356. ca->sender=users[i];
  357. ca->sessionId=sessionId++;
  358. i = users.GetIndexFromKey(recipientGuid, &objectExists);
  359. if (objectExists==false || ca->sender == ca->recipient)
  360. {
  361. // printf("DEBUG %i\n", __LINE__);
  362. // printf("DEBUG recipientGuid=%s\n", recipientGuid.ToString());
  363. // printf("DEBUG users[0] guid=%s\n", users[0]->guid.ToString());
  364. outgoingBs.Write((MessageID)ID_NAT_TARGET_NOT_CONNECTED);
  365. outgoingBs.Write(recipientGuid);
  366. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
  367. RakNet::OP_DELETE(ca,_FILE_AND_LINE_);
  368. return;
  369. }
  370. ca->recipient=users[i];
  371. if (ca->recipient->HasConnectionAttemptToUser(ca->sender))
  372. {
  373. outgoingBs.Write((MessageID)ID_NAT_ALREADY_IN_PROGRESS);
  374. outgoingBs.Write(recipientGuid);
  375. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
  376. RakNet::OP_DELETE(ca,_FILE_AND_LINE_);
  377. return;
  378. }
  379. ca->sender->connectionAttempts.Insert(ca, _FILE_AND_LINE_ );
  380. ca->recipient->connectionAttempts.Insert(ca, _FILE_AND_LINE_ );
  381. StartPunchthroughForUser(ca->sender);
  382. }
  383. void NatPunchthroughServer::OnClientReady(Packet *packet)
  384. {
  385. unsigned int i;
  386. bool objectExists;
  387. i = users.GetIndexFromKey(packet->guid, &objectExists);
  388. if (objectExists)
  389. {
  390. users[i]->isReady=true;
  391. StartPunchthroughForUser(users[i]);
  392. }
  393. }
  394. void NatPunchthroughServer::OnGetMostRecentPort(Packet *packet)
  395. {
  396. RakNet::BitStream bsIn(packet->data, packet->length, false);
  397. bsIn.IgnoreBytes(sizeof(MessageID));
  398. uint16_t sessionId;
  399. unsigned short mostRecentPort;
  400. bsIn.Read(sessionId);
  401. bsIn.Read(mostRecentPort);
  402. unsigned int i,j;
  403. User *user;
  404. ConnectionAttempt *connectionAttempt;
  405. bool objectExists;
  406. i = users.GetIndexFromKey(packet->guid, &objectExists);
  407. if (natPunchthroughServerDebugInterface)
  408. {
  409. RakNet::RakString log;
  410. char addr1[128], addr2[128];
  411. packet->systemAddress.ToString(true,addr1);
  412. packet->guid.ToString(addr2);
  413. log=RakNet::RakString("Got ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s. port=%i. sessionId=%i. userFound=%i.", addr1, addr2, mostRecentPort, sessionId, objectExists);
  414. natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
  415. }
  416. if (objectExists)
  417. {
  418. user=users[i];
  419. user->mostRecentPort=mostRecentPort;
  420. RakNet::Time time = RakNet::GetTime();
  421. for (j=0; j < user->connectionAttempts.Size(); j++)
  422. {
  423. connectionAttempt=user->connectionAttempts[j];
  424. if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS &&
  425. connectionAttempt->sender->mostRecentPort!=0 &&
  426. connectionAttempt->recipient->mostRecentPort!=0 &&
  427. // 04/29/08 add sessionId to prevent processing for other systems
  428. connectionAttempt->sessionId==sessionId)
  429. {
  430. SystemAddress senderSystemAddress = connectionAttempt->sender->systemAddress;
  431. SystemAddress recipientSystemAddress = connectionAttempt->recipient->systemAddress;
  432. SystemAddress recipientTargetAddress = recipientSystemAddress;
  433. SystemAddress senderTargetAddress = senderSystemAddress;
  434. recipientTargetAddress.SetPortHostOrder(connectionAttempt->recipient->mostRecentPort);
  435. senderTargetAddress.SetPortHostOrder(connectionAttempt->sender->mostRecentPort);
  436. // Pick a time far enough in the future that both systems will have gotten the message
  437. int targetPing = rakPeerInterface->GetAveragePing(recipientTargetAddress);
  438. int senderPing = rakPeerInterface->GetAveragePing(senderSystemAddress);
  439. RakNet::Time simultaneousAttemptTime;
  440. if (targetPing==-1 || senderPing==-1)
  441. simultaneousAttemptTime = time + 1500;
  442. else
  443. {
  444. int largerPing = targetPing > senderPing ? targetPing : senderPing;
  445. if (largerPing * 4 < 100)
  446. simultaneousAttemptTime = time + 100;
  447. else
  448. simultaneousAttemptTime = time + (largerPing * 4);
  449. }
  450. if (natPunchthroughServerDebugInterface)
  451. {
  452. RakNet::RakString log;
  453. char addr1[128], addr2[128];
  454. recipientSystemAddress.ToString(true,addr1);
  455. connectionAttempt->recipient->guid.ToString(addr2);
  456. log=RakNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to recipient systemAddress %s guid %s", addr1, addr2);
  457. natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
  458. }
  459. // Send to recipient timestamped message to connect at time
  460. RakNet::BitStream bsOut;
  461. bsOut.Write((MessageID)ID_TIMESTAMP);
  462. bsOut.Write(simultaneousAttemptTime);
  463. bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME);
  464. bsOut.Write(connectionAttempt->sessionId);
  465. bsOut.Write(senderTargetAddress); // Public IP, using most recent port
  466. for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP
  467. bsOut.Write(rakPeerInterface->GetInternalID(senderSystemAddress,j));
  468. bsOut.Write(connectionAttempt->sender->guid);
  469. bsOut.Write(false);
  470. rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,recipientSystemAddress,false);
  471. if (natPunchthroughServerDebugInterface)
  472. {
  473. RakNet::RakString log;
  474. char addr1[128], addr2[128];
  475. senderSystemAddress.ToString(true,addr1);
  476. connectionAttempt->sender->guid.ToString(addr2);
  477. log=RakNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to sender systemAddress %s guid %s", addr1, addr2);
  478. natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
  479. }
  480. // Same for sender
  481. bsOut.Reset();
  482. bsOut.Write((MessageID)ID_TIMESTAMP);
  483. bsOut.Write(simultaneousAttemptTime);
  484. bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME);
  485. bsOut.Write(connectionAttempt->sessionId);
  486. bsOut.Write(recipientTargetAddress); // Public IP, using most recent port
  487. for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP
  488. bsOut.Write(rakPeerInterface->GetInternalID(recipientSystemAddress,j));
  489. bsOut.Write(connectionAttempt->recipient->guid);
  490. bsOut.Write(true);
  491. rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,senderSystemAddress,false);
  492. connectionAttempt->recipient->DerefConnectionAttempt(connectionAttempt);
  493. connectionAttempt->sender->DeleteConnectionAttempt(connectionAttempt);
  494. // 04/29/08 missing return
  495. return;
  496. }
  497. }
  498. }
  499. else
  500. {
  501. if (natPunchthroughServerDebugInterface)
  502. {
  503. RakNet::RakString log;
  504. char addr1[128], addr2[128];
  505. packet->systemAddress.ToString(true,addr1);
  506. packet->guid.ToString(addr2);
  507. log=RakNet::RakString("Ignoring ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s", addr1, addr2);
  508. natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
  509. }
  510. }
  511. }
  512. void NatPunchthroughServer::StartPunchthroughForUser(User *user)
  513. {
  514. if (user->isReady==false)
  515. return;
  516. ConnectionAttempt *connectionAttempt;
  517. User *sender,*recipient,*otherUser;
  518. unsigned int i;
  519. for (i=0; i < user->connectionAttempts.Size(); i++)
  520. {
  521. connectionAttempt=user->connectionAttempts[i];
  522. if (connectionAttempt->sender==user)
  523. {
  524. otherUser=connectionAttempt->recipient;
  525. sender=user;
  526. recipient=otherUser;
  527. }
  528. else
  529. {
  530. otherUser=connectionAttempt->sender;
  531. recipient=user;
  532. sender=otherUser;
  533. }
  534. if (otherUser->isReady)
  535. {
  536. if (natPunchthroughServerDebugInterface)
  537. {
  538. char str[1024];
  539. char addr1[128], addr2[128];
  540. sender->systemAddress.ToString(true,addr1);
  541. recipient->systemAddress.ToString(true,addr2);
  542. sprintf(str, "Sending NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS to sender %s and recipient %s.", addr1, addr2);
  543. natPunchthroughServerDebugInterface->OnServerMessage(str);
  544. }
  545. sender->isReady=false;
  546. recipient->isReady=false;
  547. connectionAttempt->attemptPhase=ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS;
  548. connectionAttempt->startTime=RakNet::GetTime();
  549. sender->mostRecentPort=0;
  550. recipient->mostRecentPort=0;
  551. RakNet::BitStream outgoingBs;
  552. outgoingBs.Write((MessageID)ID_NAT_GET_MOST_RECENT_PORT);
  553. // 4/29/09 Write sessionID so we don't use returned port for a system we don't want
  554. outgoingBs.Write(connectionAttempt->sessionId);
  555. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,sender->systemAddress,false);
  556. rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,recipient->systemAddress,false);
  557. // 4/22/09 - BUG: missing break statement here
  558. break;
  559. }
  560. }
  561. }
  562. #endif // _RAKNET_SUPPORT_*
粤ICP备19079148号