PageRenderTime 64ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/raknet/NatTypeDetectionServer.cpp

https://gitlab.com/computerphilly/openblox
C++ | 438 lines | 318 code | 36 blank | 84 comment | 29 complexity | a554c5c89994f73087693c75ee0aa020 MD5 | raw file
  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_NatTypeDetectionServer==1
  12. #include "NatTypeDetectionServer.h"
  13. #include "SocketLayer.h"
  14. #include "RakNetSmartPtr.h"
  15. #include "SocketIncludes.h"
  16. #include "RakPeerInterface.h"
  17. #include "MessageIdentifiers.h"
  18. #include "GetTime.h"
  19. #include "BitStream.h"
  20. #include "SocketDefines.h"
  21. // #define NTDS_VERBOSE
  22. using namespace RakNet;
  23. STATIC_FACTORY_DEFINITIONS(NatTypeDetectionServer,NatTypeDetectionServer);
  24. NatTypeDetectionServer::NatTypeDetectionServer()
  25. {
  26. s1p2=s2p3=s3p4=s4p5=0;
  27. }
  28. NatTypeDetectionServer::~NatTypeDetectionServer()
  29. {
  30. Shutdown();
  31. }
  32. void NatTypeDetectionServer::Startup(
  33. const char *nonRakNetIP2,
  34. const char *nonRakNetIP3,
  35. const char *nonRakNetIP4
  36. #ifdef __native_client__
  37. ,_PP_Instance_ chromeInstance
  38. #endif
  39. )
  40. {
  41. DataStructures::List<RakNetSocket2* > sockets;
  42. rakPeerInterface->GetSockets(sockets);
  43. char str[64];
  44. sockets[0]->GetBoundAddress().ToString(false,str);
  45. s1p2=
  46. CreateNonblockingBoundSocket(str,
  47. #ifdef __native_client__
  48. chromeInstance,
  49. #endif
  50. this);
  51. s2p3=
  52. CreateNonblockingBoundSocket(nonRakNetIP2,
  53. #ifdef __native_client__
  54. chromeInstance,
  55. #endif
  56. this);
  57. s3p4=
  58. CreateNonblockingBoundSocket(nonRakNetIP3,
  59. #ifdef __native_client__
  60. chromeInstance,
  61. #endif
  62. this);
  63. s4p5=
  64. CreateNonblockingBoundSocket(nonRakNetIP4,
  65. #ifdef __native_client__
  66. chromeInstance,
  67. #endif
  68. this);
  69. strcpy(s3p4Address, nonRakNetIP3);
  70. #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
  71. if (s3p4->IsBerkleySocket())
  72. ((RNS2_Berkley*) s3p4)->CreateRecvPollingThread(0);
  73. #endif
  74. }
  75. void NatTypeDetectionServer::Shutdown()
  76. {
  77. if (s1p2!=0)
  78. {
  79. RakNet::OP_DELETE(s1p2,_FILE_AND_LINE_);
  80. s1p2=0;
  81. }
  82. if (s2p3!=0)
  83. {
  84. RakNet::OP_DELETE(s2p3,_FILE_AND_LINE_);
  85. s2p3=0;
  86. }
  87. if (s3p4!=0)
  88. {
  89. #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
  90. if (s3p4->IsBerkleySocket())
  91. ((RNS2_Berkley *)s3p4)->BlockOnStopRecvPollingThread();
  92. #endif
  93. RakNet::OP_DELETE(s3p4,_FILE_AND_LINE_);
  94. s3p4=0;
  95. }
  96. if (s4p5!=0)
  97. {
  98. RakNet::OP_DELETE(s4p5,_FILE_AND_LINE_);
  99. s4p5=0;
  100. }
  101. bufferedPacketsMutex.Lock();
  102. while (bufferedPackets.Size())
  103. RakNet::OP_DELETE(bufferedPackets.Pop(), _FILE_AND_LINE_);
  104. bufferedPacketsMutex.Unlock();
  105. }
  106. void NatTypeDetectionServer::Update(void)
  107. {
  108. int i=0;
  109. RakNet::TimeMS time = RakNet::GetTimeMS();
  110. RakNet::BitStream bs;
  111. SystemAddress boundAddress;
  112. RNS2RecvStruct *recvStruct;
  113. bufferedPacketsMutex.Lock();
  114. if (bufferedPackets.Size()>0)
  115. recvStruct=bufferedPackets.Pop();
  116. else
  117. recvStruct=0;
  118. bufferedPacketsMutex.Unlock();
  119. while (recvStruct)
  120. {
  121. SystemAddress senderAddr = recvStruct->systemAddress;
  122. char *data = recvStruct->data;
  123. if (data[0]==NAT_TYPE_PORT_RESTRICTED && recvStruct->socket==s3p4)
  124. {
  125. RakNet::BitStream bsIn((unsigned char*) data,recvStruct->bytesRead,false);
  126. RakNetGUID senderGuid;
  127. bsIn.IgnoreBytes(sizeof(MessageID));
  128. bool readSuccess = bsIn.Read(senderGuid);
  129. RakAssert(readSuccess);
  130. if (readSuccess)
  131. {
  132. unsigned int i = GetDetectionAttemptIndex(senderGuid);
  133. if (i!=(unsigned int)-1)
  134. {
  135. bs.Reset();
  136. bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_RESULT);
  137. // If different, then symmetric
  138. if (senderAddr!=natDetectionAttempts[i].systemAddress)
  139. {
  140. #ifdef NTDS_VERBOSE
  141. printf("Determined client is symmetric\n");
  142. #endif
  143. bs.Write((unsigned char) NAT_TYPE_SYMMETRIC);
  144. }
  145. else
  146. {
  147. // else port restricted
  148. #ifdef NTDS_VERBOSE
  149. printf("Determined client is port restricted\n");
  150. #endif
  151. bs.Write((unsigned char) NAT_TYPE_PORT_RESTRICTED);
  152. }
  153. rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false);
  154. // Done
  155. natDetectionAttempts.RemoveAtIndexFast(i);
  156. }
  157. else
  158. {
  159. // RakAssert("i==0 in Update when looking up GUID in NatTypeDetectionServer.cpp. Either a bug or a late resend" && 0);
  160. }
  161. }
  162. else
  163. {
  164. // RakAssert("Didn't read GUID in Update in NatTypeDetectionServer.cpp. Message format error" && 0);
  165. }
  166. }
  167. DeallocRNS2RecvStruct(recvStruct, _FILE_AND_LINE_);
  168. bufferedPacketsMutex.Lock();
  169. if (bufferedPackets.Size()>0)
  170. recvStruct=bufferedPackets.Pop();
  171. else
  172. recvStruct=0;
  173. bufferedPacketsMutex.Unlock();
  174. }
  175. /*
  176. // Only socket that receives messages is s3p4, to see if the external address is different than that of the connection to rakPeerInterface
  177. char data[ MAXIMUM_MTU_SIZE ];
  178. int len;
  179. SystemAddress senderAddr;
  180. len=NatTypeRecvFrom(data, s3p4, senderAddr);
  181. // Client is asking us if this is port restricted. Only client requests of this type come in on s3p4
  182. while (len>0 && data[0]==NAT_TYPE_PORT_RESTRICTED)
  183. {
  184. RakNet::BitStream bsIn((unsigned char*) data,len,false);
  185. RakNetGUID senderGuid;
  186. bsIn.IgnoreBytes(sizeof(MessageID));
  187. bool readSuccess = bsIn.Read(senderGuid);
  188. RakAssert(readSuccess);
  189. if (readSuccess)
  190. {
  191. unsigned int i = GetDetectionAttemptIndex(senderGuid);
  192. if (i!=(unsigned int)-1)
  193. {
  194. bs.Reset();
  195. bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_RESULT);
  196. // If different, then symmetric
  197. if (senderAddr!=natDetectionAttempts[i].systemAddress)
  198. {
  199. #ifdef NTDS_VERBOSE
  200. printf("Determined client is symmetric\n");
  201. #endif
  202. bs.Write((unsigned char) NAT_TYPE_SYMMETRIC);
  203. }
  204. else
  205. {
  206. // else port restricted
  207. #ifdef NTDS_VERBOSE
  208. printf("Determined client is port restricted\n");
  209. #endif
  210. bs.Write((unsigned char) NAT_TYPE_PORT_RESTRICTED);
  211. }
  212. rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false);
  213. // Done
  214. natDetectionAttempts.RemoveAtIndexFast(i);
  215. }
  216. else
  217. {
  218. // RakAssert("i==0 in Update when looking up GUID in NatTypeDetectionServer.cpp. Either a bug or a late resend" && 0);
  219. }
  220. }
  221. else
  222. {
  223. // RakAssert("Didn't read GUID in Update in NatTypeDetectionServer.cpp. Message format error" && 0);
  224. }
  225. len=NatTypeRecvFrom(data, s3p4, senderAddr);
  226. }
  227. */
  228. while (i < (int) natDetectionAttempts.Size())
  229. {
  230. if (time > natDetectionAttempts[i].nextStateTime)
  231. {
  232. RNS2_SendParameters bsp;
  233. natDetectionAttempts[i].detectionState=(NATDetectionState)((int)natDetectionAttempts[i].detectionState+1);
  234. natDetectionAttempts[i].nextStateTime=time+natDetectionAttempts[i].timeBetweenAttempts;
  235. SystemAddress saOut;
  236. unsigned char c;
  237. bs.Reset();
  238. switch (natDetectionAttempts[i].detectionState)
  239. {
  240. case STATE_TESTING_NONE_1:
  241. case STATE_TESTING_NONE_2:
  242. c = NAT_TYPE_NONE;
  243. #ifdef NTDS_VERBOSE
  244. printf("Testing NAT_TYPE_NONE\n");
  245. #endif
  246. // S4P5 sends to C2. If arrived, no NAT. Done. (Else S4P5 potentially banned, do not use again).
  247. saOut=natDetectionAttempts[i].systemAddress;
  248. saOut.SetPortHostOrder(natDetectionAttempts[i].c2Port);
  249. // SocketLayer::SendTo_PC( s4p5, (const char*) &c, 1, saOut, __FILE__, __LINE__ );
  250. bsp.data = (char*) &c;
  251. bsp.length = 1;
  252. bsp.systemAddress = saOut;
  253. s4p5->Send(&bsp, _FILE_AND_LINE_);
  254. break;
  255. case STATE_TESTING_FULL_CONE_1:
  256. case STATE_TESTING_FULL_CONE_2:
  257. #ifdef NTDS_VERBOSE
  258. printf("Testing NAT_TYPE_FULL_CONE\n");
  259. #endif
  260. rakPeerInterface->WriteOutOfBandHeader(&bs);
  261. bs.Write((unsigned char) ID_NAT_TYPE_DETECT);
  262. bs.Write((unsigned char) NAT_TYPE_FULL_CONE);
  263. // S2P3 sends to C1 (Different address, different port, to previously used port on client). If received, Full-cone nat. Done. (Else S2P3 potentially banned, do not use again).
  264. saOut=natDetectionAttempts[i].systemAddress;
  265. saOut.SetPortHostOrder(natDetectionAttempts[i].systemAddress.GetPort());
  266. // SocketLayer::SendTo_PC( s2p3, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), saOut, __FILE__, __LINE__ );
  267. bsp.data = (char*) bs.GetData();
  268. bsp.length = bs.GetNumberOfBytesUsed();
  269. bsp.systemAddress = saOut;
  270. s2p3->Send(&bsp, _FILE_AND_LINE_);
  271. break;
  272. case STATE_TESTING_ADDRESS_RESTRICTED_1:
  273. case STATE_TESTING_ADDRESS_RESTRICTED_2:
  274. #ifdef NTDS_VERBOSE
  275. printf("Testing NAT_TYPE_ADDRESS_RESTRICTED\n");
  276. #endif
  277. rakPeerInterface->WriteOutOfBandHeader(&bs);
  278. bs.Write((unsigned char) ID_NAT_TYPE_DETECT);
  279. bs.Write((unsigned char) NAT_TYPE_ADDRESS_RESTRICTED);
  280. // S1P2 sends to C1 (Same address, different port, to previously used port on client). If received, address-restricted cone nat. Done.
  281. saOut=natDetectionAttempts[i].systemAddress;
  282. saOut.SetPortHostOrder(natDetectionAttempts[i].systemAddress.GetPort());
  283. //SocketLayer::SendTo_PC( s1p2, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), saOut, __FILE__, __LINE__ );
  284. bsp.data = (char*) bs.GetData();
  285. bsp.length = bs.GetNumberOfBytesUsed();
  286. bsp.systemAddress = saOut;
  287. s1p2->Send(&bsp, _FILE_AND_LINE_);
  288. break;
  289. case STATE_TESTING_PORT_RESTRICTED_1:
  290. case STATE_TESTING_PORT_RESTRICTED_2:
  291. // C1 sends to S3P4. If address of C1 as seen by S3P4 is the same as the address of C1 as seen by S1P1, then port-restricted cone nat. Done
  292. #ifdef NTDS_VERBOSE
  293. printf("Testing NAT_TYPE_PORT_RESTRICTED\n");
  294. #endif
  295. bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_REQUEST);
  296. bs.Write(RakString::NonVariadic(s3p4Address));
  297. bs.Write(s3p4->GetBoundAddress().GetPort());
  298. rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false);
  299. break;
  300. default:
  301. #ifdef NTDS_VERBOSE
  302. printf("Warning, exceeded final check STATE_TESTING_PORT_RESTRICTED_2.\nExpected that client would have sent NAT_TYPE_PORT_RESTRICTED on s3p4.\nDefaulting to Symmetric\n");
  303. #endif
  304. bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_RESULT);
  305. bs.Write((unsigned char) NAT_TYPE_SYMMETRIC);
  306. rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false);
  307. natDetectionAttempts.RemoveAtIndexFast(i);
  308. i--;
  309. break;
  310. }
  311. }
  312. i++;
  313. }
  314. }
  315. PluginReceiveResult NatTypeDetectionServer::OnReceive(Packet *packet)
  316. {
  317. switch (packet->data[0])
  318. {
  319. case ID_NAT_TYPE_DETECTION_REQUEST:
  320. OnDetectionRequest(packet);
  321. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  322. }
  323. return RR_CONTINUE_PROCESSING;
  324. }
  325. void NatTypeDetectionServer::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
  326. {
  327. (void) lostConnectionReason;
  328. (void) rakNetGUID;
  329. unsigned int i = GetDetectionAttemptIndex(systemAddress);
  330. if (i==(unsigned int)-1)
  331. return;
  332. natDetectionAttempts.RemoveAtIndexFast(i);
  333. }
  334. void NatTypeDetectionServer::OnDetectionRequest(Packet *packet)
  335. {
  336. unsigned int i = GetDetectionAttemptIndex(packet->systemAddress);
  337. RakNet::BitStream bsIn(packet->data, packet->length, false);
  338. bsIn.IgnoreBytes(1);
  339. bool isRequest=false;
  340. bsIn.Read(isRequest);
  341. if (isRequest)
  342. {
  343. if (i!=(unsigned int)-1)
  344. return; // Already in progress
  345. NATDetectionAttempt nda;
  346. nda.detectionState=STATE_NONE;
  347. nda.systemAddress=packet->systemAddress;
  348. nda.guid=packet->guid;
  349. bsIn.Read(nda.c2Port);
  350. nda.nextStateTime=0;
  351. nda.timeBetweenAttempts=rakPeerInterface->GetLastPing(nda.systemAddress)*3+50;
  352. natDetectionAttempts.Push(nda, _FILE_AND_LINE_);
  353. }
  354. else
  355. {
  356. if (i==(unsigned int)-1)
  357. return; // Unknown
  358. // They are done
  359. natDetectionAttempts.RemoveAtIndexFast(i);
  360. }
  361. }
  362. unsigned int NatTypeDetectionServer::GetDetectionAttemptIndex(const SystemAddress &sa)
  363. {
  364. for (unsigned int i=0; i < natDetectionAttempts.Size(); i++)
  365. {
  366. if (natDetectionAttempts[i].systemAddress==sa)
  367. return i;
  368. }
  369. return (unsigned int) -1;
  370. }
  371. unsigned int NatTypeDetectionServer::GetDetectionAttemptIndex(RakNetGUID guid)
  372. {
  373. for (unsigned int i=0; i < natDetectionAttempts.Size(); i++)
  374. {
  375. if (natDetectionAttempts[i].guid==guid)
  376. return i;
  377. }
  378. return (unsigned int) -1;
  379. }
  380. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  381. void NatTypeDetectionServer::DeallocRNS2RecvStruct(RNS2RecvStruct *s, const char *file, unsigned int line)
  382. {
  383. RakNet::OP_DELETE(s, file, line);
  384. }
  385. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  386. RNS2RecvStruct *NatTypeDetectionServer::AllocRNS2RecvStruct(const char *file, unsigned int line)
  387. {
  388. return RakNet::OP_NEW<RNS2RecvStruct>(file,line);
  389. }
  390. void NatTypeDetectionServer::OnRNS2Recv(RNS2RecvStruct *recvStruct)
  391. {
  392. bufferedPacketsMutex.Lock();
  393. bufferedPackets.Push(recvStruct,_FILE_AND_LINE_);
  394. bufferedPacketsMutex.Unlock();
  395. }
  396. #endif // _RAKNET_SUPPORT_*