CloudServerHelper.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  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 "CloudServerHelper.h"
  11. #include "RakSleep.h"
  12. #include "Gets.h"
  13. #include "MessageIdentifiers.h"
  14. #include "BitStream.h"
  15. #include "FullyConnectedMesh2.h"
  16. #include "TwoWayAuthentication.h"
  17. #include "CloudClient.h"
  18. #include "DynDNS.h"
  19. #include "SocketLayer.h"
  20. #include "RakPeerInterface.h"
  21. #include "ConnectionGraph2.h"
  22. #include <stdlib.h>
  23. using namespace RakNet;
  24. #define CLOUD_SERVER_CONNECTION_COUNT_PRIMARY_KEY "CloudConnCount"
  25. bool CloudServerHelperFilter::OnPostRequest(RakNetGUID clientGuid, SystemAddress clientAddress, CloudKey key, uint32_t dataLength, const char *data)
  26. {
  27. if (clientGuid!=serverGuid)
  28. {
  29. if (key.primaryKey==CLOUD_SERVER_CONNECTION_COUNT_PRIMARY_KEY)
  30. return false;
  31. }
  32. return true;
  33. }
  34. bool CloudServerHelperFilter::OnReleaseRequest(RakNetGUID clientGuid, SystemAddress clientAddress, DataStructures::List<CloudKey> &cloudKeys) {return true;}
  35. bool CloudServerHelperFilter::OnGetRequest(RakNetGUID clientGuid, SystemAddress clientAddress, CloudQuery &query, DataStructures::List<RakNetGUID> &specificSystems) {return true;}
  36. bool CloudServerHelperFilter::OnUnsubscribeRequest(RakNetGUID clientGuid, SystemAddress clientAddress, DataStructures::List<CloudKey> &cloudKeys, DataStructures::List<RakNetGUID> &specificSystems) {return true;}
  37. bool CloudServerHelper::ParseCommandLineParameters(int argc, char **argv)
  38. {
  39. char *DEFAULT_SERVER_TO_SERVER_PASSWORD="qwerty1234";
  40. const unsigned short DEFAULT_SERVER_PORT=60000;
  41. const unsigned short DEFAULT_ALLOWED_INCOMING_CONNECTIONS=1024;
  42. const unsigned short DEFAULT_ALLOWED_OUTGOING_CONNECTIONS=64;
  43. if (argc<2) serverToServerPassword=DEFAULT_SERVER_TO_SERVER_PASSWORD;
  44. else serverToServerPassword=argv[1];
  45. if (argc<3) rakPeerPort=DEFAULT_SERVER_PORT;
  46. else rakPeerPort=atoi(argv[2]);
  47. if (argc<4) allowedIncomingConnections=DEFAULT_ALLOWED_INCOMING_CONNECTIONS;
  48. else allowedIncomingConnections=atoi(argv[3]);
  49. if (argc<5) allowedOutgoingConnections=DEFAULT_ALLOWED_OUTGOING_CONNECTIONS;
  50. else allowedOutgoingConnections=atoi(argv[4]);
  51. return true;
  52. }
  53. bool CloudServerHelper_DynDns::ParseCommandLineParameters(int argc, char **argv)
  54. {
  55. char *DEFAULT_DNS_HOST="test.dnsalias.net";
  56. char *DEFAULT_USERNAME_AND_PASSWORD="test:test";
  57. char *DEFAULT_SERVER_TO_SERVER_PASSWORD="qwerty1234";
  58. const unsigned short DEFAULT_SERVER_PORT=60000;
  59. const unsigned short DEFAULT_ALLOWED_INCOMING_CONNECTIONS=1024;
  60. const unsigned short DEFAULT_ALLOWED_OUTGOING_CONNECTIONS=64;
  61. #ifndef _DEBUG
  62. // Only allow insecure defaults for debugging
  63. if (argc<4)
  64. {
  65. PrintHelp();
  66. return false;
  67. }
  68. dnsHost=argv[1];
  69. dynDNSUsernameAndPassword=argv[2];
  70. serverToServerPassword=argv[3];
  71. #else
  72. if (argc<2) dnsHost=DEFAULT_DNS_HOST;
  73. else dnsHost=argv[1];
  74. if (argc<3) dynDNSUsernameAndPassword=DEFAULT_USERNAME_AND_PASSWORD;
  75. else dynDNSUsernameAndPassword=argv[2];
  76. if (argc<4) serverToServerPassword=DEFAULT_SERVER_TO_SERVER_PASSWORD;
  77. else serverToServerPassword=argv[3];
  78. #endif
  79. if (argc<5) rakPeerPort=DEFAULT_SERVER_PORT;
  80. else rakPeerPort=atoi(argv[4]);
  81. if (argc<6) allowedIncomingConnections=DEFAULT_ALLOWED_INCOMING_CONNECTIONS;
  82. else allowedIncomingConnections=atoi(argv[5]);
  83. if (argc<7) allowedOutgoingConnections=DEFAULT_ALLOWED_OUTGOING_CONNECTIONS;
  84. else allowedOutgoingConnections=atoi(argv[6]);
  85. return true;
  86. }
  87. void CloudServerHelper::PrintHelp(void)
  88. {
  89. printf("Distributed authenticated CloudServer using DNS based host migration.\n");
  90. printf("Query running servers with CloudClient::Get() on key CloudServerList,0\n\n");
  91. printf("Query load with key CloudConnCount,0. Read row data as unsigned short.\n\n");
  92. printf("Usage:\n");
  93. printf("CloudServer.exe DNSHost Username:Password S2SPWD [Port] [ConnIn] [ConnOut]\n\n");
  94. printf("Parameters:\n");
  95. printf("DNSHost - Free DNS hostname from http://www.dyndns.com/\n");
  96. printf("Username:Password - Account settings from http://www.dyndns.com/\n");
  97. printf("S2SPWD - Server to server cloud password. Anything random.\n");
  98. printf("Port - RakNet listen port. Default is 60000\n");
  99. printf("ConnIn - Max incoming connections for clients. Default is 1024\n");
  100. printf("ConnIn - Max outgoing connections, used for server to server. Default 64\n\n");
  101. printf("Example:\n");
  102. printf("CloudServer.exe test.dnsalias.net test:test qwerty1234 60000 1024 64\n\n");
  103. }
  104. bool CloudServerHelper::StartRakPeer(RakNet::RakPeerInterface *rakPeer)
  105. {
  106. RakNet::SocketDescriptor sd(RakNet::CloudServerHelper::rakPeerPort,0);
  107. RakNet::StartupResult sr = rakPeer->Startup(RakNet::CloudServerHelper::allowedIncomingConnections+RakNet::CloudServerHelper::allowedOutgoingConnections,&sd,1);
  108. if (sr!=RakNet::RAKNET_STARTED)
  109. {
  110. printf("Startup failed. Reason=%i\n", (int) sr);
  111. return false;
  112. }
  113. rakPeer->SetMaximumIncomingConnections(RakNet::CloudServerHelper::allowedIncomingConnections);
  114. //rakPeer->SetTimeoutTime(60000,UNASSIGNED_SYSTEM_ADDRESS);
  115. return true;
  116. }
  117. Packet *CloudServerHelper::ConnectToRakPeer(const char *host, unsigned short port, RakPeerInterface *rakPeer)
  118. {
  119. printf("RakPeer: Connecting to %s\n", host);
  120. ConnectionAttemptResult car;
  121. car = rakPeer->Connect(host, port, 0, 0);
  122. if (car!=CONNECTION_ATTEMPT_STARTED)
  123. {
  124. printf("Connect() call failed\n");
  125. if (car==CANNOT_RESOLVE_DOMAIN_NAME) printf("Cannot resolve domain name\n");
  126. return 0;
  127. }
  128. Packet *packet;
  129. while (1)
  130. {
  131. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  132. {
  133. switch (packet->data[0])
  134. {
  135. case ID_CONNECTION_ATTEMPT_FAILED:
  136. return packet;
  137. case ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY:
  138. case ID_OUR_SYSTEM_REQUIRES_SECURITY:
  139. case ID_PUBLIC_KEY_MISMATCH:
  140. case ID_CONNECTION_BANNED:
  141. case ID_INVALID_PASSWORD:
  142. case ID_INCOMPATIBLE_PROTOCOL_VERSION:
  143. return packet;
  144. case ID_NO_FREE_INCOMING_CONNECTIONS:
  145. case ID_IP_RECENTLY_CONNECTED:
  146. printf("Remote system full. Retrying...");
  147. car = rakPeer->Connect(host, port, 0, 0);
  148. if (car!=CONNECTION_ATTEMPT_STARTED)
  149. {
  150. printf("Connect() call failed\n");
  151. if (car==CANNOT_RESOLVE_DOMAIN_NAME) printf("Cannot resolve domain name\n");
  152. return 0;
  153. }
  154. break;
  155. case ID_CONNECTION_REQUEST_ACCEPTED:
  156. if (packet->guid==rakPeer->GetMyGUID())
  157. {
  158. // Just connected to myself! Host must be pointing to our own IP address.
  159. rakPeer->CloseConnection(packet->guid,false);
  160. RakSleep(30); // Let the thread clear out
  161. packet->data[0]=ID_ALREADY_CONNECTED;
  162. return packet;
  163. }
  164. case ID_ALREADY_CONNECTED:
  165. return packet; // Not initial host
  166. }
  167. }
  168. RakSleep(30);
  169. }
  170. }
  171. bool CloudServerHelper_DynDns::SetHostDNSToThisSystemBlocking(void)
  172. {
  173. dynDNS->UpdateHostIPAsynch(
  174. dnsHost,
  175. 0,
  176. dynDNSUsernameAndPassword);
  177. // Wait for the DNS update to complete
  178. while (1)
  179. {
  180. dynDNS->Update();
  181. if (dynDNS->IsCompleted())
  182. {
  183. printf("%s\n", dynDNS->GetCompletedDescription());
  184. return dynDNS->WasResultSuccessful();
  185. }
  186. RakSleep(30);
  187. }
  188. return false;
  189. }
  190. MessageID CloudServerHelper::AuthenticateRemoteServerBlocking(RakPeerInterface *rakPeer, TwoWayAuthentication *twoWayAuthentication, RakNetGUID remoteSystem)
  191. {
  192. twoWayAuthentication->Challenge("CloudServerHelperS2SPassword", remoteSystem);
  193. MessageID messageId;
  194. Packet *packet;
  195. while (1)
  196. {
  197. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  198. {
  199. switch (packet->data[0])
  200. {
  201. case ID_CONNECTION_LOST:
  202. case ID_DISCONNECTION_NOTIFICATION:
  203. if (packet->guid==remoteSystem)
  204. {
  205. messageId=packet->data[0];
  206. rakPeer->DeallocatePacket(packet);
  207. return messageId;
  208. }
  209. break;
  210. case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS:
  211. case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT:
  212. case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE:
  213. {
  214. messageId=packet->data[0];
  215. rakPeer->DeallocatePacket(packet);
  216. return messageId;
  217. }
  218. break;
  219. }
  220. }
  221. RakSleep(30);
  222. }
  223. }
  224. void CloudServerHelper::SetupPlugins(
  225. RakNet::CloudServer *cloudServer,
  226. RakNet::CloudServerHelperFilter *sampleFilter,
  227. RakNet::CloudClient *cloudClient,
  228. RakNet::FullyConnectedMesh2 *fullyConnectedMesh2,
  229. RakNet::TwoWayAuthentication *twoWayAuthentication,
  230. RakNet::ConnectionGraph2 *connectionGraph2,
  231. const char *serverToServerPassword
  232. )
  233. {
  234. cloudServer->AddQueryFilter(sampleFilter);
  235. // Connect to all systems told about via ConnectionGraph2::AddParticpant(). We are only told about servers that have already been authenticated
  236. fullyConnectedMesh2->SetConnectOnNewRemoteConnection(true, "");
  237. // Do not add to the host trracking system all connections, only those designated as servers
  238. fullyConnectedMesh2->SetAutoparticipateConnections(false);
  239. // Shared password
  240. twoWayAuthentication->AddPassword("CloudServerHelperS2SPassword",serverToServerPassword);
  241. // Do not add systems to the graph unless first validated as a server through the TwoWayAuthentication plugin
  242. connectionGraph2->SetAutoProcessNewConnections(false);
  243. }
  244. void CloudServerHelper::OnPacket(Packet *packet, RakPeerInterface *rakPeer, CloudClient *cloudClient, RakNet::CloudServer *cloudServer, RakNet::FullyConnectedMesh2 *fullyConnectedMesh2, TwoWayAuthentication *twoWayAuthentication, ConnectionGraph2 *connectionGraph2)
  245. {
  246. switch (packet->data[0])
  247. {
  248. case ID_FCM2_NEW_HOST:
  249. RakNet::CloudServerHelper::OnFCMNewHost(packet, rakPeer);
  250. break;
  251. case ID_CONNECTION_REQUEST_ACCEPTED:
  252. twoWayAuthentication->Challenge("CloudServerHelperS2SPassword", packet->guid);
  253. // Fallthrough
  254. case ID_NEW_INCOMING_CONNECTION:
  255. printf("Got connection to %s\n", packet->systemAddress.ToString(true));
  256. RakNet::CloudServerHelper::OnConnectionCountChange(rakPeer, cloudClient);
  257. break;
  258. case ID_CONNECTION_LOST:
  259. // printf("ID_CONNECTION_LOST (UDP) from %s\n", packet->systemAddress.ToString(true));
  260. RakNet::CloudServerHelper::OnConnectionCountChange(rakPeer, cloudClient);
  261. break;
  262. case ID_DISCONNECTION_NOTIFICATION:
  263. // printf("ID_DISCONNECTION_NOTIFICATION (UDP) from %s\n", packet->systemAddress.ToString(true));
  264. RakNet::CloudServerHelper::OnConnectionCountChange(rakPeer, cloudClient);
  265. break;
  266. case ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_SUCCESS:
  267. printf("New server connected to us from %s\n", packet->systemAddress.ToString(true));
  268. // Fallthrough
  269. case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS:
  270. if (packet->data[0]==ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS)
  271. printf("We connected to server %s\n", packet->systemAddress.ToString(true));
  272. cloudServer->AddServer(packet->guid);
  273. fullyConnectedMesh2->AddParticipant(packet->guid);
  274. connectionGraph2->AddParticipant(packet->systemAddress, packet->guid);
  275. break;
  276. case ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_FAILURE:
  277. case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE:
  278. case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT:
  279. rakPeer->CloseConnection(packet->guid,false);
  280. break;
  281. }
  282. }
  283. bool CloudServerHelper::Update(void)
  284. {
  285. return true;
  286. }
  287. CloudServerHelper_DynDns::CloudServerHelper_DynDns(DynDNS *_dynDns)
  288. {
  289. dynDNS = _dynDns;
  290. }
  291. bool CloudServerHelper_DynDns::Update(void)
  292. {
  293. // Keep DNS updated if needed
  294. if (dynDNS->IsRunning())
  295. {
  296. dynDNS->Update();
  297. if (dynDNS->IsCompleted())
  298. {
  299. printf("%s.\n", dynDNS->GetCompletedDescription());
  300. if (dynDNS->WasResultSuccessful()==false)
  301. return false;
  302. printf("Note: The DNS cache update takes about 60 seconds.\n");
  303. }
  304. }
  305. return true;
  306. }
  307. void CloudServerHelper::OnFCMNewHost(Packet *packet, RakPeerInterface *rakPeer)
  308. {
  309. }
  310. void CloudServerHelper_DynDns::OnFCMNewHost(Packet *packet, RakPeerInterface *rakPeer)
  311. {
  312. RakAssert(packet->data[0]==ID_FCM2_NEW_HOST);
  313. RakNet::BitStream bsIn(packet->data, packet->length, false);
  314. bsIn.IgnoreBytes(sizeof(MessageID));
  315. RakNetGUID oldHost;
  316. bsIn.Read(oldHost);
  317. RakNetGUID newHost = packet->guid;
  318. if (newHost==rakPeer->GetMyGUID() && oldHost!=newHost)
  319. {
  320. printf("Assuming host. Updating DNS\n");
  321. // Change dynDNS to point to us
  322. dynDNS->UpdateHostIPAsynch(
  323. dnsHost,
  324. 0,
  325. dynDNSUsernameAndPassword);
  326. }
  327. }
  328. void CloudServerHelper::OnConnectionCountChange(RakPeerInterface *rakPeer, CloudClient *cloudClient)
  329. {
  330. RakNet::BitStream bs;
  331. CloudKey cloudKey(CLOUD_SERVER_CONNECTION_COUNT_PRIMARY_KEY,0);
  332. unsigned short numberOfSystems;
  333. rakPeer->GetConnectionList(0, &numberOfSystems);
  334. bs.Write(numberOfSystems);
  335. cloudClient->Post(&cloudKey, bs.GetData(), bs.GetNumberOfBytesUsed(), rakPeer->GetMyGUID());
  336. }
  337. int CloudServerHelper_DynDns::OnJoinCloudResult(
  338. Packet *packet,
  339. RakNet::RakPeerInterface *rakPeer,
  340. RakNet::CloudServer *cloudServer,
  341. RakNet::CloudClient *cloudClient,
  342. RakNet::FullyConnectedMesh2 *fullyConnectedMesh2,
  343. RakNet::TwoWayAuthentication *twoWayAuthentication,
  344. RakNet::ConnectionGraph2 *connectionGraph2,
  345. const char *rakPeerIpOrDomain,
  346. char myPublicIP[32]
  347. )
  348. {
  349. if (packet->data[0]==ID_CONNECTION_ATTEMPT_FAILED)
  350. {
  351. printf("Failed connection. Changing DNS to point to this system.\n");
  352. if (SetHostDNSToThisSystemBlocking()==false)
  353. return 1;
  354. // dynDNS gets our public IP when it succeeds
  355. strcpy( myPublicIP, dynDNS->GetMyPublicIP());
  356. }
  357. return CloudServerHelper::OnJoinCloudResult(packet, rakPeer, cloudServer, cloudClient, fullyConnectedMesh2, twoWayAuthentication, connectionGraph2, rakPeerIpOrDomain, myPublicIP);
  358. }
  359. int CloudServerHelper::OnJoinCloudResult(
  360. Packet *packet,
  361. RakNet::RakPeerInterface *rakPeer,
  362. RakNet::CloudServer *cloudServer,
  363. RakNet::CloudClient *cloudClient,
  364. RakNet::FullyConnectedMesh2 *fullyConnectedMesh2,
  365. RakNet::TwoWayAuthentication *twoWayAuthentication,
  366. RakNet::ConnectionGraph2 *connectionGraph2,
  367. const char *rakPeerIpOrDomain,
  368. char myPublicIP[32]
  369. )
  370. {
  371. RakNet::MessageID result;
  372. SystemAddress packetAddress;
  373. RakNetGUID packetGuid;
  374. result = packet->data[0];
  375. packetAddress = packet->systemAddress;
  376. packetGuid = packet->guid;
  377. if (result==ID_CONNECTION_REQUEST_ACCEPTED)
  378. {
  379. printf("Connected to host %s.\n", rakPeerIpOrDomain);
  380. // We connected through a public IP.
  381. // Our external IP should also be public
  382. // rakPeer->GetExternalID(packetAddress).ToString(false, myPublicIP);
  383. // Log in to the remote server using two way authentication
  384. result = RakNet::CloudServerHelper::AuthenticateRemoteServerBlocking(rakPeer, twoWayAuthentication, packetGuid);
  385. if (result==ID_CONNECTION_LOST || result==ID_DISCONNECTION_NOTIFICATION)
  386. {
  387. printf("Connection lost while authenticating.\n");
  388. printf("Waiting 60 seconds then restarting.\n");
  389. RakSleep(60000);
  390. return 2;
  391. }
  392. else if (result==ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT)
  393. {
  394. // Other system is not running plugin? Fail
  395. printf("Remote server did not respond to challenge.\n");
  396. return 1;
  397. }
  398. else if (result==ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE)
  399. {
  400. printf("Failed remote server challenge.\n");
  401. return 1;
  402. }
  403. RakAssert(result==ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS);
  404. // Add this system as a server, and to FullyConnectedMesh2 as a participant
  405. cloudServer->AddServer(packetGuid);
  406. fullyConnectedMesh2->AddParticipant(packetGuid);
  407. connectionGraph2->AddParticipant(packetAddress, packetGuid);
  408. }
  409. else if (result==ID_ALREADY_CONNECTED)
  410. {
  411. printf("Connected to self. DNS entry already points to this server.\n");
  412. /*
  413. if (SetHostDNSToThisSystemBlocking()==false)
  414. return 1;
  415. // dynDNS gets our public IP when it succeeds
  416. strcpy( myPublicIP, dynDNS->GetMyPublicIP());
  417. */
  418. // dnsHost is always public, so if I can connect through it that's my public IP
  419. RakNetSocket2::DomainNameToIP( rakPeerIpOrDomain, myPublicIP );
  420. }
  421. else if (result==ID_CONNECTION_ATTEMPT_FAILED)
  422. {
  423. }
  424. else
  425. {
  426. // Another server is running but we cannot connect to them
  427. printf("Critical failure\n");
  428. printf("Reason: ");
  429. switch (result)
  430. {
  431. case ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY:
  432. case ID_OUR_SYSTEM_REQUIRES_SECURITY:
  433. case ID_PUBLIC_KEY_MISMATCH:
  434. printf("Other system is running security code.\n");
  435. break;
  436. case ID_CONNECTION_BANNED:
  437. printf("Banned from the other system.\n");
  438. break;
  439. case ID_INVALID_PASSWORD:
  440. printf("Other system has a password.\n");
  441. break;
  442. case ID_INCOMPATIBLE_PROTOCOL_VERSION:
  443. printf("Different major RakNet version.\n");
  444. break;
  445. default:
  446. printf("N/A\n");
  447. break;
  448. }
  449. return 1;
  450. }
  451. // Force the external server address for queries. Otherwise it would report 127.0.0.1 since the client is on localhost
  452. SystemAddress forceAddress;
  453. forceAddress.FromString(myPublicIP,RakNet::CloudServerHelper::rakPeerPort);
  454. cloudServer->ForceExternalSystemAddress(forceAddress);
  455. if (result==ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS)
  456. {
  457. OnConnectionCountChange(rakPeer, cloudClient);
  458. }
  459. else
  460. {
  461. RakNet::BitStream bs;
  462. CloudKey cloudKey(CLOUD_SERVER_CONNECTION_COUNT_PRIMARY_KEY,0);
  463. bs.WriteCasted<unsigned short>(0);
  464. cloudClient->Post(&cloudKey, bs.GetData(), bs.GetNumberOfBytesUsed(), rakPeer->GetMyGUID());
  465. }
  466. return 0;
  467. }
  468. int CloudServerHelper::JoinCloud(
  469. RakNet::RakPeerInterface *rakPeer,
  470. RakNet::CloudServer *cloudServer,
  471. RakNet::CloudClient *cloudClient,
  472. RakNet::FullyConnectedMesh2 *fullyConnectedMesh2,
  473. RakNet::TwoWayAuthentication *twoWayAuthentication,
  474. RakNet::ConnectionGraph2 *connectionGraph2,
  475. const char *rakPeerIpOrDomain
  476. )
  477. {
  478. Packet *packet;
  479. char myPublicIP[32];
  480. // Reset plugins
  481. cloudServer->Clear();
  482. fullyConnectedMesh2->Clear();
  483. // ---- CONNECT TO EXISTING SERVER ----
  484. packet = RakNet::CloudServerHelper::ConnectToRakPeer(rakPeerIpOrDomain, RakNet::CloudServerHelper::rakPeerPort, rakPeer);
  485. if (packet==0)
  486. return 1;
  487. int res = OnJoinCloudResult(packet, rakPeer, cloudServer, cloudClient, fullyConnectedMesh2, twoWayAuthentication, connectionGraph2, rakPeerIpOrDomain, myPublicIP);
  488. rakPeer->DeallocatePacket(packet);
  489. return res;
  490. }
粤ICP备19079148号