main.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  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 "RakPeerInterface.h"
  11. #include "RakSleep.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "Kbhit.h"
  16. #include "MessageIdentifiers.h"
  17. #include "BitStream.h"
  18. #include "RakSleep.h"
  19. #include "NatPunchthroughClient.h"
  20. #include "NatTypeDetectionClient.h"
  21. #include "Getche.h"
  22. #include "GetTime.h"
  23. #include "Router2.h"
  24. #include "UDPProxyClient.h"
  25. #include "Gets.h"
  26. #include "Itoa.h"
  27. // To include miniupnp, see Samples\NATCompleteClient\readme.txt
  28. #include "miniupnpc.h"
  29. #include "upnpcommands.h"
  30. #include "upnperrors.h"
  31. using namespace RakNet;
  32. #define DEFAULT_RAKPEER_PORT 50000
  33. #define RAKPEER_PORT_STR "0"
  34. #define DEFAULT_SERVER_PORT "61111"
  35. #define DEFAULT_SERVER_ADDRESS "natpunch.jenkinssoftware.com"
  36. enum SampleResult
  37. {
  38. PENDING,
  39. FAILED,
  40. SUCCEEDED
  41. };
  42. #define SUPPORT_UPNP FAILED
  43. #define SUPPORT_NAT_TYPE_DETECTION FAILED
  44. #define SUPPORT_NAT_PUNCHTHROUGH PENDING
  45. #define SUPPORT_ROUTER2 FAILED
  46. #define SUPPORT_UDP_PROXY FAILED
  47. struct SampleFramework
  48. {
  49. virtual const char * QueryName(void)=0;
  50. virtual bool QueryRequiresServer(void)=0;
  51. virtual const char * QueryFunction(void)=0;
  52. virtual const char * QuerySuccess(void)=0;
  53. virtual bool QueryQuitOnSuccess(void)=0;
  54. virtual void Init(RakNet::RakPeerInterface *rakPeer)=0;
  55. virtual void ProcessPacket(Packet *packet)=0;
  56. virtual void Update(RakNet::RakPeerInterface *rakPeer)=0;
  57. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)=0;
  58. SampleResult sampleResult;
  59. };
  60. SystemAddress SelectAmongConnectedSystems(RakNet::RakPeerInterface *rakPeer, const char *hostName)
  61. {
  62. DataStructures::List<SystemAddress> addresses;
  63. DataStructures::List<RakNetGUID> guids;
  64. rakPeer->GetSystemList(addresses, guids);
  65. if (addresses.Size()==0)
  66. {
  67. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  68. }
  69. if (addresses.Size()>1)
  70. {
  71. printf("Select IP address for %s.\n", hostName);
  72. char buff[64];
  73. for (unsigned int i=0; i < addresses.Size(); i++)
  74. {
  75. addresses[i].ToString(true, buff);
  76. printf("%i. %s\n", i+1, buff);
  77. }
  78. Gets(buff,sizeof(buff));
  79. if (buff[0]==0)
  80. {
  81. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  82. }
  83. unsigned int idx = atoi(buff);
  84. if (idx<=0 || idx > addresses.Size())
  85. {
  86. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  87. }
  88. return addresses[idx-1];
  89. }
  90. else
  91. return addresses[0];
  92. };
  93. SystemAddress ConnectBlocking(RakNet::RakPeerInterface *rakPeer, const char *hostName, const char *defaultAddress, const char *defaultPort)
  94. {
  95. char ipAddr[64];
  96. if (defaultAddress==0 || defaultAddress[0]==0)
  97. printf("Enter IP of system %s is running on: ", hostName);
  98. else
  99. printf("Enter IP of system %s, or press enter for default: ", hostName);
  100. Gets(ipAddr,sizeof(ipAddr));
  101. if (ipAddr[0]==0)
  102. {
  103. if (defaultAddress==0 || defaultAddress[0]==0)
  104. {
  105. printf("Failed. No address entered for %s.\n", hostName);
  106. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  107. }
  108. else
  109. {
  110. strcpy(ipAddr, defaultAddress);
  111. }
  112. }
  113. char port[64];
  114. if (defaultAddress==0 || defaultAddress[0]==0)
  115. printf("Enter port of system %s is running on: ", hostName);
  116. else
  117. printf("Enter port of system %s, or press enter for default: ", hostName);
  118. Gets(port, sizeof(port));
  119. if (port[0]==0)
  120. {
  121. if (defaultPort==0 || defaultPort[0]==0)
  122. {
  123. printf("Failed. No port entered for %s.\n", hostName);
  124. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  125. }
  126. else
  127. {
  128. strcpy(port, defaultPort);
  129. }
  130. }
  131. if (rakPeer->Connect(ipAddr, atoi(port), 0, 0)!=RakNet::CONNECTION_ATTEMPT_STARTED)
  132. {
  133. printf("Failed connect call for %s.\n", hostName);
  134. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  135. }
  136. printf("Connecting...\n");
  137. RakNet::Packet *packet;
  138. while (1)
  139. {
  140. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  141. {
  142. if (packet->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)
  143. {
  144. return packet->systemAddress;
  145. }
  146. else if (packet->data[0]==ID_NO_FREE_INCOMING_CONNECTIONS)
  147. {
  148. printf("ID_NO_FREE_INCOMING_CONNECTIONS");
  149. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  150. }
  151. else
  152. {
  153. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  154. }
  155. RakSleep(100);
  156. }
  157. }
  158. }
  159. struct UPNPFramework : public SampleFramework
  160. {
  161. UPNPFramework() { sampleResult=SUPPORT_UPNP;}
  162. virtual const char * QueryName(void) {return "UPNPFramework";}
  163. virtual bool QueryRequiresServer(void) {return false;}
  164. virtual const char * QueryFunction(void) {return "Use UPNP to open the router";}
  165. virtual const char * QuerySuccess(void) {return "Other systems can now connect to you on the opened port.";}
  166. virtual bool QueryQuitOnSuccess(void) {return true;}
  167. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  168. {
  169. if (sampleResult==FAILED) return;
  170. struct UPNPDev * devlist = 0;
  171. devlist = upnpDiscover(2000, 0, 0, 0, 0, 0);
  172. if (devlist)
  173. {
  174. printf("List of UPNP devices found on the network :\n");
  175. struct UPNPDev * device;
  176. for(device = devlist; device; device = device->pNext)
  177. {
  178. printf(" desc: %s\n st: %s\n\n",
  179. device->descURL, device->st);
  180. }
  181. char lanaddr[64]; /* my ip address on the LAN */
  182. struct UPNPUrls urls;
  183. struct IGDdatas data;
  184. if (UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))==1)
  185. {
  186. // 4/16/2012 Why was I doing this? Just to read my external port? That shouldn't be necessary
  187. /*
  188. SystemAddress serverAddress=SelectAmongConnectedSystems(rakPeer, "NatTypeDetectionServer");
  189. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  190. {
  191. serverAddress=ConnectBlocking(rakPeer, "NatTypeDetectionServer", DEFAULT_SERVER_ADDRESS, DEFAULT_SERVER_PORT);
  192. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  193. {
  194. printf("Failed to connect to a server.\n");
  195. sampleResult=FAILED;
  196. return;
  197. }
  198. }
  199. char iport[32];
  200. Itoa(sockets[0]->boundAddress.GetPort(),iport,10);
  201. char eport[32];
  202. Itoa(rakPeer->GetExternalID(serverAddress).GetPort(),eport,10);
  203. */
  204. // Use same external and internal ports
  205. DataStructures::List<RakNetSocket2* > sockets;
  206. rakPeer->GetSockets(sockets);
  207. char iport[32];
  208. Itoa(sockets[0]->GetBoundAddress().GetPort(),iport,10);
  209. char eport[32];
  210. strcpy(eport, iport);
  211. // Version 1.5
  212. // int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
  213. // eport, iport, lanaddr, 0, "UDP", 0);
  214. // Version miniupnpc-1.6.20120410
  215. int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
  216. eport, iport, lanaddr, 0, "UDP", 0, "0");
  217. if(r!=UPNPCOMMAND_SUCCESS)
  218. printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
  219. eport, iport, lanaddr, r, strupnperror(r));
  220. char intPort[6];
  221. char intClient[16];
  222. // Version 1.5
  223. // r = UPNP_GetSpecificPortMappingEntry(urls.controlURL,
  224. // data.first.servicetype,
  225. // eport, "UDP",
  226. // intClient, intPort);
  227. // Version miniupnpc-1.6.20120410
  228. char desc[128];
  229. char enabled[128];
  230. char leaseDuration[128];
  231. r = UPNP_GetSpecificPortMappingEntry(urls.controlURL,
  232. data.first.servicetype,
  233. eport, "UDP",
  234. intClient, intPort,
  235. desc, enabled, leaseDuration);
  236. if(r!=UPNPCOMMAND_SUCCESS)
  237. {
  238. printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
  239. r, strupnperror(r));
  240. sampleResult=FAILED;
  241. }
  242. else
  243. sampleResult=SUCCEEDED;
  244. }
  245. else
  246. sampleResult=FAILED;
  247. }
  248. else
  249. sampleResult=FAILED;
  250. }
  251. virtual void ProcessPacket(Packet *packet)
  252. {
  253. }
  254. virtual void Update(RakNet::RakPeerInterface *rakPeer)
  255. {
  256. if (sampleResult==FAILED) return;
  257. }
  258. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  259. {
  260. }
  261. };
  262. struct NatTypeDetectionFramework : public SampleFramework
  263. {
  264. // Set to FAILED to skip this test
  265. NatTypeDetectionFramework() { sampleResult=SUPPORT_NAT_TYPE_DETECTION; ntdc=0;}
  266. virtual const char * QueryName(void) {return "NatTypeDetectionFramework";}
  267. virtual bool QueryRequiresServer(void) {return true;}
  268. virtual const char * QueryFunction(void) {return "Determines router type to avoid NAT punch attempts that cannot\nsucceed.";}
  269. virtual const char * QuerySuccess(void) {return "If our NAT type is Symmetric, we can skip NAT punch to other symmetric NATs.";}
  270. virtual bool QueryQuitOnSuccess(void) {return false;}
  271. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  272. {
  273. if (sampleResult==FAILED) return;
  274. SystemAddress serverAddress=SelectAmongConnectedSystems(rakPeer, "NatTypeDetectionServer");
  275. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  276. {
  277. serverAddress=ConnectBlocking(rakPeer, "NatTypeDetectionServer", DEFAULT_SERVER_ADDRESS, DEFAULT_SERVER_PORT);
  278. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  279. {
  280. printf("Failed to connect to a server.\n");
  281. sampleResult=FAILED;
  282. return;
  283. }
  284. }
  285. ntdc = new NatTypeDetectionClient;
  286. rakPeer->AttachPlugin(ntdc);
  287. ntdc->DetectNATType(serverAddress);
  288. timeout=RakNet::GetTimeMS() + 5000;
  289. }
  290. virtual void ProcessPacket(Packet *packet)
  291. {
  292. if (packet->data[0]==ID_NAT_TYPE_DETECTION_RESULT)
  293. {
  294. RakNet::NATTypeDetectionResult r = (RakNet::NATTypeDetectionResult) packet->data[1];
  295. printf("NAT Type is %s (%s)\n", NATTypeDetectionResultToString(r), NATTypeDetectionResultToStringFriendly(r));
  296. printf("Using NATPunchthrough can connect to systems using:\n");
  297. for (int i=0; i < (int) RakNet::NAT_TYPE_COUNT; i++)
  298. {
  299. if (CanConnect(r,(RakNet::NATTypeDetectionResult)i))
  300. {
  301. if (i!=0)
  302. printf(", ");
  303. printf("%s", NATTypeDetectionResultToString((RakNet::NATTypeDetectionResult)i));
  304. }
  305. }
  306. printf("\n");
  307. if (r==RakNet::NAT_TYPE_PORT_RESTRICTED || r==RakNet::NAT_TYPE_SYMMETRIC)
  308. {
  309. // For UPNP, see Samples\UDPProxy
  310. printf("Note: Your router must support UPNP or have the user manually forward ports.\n");
  311. printf("Otherwise NATPunchthrough may not always succeed.\n");
  312. }
  313. sampleResult=SUCCEEDED;
  314. }
  315. }
  316. virtual void Update(RakNet::RakPeerInterface *rakPeer)
  317. {
  318. if (sampleResult==FAILED) return;
  319. if (sampleResult==PENDING && RakNet::GetTimeMS()>timeout)
  320. {
  321. printf("No response from the server, probably not running NatTypeDetectionServer plugin.\n");
  322. sampleResult=FAILED;
  323. }
  324. }
  325. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  326. {
  327. delete ntdc;
  328. ntdc=0;
  329. }
  330. NatTypeDetectionClient *ntdc;
  331. RakNet::TimeMS timeout;
  332. };
  333. struct NatPunchthoughClientFramework : public SampleFramework, public NatPunchthroughDebugInterface_Printf
  334. {
  335. SystemAddress serverAddress;
  336. // Set to FAILED to skip this test
  337. NatPunchthoughClientFramework() { sampleResult=SUPPORT_NAT_PUNCHTHROUGH; npClient=0;}
  338. virtual const char * QueryName(void) {return "NatPunchthoughClientFramework";}
  339. virtual bool QueryRequiresServer(void) {return true;}
  340. virtual const char * QueryFunction(void) {return "Causes two systems to try to connect to each other at the same\ntime, to get through routers.";}
  341. virtual const char * QuerySuccess(void) {return "We can now communicate with the other system, including connecting.";}
  342. virtual bool QueryQuitOnSuccess(void) {return true;}
  343. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  344. {
  345. if (sampleResult==FAILED) return;
  346. serverAddress=SelectAmongConnectedSystems(rakPeer, "NatPunchthroughServer");
  347. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  348. {
  349. serverAddress=ConnectBlocking(rakPeer, "NatPunchthroughServer", DEFAULT_SERVER_ADDRESS, DEFAULT_SERVER_PORT);
  350. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  351. {
  352. printf("Failed to connect to a server.\n");
  353. sampleResult=FAILED;
  354. return;
  355. }
  356. }
  357. npClient = new NatPunchthroughClient;
  358. npClient->SetDebugInterface(this);
  359. rakPeer->AttachPlugin(npClient);
  360. char guid[128];
  361. printf("Enter RakNetGuid of the remote system, which should have already connected\nto the server.\nOr press enter to just listen.\n");
  362. Gets(guid,sizeof(guid));
  363. if (guid[0])
  364. {
  365. RakNetGUID remoteSystemGuid;
  366. remoteSystemGuid.FromString(guid);
  367. npClient->OpenNAT(remoteSystemGuid, serverAddress);
  368. isListening=false;
  369. timeout=RakNet::GetTimeMS() + 10000;
  370. }
  371. else
  372. {
  373. printf("Listening\n");
  374. printf("My GUID is %s\n", rakPeer->GetMyGUID().ToString());
  375. isListening=true;
  376. // Find the stride of our router in advance
  377. npClient->FindRouterPortStride(serverAddress);
  378. }
  379. }
  380. virtual void ProcessPacket(Packet *packet)
  381. {
  382. if (
  383. packet->data[0]==ID_NAT_TARGET_NOT_CONNECTED ||
  384. packet->data[0]==ID_NAT_TARGET_UNRESPONSIVE ||
  385. packet->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST ||
  386. packet->data[0]==ID_NAT_PUNCHTHROUGH_FAILED
  387. )
  388. {
  389. RakNetGUID guid;
  390. if (packet->data[0]==ID_NAT_PUNCHTHROUGH_FAILED)
  391. {
  392. guid=packet->guid;
  393. }
  394. else
  395. {
  396. RakNet::BitStream bs(packet->data,packet->length,false);
  397. bs.IgnoreBytes(1);
  398. bool b = bs.Read(guid);
  399. RakAssert(b);
  400. }
  401. switch (packet->data[0])
  402. {
  403. case ID_NAT_TARGET_NOT_CONNECTED:
  404. printf("Failed: ID_NAT_TARGET_NOT_CONNECTED\n");
  405. break;
  406. case ID_NAT_TARGET_UNRESPONSIVE:
  407. printf("Failed: ID_NAT_TARGET_UNRESPONSIVE\n");
  408. break;
  409. case ID_NAT_CONNECTION_TO_TARGET_LOST:
  410. printf("Failed: ID_NAT_CONNECTION_TO_TARGET_LOST\n");
  411. break;
  412. case ID_NAT_PUNCHTHROUGH_FAILED:
  413. printf("Failed: ID_NAT_PUNCHTHROUGH_FAILED\n");
  414. break;
  415. }
  416. sampleResult=FAILED;
  417. return;
  418. }
  419. else if (packet->data[0]==ID_NAT_PUNCHTHROUGH_SUCCEEDED)
  420. {
  421. unsigned char weAreTheSender = packet->data[1];
  422. if (weAreTheSender)
  423. printf("NAT punch success to remote system %s.\n", packet->systemAddress.ToString(true));
  424. else
  425. printf("NAT punch success from remote system %s.\n", packet->systemAddress.ToString(true));
  426. char guid[128];
  427. printf("Enter RakNetGuid of the remote system, which should have already connected.\nOr press enter to quit.\n");
  428. Gets(guid,sizeof(guid));
  429. if (guid[0])
  430. {
  431. RakNetGUID remoteSystemGuid;
  432. remoteSystemGuid.FromString(guid);
  433. npClient->OpenNAT(remoteSystemGuid, serverAddress);
  434. timeout=RakNet::GetTimeMS() + 10000;
  435. }
  436. else
  437. {
  438. sampleResult=SUCCEEDED;
  439. }
  440. }
  441. }
  442. virtual void Update(RakNet::RakPeerInterface *rakPeer)
  443. {
  444. if (sampleResult==FAILED) return;
  445. if (sampleResult==PENDING && RakNet::GetTimeMS()>timeout && isListening==false)
  446. {
  447. printf("No response from the server, probably not running NatPunchthroughServer plugin.\n");
  448. sampleResult=FAILED;
  449. }
  450. }
  451. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  452. {
  453. delete npClient;
  454. npClient=0;
  455. }
  456. NatPunchthroughClient *npClient;
  457. RakNet::TimeMS timeout;
  458. bool isListening;
  459. };
  460. struct Router2Framework : public SampleFramework
  461. {
  462. // Set to FAILED to skip this test
  463. Router2Framework() { sampleResult=SUPPORT_ROUTER2; router2=0;}
  464. virtual const char * QueryName(void) {return "Router2Framework";}
  465. virtual bool QueryRequiresServer(void) {return false;}
  466. virtual const char * QueryFunction(void) {return "Connect to a peer we cannot directly connect to using the\nbandwidth of a shared peer.";}
  467. virtual const char * QuerySuccess(void) {return "Router2 assumes we will now connect to the other system.";}
  468. virtual bool QueryQuitOnSuccess(void) {return true;}
  469. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  470. {
  471. if (sampleResult==FAILED) return;
  472. printf("Given your application's bandwidth, how much traffic can be forwarded through a single peer?\nIf you use more than half the available bandwidth, then this plugin won't work for you.\n");;
  473. char supportedStr[64];
  474. do
  475. {
  476. printf("Enter a number greater than or equal to 0: ");
  477. Gets(supportedStr,sizeof(supportedStr));
  478. } while (supportedStr[0]==0);
  479. int supported=atoi(supportedStr);
  480. if (supported<=0)
  481. {
  482. printf("Aborting Router2\n");
  483. sampleResult=FAILED;
  484. return;
  485. }
  486. SystemAddress peerAddress = SelectAmongConnectedSystems(rakPeer, "shared peer");
  487. if (peerAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  488. {
  489. peerAddress=ConnectBlocking(rakPeer, "shared peer", "", RAKPEER_PORT_STR);
  490. if (peerAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  491. {
  492. printf("Failed to connect to a shared peer.\n");
  493. sampleResult=FAILED;
  494. return;
  495. }
  496. }
  497. char guid[64];
  498. printf("Destination system must be connected to the shared peer.\n");
  499. do
  500. {
  501. printf("Enter RakNetGUID of destination system: ");
  502. Gets(guid,sizeof(guid));
  503. } while (guid[0]==0);
  504. RakNetGUID endpointGuid;
  505. endpointGuid.FromString(guid);
  506. router2 = new Router2;
  507. rakPeer->AttachPlugin(router2);
  508. router2->EstablishRouting(endpointGuid);
  509. timeout=RakNet::GetTimeMS() + 5000;
  510. }
  511. virtual void ProcessPacket(Packet *packet)
  512. {
  513. }
  514. virtual void Update(RakNet::RakPeerInterface *rakPeer)
  515. {
  516. if (sampleResult==FAILED) return;
  517. if (sampleResult==PENDING && RakNet::GetTimeMS()>timeout)
  518. {
  519. printf("No response from any system, probably not running Router2 plugin.\n");
  520. sampleResult=FAILED;
  521. }
  522. }
  523. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  524. {
  525. delete router2;
  526. router2=0;
  527. }
  528. Router2 *router2;
  529. RakNet::TimeMS timeout;
  530. };
  531. struct UDPProxyClientFramework : public SampleFramework, public UDPProxyClientResultHandler
  532. {
  533. // Set to FAILED to skip this test
  534. UDPProxyClientFramework() { sampleResult=SUPPORT_UDP_PROXY; udpProxy=0;}
  535. virtual const char * QueryName(void) {return "UDPProxyClientFramework";}
  536. virtual bool QueryRequiresServer(void) {return true;}
  537. virtual const char * QueryFunction(void) {return "Connect to a peer using a shared server connection.";}
  538. virtual const char * QuerySuccess(void) {return "We can now communicate with the other system, including connecting, within 5 seconds.";}
  539. virtual bool QueryQuitOnSuccess(void) {return false;}
  540. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  541. {
  542. if (sampleResult==FAILED) return;
  543. SystemAddress serverAddress=SelectAmongConnectedSystems(rakPeer, "UDPProxyCoordinator");
  544. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  545. {
  546. serverAddress=ConnectBlocking(rakPeer, "UDPProxyCoordinator", DEFAULT_SERVER_ADDRESS, DEFAULT_SERVER_PORT);
  547. if (serverAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  548. {
  549. printf("Failed to connect to a server.\n");
  550. sampleResult=FAILED;
  551. return;
  552. }
  553. }
  554. udpProxy = new UDPProxyClient;
  555. rakPeer->AttachPlugin(udpProxy);
  556. udpProxy->SetResultHandler(this);
  557. char guid[128];
  558. printf("Enter RakNetGuid of the remote system, which should have already connected\nto the server.\nOr press enter to just listen.\n");
  559. Gets(guid,sizeof(guid));
  560. RakNetGUID targetGuid;
  561. targetGuid.FromString(guid);
  562. if (guid[0])
  563. {
  564. RakNetGUID remoteSystemGuid;
  565. remoteSystemGuid.FromString(guid);
  566. udpProxy->RequestForwarding(serverAddress, UNASSIGNED_SYSTEM_ADDRESS, targetGuid, UDP_FORWARDER_MAXIMUM_TIMEOUT, 0);
  567. isListening=false;
  568. }
  569. else
  570. {
  571. printf("Listening\n");
  572. printf("My GUID is %s\n", rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString());
  573. isListening=true;
  574. }
  575. timeout=RakNet::GetTimeMS() + 5000;
  576. }
  577. virtual void ProcessPacket(Packet *packet)
  578. {
  579. }
  580. virtual void Update(RakNet::RakPeerInterface *rakPeer)
  581. {
  582. if (sampleResult==FAILED) return;
  583. if (sampleResult==PENDING && RakNet::GetTimeMS()>timeout && isListening==false)
  584. {
  585. printf("No response from the server, probably not running UDPProxyCoordinator plugin.\n");
  586. sampleResult=FAILED;
  587. }
  588. }
  589. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  590. {
  591. delete udpProxy;
  592. udpProxy=0;
  593. }
  594. virtual void OnForwardingSuccess(const char *proxyIPAddress, unsigned short proxyPort,
  595. SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddress, RakNetGUID targetGuid, RakNet::UDPProxyClient *proxyClientPlugin)
  596. {
  597. printf("Datagrams forwarded by proxy %s:%i to target %s.\n", proxyIPAddress, proxyPort, targetAddress.ToString(false));
  598. printf("Connecting to proxy, which will be received by target.\n");
  599. ConnectionAttemptResult car = proxyClientPlugin->GetRakPeerInterface()->Connect(proxyIPAddress, proxyPort, 0, 0);
  600. RakAssert(car==CONNECTION_ATTEMPT_STARTED);
  601. sampleResult=SUCCEEDED;
  602. }
  603. virtual void OnForwardingNotification(const char *proxyIPAddress, unsigned short proxyPort,
  604. SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddress, RakNetGUID targetGuid, RakNet::UDPProxyClient *proxyClientPlugin)
  605. {
  606. printf("Source %s has setup forwarding to us through proxy %s:%i.\n", sourceAddress.ToString(false), proxyIPAddress, proxyPort);
  607. sampleResult=SUCCEEDED;
  608. }
  609. virtual void OnNoServersOnline(SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddress, RakNetGUID targetGuid, RakNet::UDPProxyClient *proxyClientPlugin)
  610. {
  611. printf("Failure: No servers logged into coordinator.\n");
  612. sampleResult=FAILED;
  613. }
  614. virtual void OnRecipientNotConnected(SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddress, RakNetGUID targetGuid, RakNet::UDPProxyClient *proxyClientPlugin)
  615. {
  616. printf("Failure: Recipient not connected to coordinator.\n");
  617. sampleResult=FAILED;
  618. }
  619. virtual void OnAllServersBusy(SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddress, RakNetGUID targetGuid, RakNet::UDPProxyClient *proxyClientPlugin)
  620. {
  621. printf("Failure: No servers have available forwarding ports.\n");
  622. sampleResult=FAILED;
  623. }
  624. virtual void OnForwardingInProgress(const char *proxyIPAddress, unsigned short proxyPort, SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddress, RakNetGUID targetGuid, RakNet::UDPProxyClient *proxyClientPlugin)
  625. {
  626. printf("Notification: Forwarding already in progress.\n");
  627. }
  628. UDPProxyClient *udpProxy;
  629. RakNet::TimeMS timeout;
  630. bool isListening;
  631. };
  632. void PrintPacketMessages(Packet *packet, RakPeerInterface *rakPeer)
  633. {
  634. switch (packet->data[0])
  635. {
  636. case ID_DISCONNECTION_NOTIFICATION:
  637. // Connection lost normally
  638. printf("ID_DISCONNECTION_NOTIFICATION\n");
  639. break;
  640. case ID_NEW_INCOMING_CONNECTION:
  641. printf("ID_NEW_INCOMING_CONNECTION\n");
  642. break;
  643. case ID_ALREADY_CONNECTED:
  644. // Connection lost normally
  645. printf("ID_ALREADY_CONNECTED\n");
  646. break;
  647. case ID_INCOMPATIBLE_PROTOCOL_VERSION:
  648. printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
  649. break;
  650. case ID_REMOTE_DISCONNECTION_NOTIFICATION: // Server telling the clients of another client disconnecting gracefully. You can manually broadcast this in a peer to peer enviroment if you want.
  651. printf("ID_REMOTE_DISCONNECTION_NOTIFICATION\n");
  652. break;
  653. case ID_REMOTE_CONNECTION_LOST: // Server telling the clients of another client disconnecting forcefully. You can manually broadcast this in a peer to peer enviroment if you want.
  654. printf("ID_REMOTE_CONNECTION_LOST\n");
  655. break;
  656. case ID_REMOTE_NEW_INCOMING_CONNECTION: // Server telling the clients of another client connecting. You can manually broadcast this in a peer to peer enviroment if you want.
  657. printf("ID_REMOTE_NEW_INCOMING_CONNECTION\n");
  658. break;
  659. case ID_CONNECTION_BANNED: // Banned from this server
  660. printf("We are banned from this server.\n");
  661. break;
  662. case ID_CONNECTION_ATTEMPT_FAILED:
  663. printf("Connection attempt failed\n");
  664. break;
  665. case ID_NO_FREE_INCOMING_CONNECTIONS:
  666. printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
  667. break;
  668. case ID_INVALID_PASSWORD:
  669. printf("ID_INVALID_PASSWORD\n");
  670. break;
  671. case ID_CONNECTION_LOST:
  672. printf("ID_CONNECTION_LOST from %s\n", packet->systemAddress.ToString(true));
  673. break;
  674. case ID_CONNECTION_REQUEST_ACCEPTED:
  675. // This tells the client they have connected
  676. printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", packet->systemAddress.ToString(true), packet->guid.ToString());
  677. printf("My external address is %s\n", rakPeer->GetExternalID(packet->systemAddress).ToString(true));
  678. break;
  679. }
  680. }
  681. enum FeatureList
  682. {
  683. _UPNPFramework,
  684. _NatTypeDetectionFramework,
  685. _NatPunchthoughFramework,
  686. _Router2Framework,
  687. _UDPProxyClientFramework,
  688. FEATURE_LIST_COUNT
  689. };
  690. int main(void)
  691. {
  692. RakNet::RakPeerInterface *rakPeer=RakNet::RakPeerInterface::GetInstance();
  693. printf("Enter local port, or press enter for default: ");
  694. char buff[64];
  695. Gets(buff,sizeof(buff));
  696. unsigned short port = DEFAULT_RAKPEER_PORT;
  697. if (buff[0]!=0)
  698. port = atoi(buff);
  699. RakNet::SocketDescriptor sd(port,0);
  700. if (rakPeer->Startup(32,&sd,1)!=RakNet::RAKNET_STARTED)
  701. {
  702. printf("Failed to start rakPeer! Quitting\n");
  703. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  704. getch();
  705. return 1;
  706. }
  707. rakPeer->SetMaximumIncomingConnections(32);
  708. SampleFramework *samples[FEATURE_LIST_COUNT];
  709. unsigned int i=0;
  710. samples[i++] = new UPNPFramework;
  711. samples[i++] = new NatTypeDetectionFramework;
  712. samples[i++] = new NatPunchthoughClientFramework;
  713. samples[i++] = new Router2Framework;
  714. samples[i++] = new UDPProxyClientFramework;
  715. assert(i==FEATURE_LIST_COUNT);
  716. bool isFirstPrint=true;
  717. for (i=0; i < FEATURE_LIST_COUNT; i++)
  718. {
  719. if (isFirstPrint)
  720. {
  721. printf("NAT traversal client\nSupported operations:\n");
  722. isFirstPrint=false;
  723. }
  724. printf("\n%s\nRequires server: %s\nDescription: %s\n", samples[i]->QueryName(), samples[i]->QueryRequiresServer()==1 ? "Yes" : "No", samples[i]->QueryFunction());
  725. }
  726. printf("\nDo you have a server running the NATCompleteServer project? (y/n): ");
  727. char responseLetter=getche();
  728. bool hasServer=responseLetter=='y' || responseLetter=='Y' || responseLetter==' ';
  729. printf("\n");
  730. if (hasServer==false)
  731. printf("Note: Only UPNP and Router2 are supported without a server\nYou may want to consider using the Lobby2/Steam project. They host the\nservers for you.\n\n");
  732. FeatureList currentStage=_UPNPFramework;
  733. if (hasServer==false)
  734. {
  735. while (samples[(int) currentStage]->QueryRequiresServer()==true)
  736. {
  737. printf("No server: Skipping %s\n", samples[(int) currentStage]->QueryName());
  738. int stageInt = (int) currentStage;
  739. stageInt++;
  740. currentStage=(FeatureList)stageInt;
  741. if (currentStage==FEATURE_LIST_COUNT)
  742. {
  743. printf("Connectivity not possible. Exiting\n");
  744. getch();
  745. return 1;
  746. }
  747. }
  748. }
  749. while (1)
  750. {
  751. printf("Executing %s\n", samples[(int) currentStage]->QueryName());
  752. samples[(int) currentStage]->Init(rakPeer);
  753. bool thisSampleDone=false;
  754. while (1)
  755. {
  756. samples[(int) currentStage]->Update(rakPeer);
  757. RakNet::Packet *packet;
  758. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  759. {
  760. for (i=0; i < FEATURE_LIST_COUNT; i++)
  761. {
  762. samples[i]->ProcessPacket(packet);
  763. }
  764. PrintPacketMessages(packet, rakPeer);
  765. }
  766. if (samples[(int) currentStage]->sampleResult==FAILED ||
  767. samples[(int) currentStage]->sampleResult==SUCCEEDED)
  768. {
  769. printf("\n");
  770. thisSampleDone=true;
  771. if (samples[(int) currentStage]->sampleResult==FAILED)
  772. {
  773. printf("Failed %s\n", samples[(int) currentStage]->QueryName());
  774. int stageInt = (int) currentStage;
  775. stageInt++;
  776. currentStage=(FeatureList)stageInt;
  777. if (currentStage==FEATURE_LIST_COUNT)
  778. {
  779. printf("Connectivity not possible. Exiting\n");
  780. rakPeer->Shutdown(100);
  781. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  782. getch();
  783. return 1;
  784. }
  785. else
  786. {
  787. printf("Proceeding to next stage.\n");
  788. break;
  789. }
  790. }
  791. else
  792. {
  793. printf("Passed %s\n", samples[(int) currentStage]->QueryName());
  794. if (samples[(int) currentStage]->QueryQuitOnSuccess())
  795. {
  796. printf("Press any key to quit.\n");
  797. while (!kbhit())
  798. {
  799. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  800. {
  801. for (i=0; i < FEATURE_LIST_COUNT; i++)
  802. {
  803. samples[i]->ProcessPacket(packet);
  804. }
  805. PrintPacketMessages(packet, rakPeer);
  806. }
  807. RakSleep(30);
  808. }
  809. rakPeer->Shutdown(100);
  810. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  811. printf("Press enter to quit.\n");
  812. char temp[32];
  813. Gets(temp,sizeof(temp));
  814. getch();
  815. return 1;
  816. }
  817. printf("Proceeding to next stage.\n");
  818. int stageInt = (int) currentStage;
  819. stageInt++;
  820. if (stageInt<FEATURE_LIST_COUNT)
  821. {
  822. currentStage=(FeatureList)stageInt;
  823. }
  824. else
  825. {
  826. printf("Press any key to quit when done.\n");
  827. while (!kbhit())
  828. {
  829. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  830. {
  831. for (i=0; i < FEATURE_LIST_COUNT; i++)
  832. {
  833. samples[i]->ProcessPacket(packet);
  834. }
  835. PrintPacketMessages(packet, rakPeer);
  836. }
  837. RakSleep(30);
  838. }
  839. rakPeer->Shutdown(100);
  840. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  841. getch();
  842. return 1;
  843. }
  844. break;
  845. }
  846. }
  847. RakSleep(30);
  848. }
  849. }
  850. getch();
  851. return 0;
  852. }
粤ICP备19079148号