main.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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 "UDPProxyServer.h"
  20. #include "UDPProxyCoordinator.h"
  21. #include "NatPunchthroughServer.h"
  22. #include "NatTypeDetectionServer.h"
  23. #include "SocketLayer.h"
  24. #include "Getche.h"
  25. #include "Gets.h"
  26. #include "CloudServerHelper.h"
  27. #include "CloudClient.h"
  28. #include "RakNetStatistics.h"
  29. #include "RelayPlugin.h"
  30. //#define VERBOSE_LOGGING
  31. using namespace RakNet;
  32. enum FeatureSupport
  33. {
  34. SUPPORTED,
  35. UNSUPPORTED,
  36. QUERY
  37. };
  38. enum FeatureList
  39. {
  40. NAT_TYPE_DETECTION_SERVER,
  41. NAT_PUNCHTHROUGH_SERVER,
  42. RELAY_PLUGIN,
  43. UDP_PROXY_COORDINATOR,
  44. UDP_PROXY_SERVER,
  45. CLOUD_SERVER,
  46. FEATURE_LIST_COUNT,
  47. };
  48. static int DEFAULT_RAKPEER_PORT=61111;
  49. #define NatTypeDetectionServerFramework_Supported QUERY
  50. #define NatPunchthroughServerFramework_Supported QUERY
  51. #define RelayPlugin_Supported QUERY
  52. #define UDPProxyCoordinatorFramework_Supported UNSUPPORTED
  53. #define UDPProxyServerFramework_Supported UNSUPPORTED
  54. #define CloudServerFramework_Supported QUERY
  55. struct SampleFramework
  56. {
  57. virtual const char * QueryName(void)=0;
  58. virtual const char * QueryRequirements(void)=0;
  59. virtual const char * QueryFunction(void)=0;
  60. virtual void Init(RakNet::RakPeerInterface *rakPeer)=0;
  61. virtual void ProcessPacket(RakNet::RakPeerInterface *rakPeer, Packet *packet)=0;
  62. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)=0;
  63. FeatureSupport isSupported;
  64. };
  65. struct NatTypeDetectionServerFramework : public SampleFramework
  66. {
  67. NatTypeDetectionServerFramework() {isSupported=NatTypeDetectionServerFramework_Supported; ntds=0;}
  68. virtual const char * QueryName(void) {return "NatTypeDetectionServer";}
  69. virtual const char * QueryRequirements(void) {return "Requires 4 IP addresses";}
  70. virtual const char * QueryFunction(void) {return "Determines router type to filter by connectable systems.\nOne instance needed, multiple instances may exist to spread workload.";}
  71. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  72. {
  73. if (isSupported==SUPPORTED)
  74. {
  75. ntds = new NatTypeDetectionServer;
  76. rakPeer->AttachPlugin(ntds);
  77. if (rakPeer->GetNumberOfAddresses() < 4)
  78. {
  79. printf("Failed. Not enough IP addresses to bind to.\n");
  80. rakPeer->DetachPlugin(ntds);
  81. delete ntds;
  82. ntds=0;
  83. isSupported=UNSUPPORTED;
  84. return;
  85. }
  86. ntds->Startup(rakPeer->GetLocalIP(1), rakPeer->GetLocalIP(2), rakPeer->GetLocalIP(3));
  87. }
  88. }
  89. virtual void ProcessPacket(RakNet::RakPeerInterface *rakPeer, Packet *packet)
  90. {
  91. }
  92. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  93. {
  94. if (ntds)
  95. {
  96. rakPeer->DetachPlugin(ntds);
  97. delete ntds;
  98. }
  99. ntds=0;
  100. }
  101. NatTypeDetectionServer *ntds;
  102. };
  103. struct NatPunchthroughServerFramework : public SampleFramework, public NatPunchthroughServerDebugInterface_Printf
  104. {
  105. NatPunchthroughServerFramework() {isSupported=NatPunchthroughServerFramework_Supported; nps=0;}
  106. virtual const char * QueryName(void) {return "NatPunchthroughServerFramework";}
  107. virtual const char * QueryRequirements(void) {return "None";}
  108. virtual const char * QueryFunction(void) {return "Coordinates NATPunchthroughClient.";}
  109. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  110. {
  111. if (isSupported==SUPPORTED)
  112. {
  113. nps = new NatPunchthroughServer;
  114. rakPeer->AttachPlugin(nps);
  115. #ifdef VERBOSE_LOGGING
  116. nps->SetDebugInterface(this);
  117. #endif
  118. }
  119. }
  120. virtual void ProcessPacket(RakNet::RakPeerInterface *rakPeer, Packet *packet)
  121. {
  122. }
  123. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  124. {
  125. if (nps)
  126. {
  127. rakPeer->DetachPlugin(nps);
  128. delete nps;
  129. }
  130. nps=0;
  131. }
  132. NatPunchthroughServer *nps;
  133. };
  134. struct RelayPluginFramework : public SampleFramework
  135. {
  136. RelayPluginFramework() {isSupported=RelayPlugin_Supported;}
  137. virtual const char * QueryName(void) {return "RelayPlugin";}
  138. virtual const char * QueryRequirements(void) {return "None.";}
  139. virtual const char * QueryFunction(void) {return "Relays messages between named connections.";}
  140. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  141. {
  142. if (isSupported==SUPPORTED)
  143. {
  144. relayPlugin = new RelayPlugin;
  145. rakPeer->AttachPlugin(relayPlugin);
  146. relayPlugin->SetAcceptAddParticipantRequests(true);
  147. }
  148. }
  149. virtual void ProcessPacket(RakNet::RakPeerInterface *rakPeer, Packet *packet)
  150. {
  151. }
  152. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  153. {
  154. if (relayPlugin)
  155. {
  156. rakPeer->DetachPlugin(relayPlugin);
  157. delete relayPlugin;
  158. relayPlugin=0;
  159. }
  160. }
  161. RelayPlugin *relayPlugin;
  162. };
  163. struct UDPProxyCoordinatorFramework : public SampleFramework
  164. {
  165. UDPProxyCoordinatorFramework() {udppc=0; isSupported=UDPProxyCoordinatorFramework_Supported;}
  166. virtual const char * QueryName(void) {return "UDPProxyCoordinator";}
  167. virtual const char * QueryRequirements(void) {return "Bandwidth to handle a few hundred bytes per game session.";}
  168. virtual const char * QueryFunction(void) {return "Coordinates UDPProxyClient to find available UDPProxyServer.\nExactly one instance required.";}
  169. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  170. {
  171. if (isSupported==SUPPORTED)
  172. {
  173. udppc = new UDPProxyCoordinator;
  174. rakPeer->AttachPlugin(udppc);
  175. char password[512];
  176. printf("Create password for UDPProxyCoordinator: ");
  177. Gets(password,sizeof(password));
  178. if (password[0]==0)
  179. {
  180. password[0]='a';
  181. password[1]=0;
  182. }
  183. udppc->SetRemoteLoginPassword(password);
  184. }
  185. }
  186. virtual void ProcessPacket(RakNet::RakPeerInterface *rakPeer, Packet *packet)
  187. {
  188. }
  189. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  190. {
  191. if (udppc)
  192. {
  193. rakPeer->DetachPlugin(udppc);
  194. delete udppc;
  195. udppc=0;
  196. }
  197. }
  198. UDPProxyCoordinator *udppc;
  199. };
  200. SystemAddress SelectAmongConnectedSystems(RakNet::RakPeerInterface *rakPeer, const char *hostName)
  201. {
  202. DataStructures::List<SystemAddress> addresses;
  203. DataStructures::List<RakNetGUID> guids;
  204. rakPeer->GetSystemList(addresses, guids);
  205. if (addresses.Size()==0)
  206. {
  207. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  208. }
  209. if (addresses.Size()>1)
  210. {
  211. printf("Select IP address for %s.\n", hostName);
  212. char buff[64];
  213. for (unsigned int i=0; i < addresses.Size(); i++)
  214. {
  215. addresses[i].ToString(true, buff);
  216. printf("%i. %s\n", i+1, buff);
  217. }
  218. Gets(buff,sizeof(buff));
  219. if (buff[0]==0)
  220. {
  221. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  222. }
  223. unsigned int idx = atoi(buff);
  224. if (idx<=0 || idx > addresses.Size())
  225. {
  226. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  227. }
  228. return addresses[idx-1];
  229. }
  230. else
  231. return addresses[0];
  232. };
  233. SystemAddress ConnectBlocking(RakNet::RakPeerInterface *rakPeer, const char *hostName)
  234. {
  235. char ipAddr[64];
  236. printf("Enter IP of system %s is running on: ", hostName);
  237. Gets(ipAddr,sizeof(ipAddr));
  238. if (ipAddr[0]==0)
  239. {
  240. printf("Failed. Not connected to %s.\n", hostName);
  241. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  242. }
  243. char port[64];
  244. printf("Enter port of system %s is running on: ", hostName);
  245. Gets(port, sizeof(port));
  246. if (port[0]==0)
  247. {
  248. printf("Failed. Not connected to %s.\n", hostName);
  249. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  250. }
  251. if (rakPeer->Connect(ipAddr, atoi(port), 0, 0)!=RakNet::CONNECTION_ATTEMPT_STARTED)
  252. {
  253. printf("Failed connect call for %s.\n", hostName);
  254. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  255. }
  256. printf("Connecting...\n");
  257. RakNet::Packet *packet;
  258. while (1)
  259. {
  260. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  261. {
  262. if (packet->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)
  263. {
  264. return packet->systemAddress;
  265. }
  266. else
  267. {
  268. return RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  269. }
  270. RakSleep(100);
  271. }
  272. }
  273. }
  274. struct UDPProxyServerFramework : public SampleFramework, public UDPProxyServerResultHandler
  275. {
  276. UDPProxyServerFramework() {udpps=0; isSupported=UDPProxyServerFramework_Supported;}
  277. virtual const char * QueryName(void) {return "UDPProxyServer";}
  278. virtual const char * QueryRequirements(void) {return "Bandwidth to handle forwarded game traffic.";}
  279. virtual const char * QueryFunction(void) {return "Allows game clients to forward network traffic transparently.\nOne or more instances required, can be added at runtime.";}
  280. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  281. {
  282. if (isSupported==SUPPORTED)
  283. {
  284. printf("Logging into UDPProxyCoordinator...\n");
  285. SystemAddress coordinatorAddress=SelectAmongConnectedSystems(rakPeer, "UDPProxyCoordinator");
  286. if (coordinatorAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  287. {
  288. printf("Warning: RakPeer is not currently connected to any system.\nEnter option:\n(1). UDPProxyCoordinator is on localhost\n(2). Connect to a remote system\n(3). Fail.\nOption: ");
  289. char ch=getche();
  290. printf("\n");
  291. if (ch=='1' || ch==13) // 13 is just pressing return
  292. {
  293. coordinatorAddress=rakPeer->GetInternalID(UNASSIGNED_SYSTEM_ADDRESS,0);
  294. }
  295. else if (ch=='2')
  296. {
  297. coordinatorAddress=ConnectBlocking(rakPeer, "UDPProxyCoordinator");
  298. if (coordinatorAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  299. {
  300. printf("Failed to connect.\n");
  301. isSupported=QUERY;
  302. return;
  303. }
  304. }
  305. else
  306. {
  307. printf("Failed. Not connected to UDPProxyCoordinator.\n");
  308. isSupported=QUERY;
  309. return;
  310. }
  311. }
  312. char password[512];
  313. printf("Enter password used with UDPProxyCoordinator: ");
  314. Gets(password,sizeof(password));
  315. if (password[0]==0)
  316. {
  317. password[0]='a';
  318. password[1]=0;
  319. }
  320. udpps = new UDPProxyServer;
  321. udpps->SetResultHandler(this);
  322. rakPeer->AttachPlugin(udpps);
  323. if (udpps->LoginToCoordinator(password, coordinatorAddress)==false)
  324. {
  325. printf("LoginToCoordinator call failed.\n");
  326. isSupported=QUERY;
  327. rakPeer->DetachPlugin(udpps);
  328. delete udpps;
  329. udpps=0;
  330. return;
  331. }
  332. }
  333. }
  334. virtual void ProcessPacket(RakNet::RakPeerInterface *rakPeer, Packet *packet)
  335. {
  336. }
  337. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  338. {
  339. if (udpps)
  340. {
  341. rakPeer->DetachPlugin(udpps);
  342. delete udpps;
  343. udpps=0;
  344. }
  345. }
  346. virtual void OnLoginSuccess(RakNet::RakString usedPassword, RakNet::UDPProxyServer *proxyServerPlugin)
  347. {
  348. printf("%s logged into UDPProxyCoordinator.\n", QueryName());
  349. }
  350. virtual void OnAlreadyLoggedIn(RakNet::RakString usedPassword, RakNet::UDPProxyServer *proxyServerPlugin)
  351. {
  352. printf("%s already logged into UDPProxyCoordinator.\n", QueryName());
  353. }
  354. virtual void OnNoPasswordSet(RakNet::RakString usedPassword, RakNet::UDPProxyServer *proxyServerPlugin)
  355. {
  356. printf("%s failed login to UDPProxyCoordinator. No password set.\n", QueryName());
  357. isSupported=QUERY;
  358. delete udpps;
  359. udpps=0;
  360. }
  361. virtual void OnWrongPassword(RakNet::RakString usedPassword, RakNet::UDPProxyServer *proxyServerPlugin)
  362. {
  363. printf("%s failed login to UDPProxyCoordinator. %s was the wrong password.\n", QueryName(), usedPassword.C_String());
  364. isSupported=QUERY;
  365. delete udpps;
  366. udpps=0;
  367. }
  368. UDPProxyServer *udpps;
  369. };
  370. struct CloudServerFramework : public SampleFramework
  371. {
  372. CloudServerFramework() {isSupported=CloudServerFramework_Supported;}
  373. virtual const char * QueryName(void) {return "CloudServer";}
  374. virtual const char * QueryRequirements(void) {return "None.";}
  375. virtual const char * QueryFunction(void) {return "Single instance cloud server that maintains connection counts\nUseful as a directory server to find other client instances.";}
  376. virtual void Init(RakNet::RakPeerInterface *rakPeer)
  377. {
  378. if (isSupported==SUPPORTED)
  379. {
  380. cloudServer = new CloudServer;
  381. rakPeer->AttachPlugin(cloudServer);
  382. cloudClient = new CloudClient;
  383. rakPeer->AttachPlugin(cloudClient);
  384. cloudServerHelperFilter = new CloudServerHelperFilter;
  385. cloudServer->AddQueryFilter(cloudServerHelperFilter);
  386. cloudServer->SetMaxUploadBytesPerClient(65535);
  387. cloudServerHelper.OnConnectionCountChange(rakPeer, cloudClient);
  388. }
  389. }
  390. virtual void ProcessPacket(RakNet::RakPeerInterface *rakPeer, Packet *packet)
  391. {
  392. if (isSupported!=SUPPORTED)
  393. return;
  394. switch (packet->data[0])
  395. {
  396. case ID_NEW_INCOMING_CONNECTION:
  397. #ifdef VERBOSE_LOGGING
  398. printf("Got connection to %s\n", packet->systemAddress.ToString(true));
  399. #endif
  400. cloudServerHelper.OnConnectionCountChange(rakPeer, cloudClient);
  401. break;
  402. case ID_CONNECTION_LOST:
  403. case ID_DISCONNECTION_NOTIFICATION:
  404. #ifdef VERBOSE_LOGGING
  405. printf("Lost connection to %s\n", packet->systemAddress.ToString(true));
  406. #endif
  407. cloudServerHelper.OnConnectionCountChange(rakPeer, cloudClient);
  408. break;
  409. }
  410. }
  411. virtual void Shutdown(RakNet::RakPeerInterface *rakPeer)
  412. {
  413. if (cloudServer)
  414. {
  415. rakPeer->DetachPlugin(cloudServer);
  416. delete cloudServer;
  417. cloudServer=0;
  418. rakPeer->DetachPlugin(cloudClient);
  419. delete cloudClient;
  420. cloudClient=0;
  421. delete cloudServerHelperFilter;
  422. cloudServerHelperFilter=0;
  423. }
  424. }
  425. RakNet::CloudServer *cloudServer;
  426. RakNet::CloudClient *cloudClient;
  427. RakNet::CloudServerHelperFilter *cloudServerHelperFilter;
  428. RakNet::CloudServerHelper cloudServerHelper;
  429. };
  430. int main(int argc, char **argv)
  431. {
  432. RakNet::RakPeerInterface *rakPeer=RakNet::RakPeerInterface::GetInstance();
  433. SystemAddress ipList[ MAXIMUM_NUMBER_OF_INTERNAL_IDS ];
  434. printf("IPs:\n");
  435. unsigned int i;
  436. for (i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
  437. {
  438. ipList[i]=rakPeer->GetLocalIP(i);
  439. if (ipList[i]!=UNASSIGNED_SYSTEM_ADDRESS)
  440. printf("%i. %s\n", i+1, ipList[i].ToString(false));
  441. else
  442. break;
  443. }
  444. // If RakPeer is started on 2 IP addresses, NATPunchthroughServer supports port stride detection, improving success rate
  445. int sdLen=1;
  446. RakNet::SocketDescriptor sd[2];
  447. if (argc>1)
  448. {
  449. DEFAULT_RAKPEER_PORT = atoi(argv[1]);
  450. }
  451. sd[0].port=DEFAULT_RAKPEER_PORT;
  452. printf("Using port %i\n", sd[0].port);
  453. if (i>=2)
  454. {
  455. strcpy(sd[0].hostAddress, ipList[0].ToString(false));
  456. sd[1].port=DEFAULT_RAKPEER_PORT+1;
  457. strcpy(sd[1].hostAddress, ipList[1].ToString(false));
  458. sdLen=2;
  459. }
  460. if (rakPeer->Startup(8096,sd,sdLen)!=RakNet::RAKNET_STARTED)
  461. {
  462. printf("Failed to start rakPeer! Quitting\n");
  463. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  464. return 1;
  465. }
  466. rakPeer->SetTimeoutTime(5000, UNASSIGNED_SYSTEM_ADDRESS);
  467. printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true));
  468. printf("\n");
  469. rakPeer->SetMaximumIncomingConnections(8096);
  470. SampleFramework *samples[FEATURE_LIST_COUNT];
  471. i=0;
  472. samples[i++] = new NatTypeDetectionServerFramework;
  473. samples[i++] = new NatPunchthroughServerFramework;
  474. samples[i++] = new RelayPluginFramework;
  475. samples[i++] = new UDPProxyCoordinatorFramework;
  476. samples[i++] = new UDPProxyServerFramework;
  477. samples[i++] = new CloudServerFramework;
  478. assert(i==FEATURE_LIST_COUNT);
  479. bool isFirstPrint=true;
  480. for (i=0; i < FEATURE_LIST_COUNT; i++)
  481. {
  482. if (samples[i]->isSupported==QUERY)
  483. {
  484. if (isFirstPrint)
  485. {
  486. printf("NAT traversal server.\nSee http://www.dx.net/raknet_dx.php for discounted server hosting\nSelect which features to support.\n");
  487. isFirstPrint=false;
  488. }
  489. printf("\n%s\nRequirements: %s\nDescription: %s\n", samples[i]->QueryName(), samples[i]->QueryRequirements(), samples[i]->QueryFunction());
  490. printf("Support %s? (y/n): ", samples[i]->QueryName());
  491. char supported=getche();
  492. if (supported=='y' || supported=='Y' || supported==13) // 13 is just pressing return
  493. {
  494. samples[i]->isSupported=SUPPORTED;
  495. }
  496. printf("\n");
  497. }
  498. }
  499. printf("\n");
  500. for (i=0; i < FEATURE_LIST_COUNT; i++)
  501. {
  502. if (samples[i]->isSupported==SUPPORTED)
  503. {
  504. printf("Starting %s...\n", samples[i]->QueryName());
  505. samples[i]->Init(rakPeer);
  506. if (samples[i]->isSupported!=SUPPORTED)
  507. {
  508. printf("Failed to start %s.", samples[i]->QueryName());
  509. if (samples[i]->isSupported==QUERY)
  510. {
  511. printf(" Retry? (y/n): ");
  512. char supported=getche();
  513. if (supported=='y' || supported=='Y')
  514. {
  515. samples[i]->isSupported=SUPPORTED;
  516. i--;
  517. }
  518. }
  519. else
  520. printf("\n");
  521. printf("\n");
  522. }
  523. else
  524. printf("Success.\n\n");
  525. }
  526. }
  527. bool anySupported=false;
  528. for (i=0; i < FEATURE_LIST_COUNT; i++)
  529. {
  530. if (samples[i]->isSupported==SUPPORTED)
  531. {
  532. anySupported=true;
  533. break;
  534. }
  535. }
  536. if (anySupported==false)
  537. {
  538. printf("No features supported! Quitting.\n");
  539. rakPeer->Shutdown(100);
  540. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  541. return 1;
  542. }
  543. bool firstComma=true;
  544. printf("Supported features: ");
  545. for (i=0; i < FEATURE_LIST_COUNT; i++)
  546. {
  547. if (samples[i]->isSupported==SUPPORTED)
  548. {
  549. if (firstComma==false)
  550. printf(", ");
  551. else
  552. firstComma=false;
  553. printf("%s", samples[i]->QueryName());
  554. }
  555. }
  556. printf("\nEntering update loop. Press 'q' to quit.\n");
  557. RakNet::Packet *packet;
  558. bool quit=false;
  559. while (!quit)
  560. {
  561. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  562. {
  563. for (i=0; i < FEATURE_LIST_COUNT; i++)
  564. {
  565. samples[i]->ProcessPacket(rakPeer, packet);
  566. }
  567. }
  568. if (kbhit())
  569. {
  570. char ch = getch();
  571. if (ch=='q')
  572. {
  573. quit=true;
  574. }
  575. else if (ch==' ')
  576. {
  577. RakNetStatistics rns;
  578. char message[2048];
  579. bool hasStatistics = rakPeer->GetStatistics(0, &rns);
  580. if (hasStatistics)
  581. {
  582. StatisticsToString(&rns, message, 2);
  583. printf("SYSTEM 0:\n%s\n", message);
  584. memset(&rns, 0, sizeof(RakNetStatistics));
  585. rakPeer->GetStatistics(UNASSIGNED_SYSTEM_ADDRESS, &rns);
  586. StatisticsToString(&rns, message, 2);
  587. printf("STAT SUM:\n%s\n", message);
  588. }
  589. else
  590. {
  591. printf("No system 0\n");
  592. }
  593. DataStructures::List<SystemAddress> addresses;
  594. DataStructures::List<RakNetGUID> guids;
  595. rakPeer->GetSystemList(addresses, guids);
  596. printf("%i systems connected\n", addresses.Size());
  597. }
  598. }
  599. RakSleep(30);
  600. }
  601. printf("Quitting.\n");
  602. for (i=0; i < FEATURE_LIST_COUNT; i++)
  603. {
  604. samples[i]->Shutdown(rakPeer);
  605. }
  606. rakPeer->Shutdown(100);
  607. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  608. return 0;
  609. }
粤ICP备19079148号