Network.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/Context.h"
  24. #include "../Core/CoreEvents.h"
  25. #include "../Core/Profiler.h"
  26. #include "../Engine/EngineEvents.h"
  27. #include "../IO/FileSystem.h"
  28. #include "../Input/InputEvents.h"
  29. #include "../IO/IOEvents.h"
  30. #include "../IO/Log.h"
  31. #include "../IO/MemoryBuffer.h"
  32. #include "../Network/HttpRequest.h"
  33. #include "../Network/Network.h"
  34. #include "../Network/NetworkEvents.h"
  35. #include "../Network/NetworkPriority.h"
  36. #include "../Network/Protocol.h"
  37. #include "../Scene/Scene.h"
  38. #ifdef URHO3D_WEBSOCKETS
  39. #include "WS/WSServer.h"
  40. #include "WS/WSClient.h"
  41. #include "WS/WSConnection.h"
  42. #include "WS/WSPacket.h"
  43. #endif
  44. #ifndef __EMSCRIPTEN__
  45. #include <SLikeNet/MessageIdentifiers.h>
  46. #include <SLikeNet/NatPunchthroughClient.h>
  47. #include <SLikeNet/peerinterface.h>
  48. #include <SLikeNet/statistics.h>
  49. #endif
  50. #ifdef SendMessage
  51. #undef SendMessage
  52. #endif
  53. #ifndef URHO3D_WEBSOCKETS
  54. #define WEBSOCKETS_NOT_ENABLED() URHO3D_LOGERROR("Engine built without websocket support")
  55. #endif
  56. #include "../DebugNew.h"
  57. namespace Urho3D
  58. {
  59. #ifndef __EMSCRIPTEN__
  60. static const char* RAKNET_MESSAGEID_STRINGS[] = {
  61. "ID_CONNECTED_PING",
  62. "ID_UNCONNECTED_PING",
  63. "ID_UNCONNECTED_PING_OPEN_CONNECTIONS",
  64. "ID_CONNECTED_PONG",
  65. "ID_DETECT_LOST_CONNECTIONS",
  66. "ID_OPEN_CONNECTION_REQUEST_1",
  67. "ID_OPEN_CONNECTION_REPLY_1",
  68. "ID_OPEN_CONNECTION_REQUEST_2",
  69. "ID_OPEN_CONNECTION_REPLY_2",
  70. "ID_CONNECTION_REQUEST",
  71. "ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY",
  72. "ID_OUR_SYSTEM_REQUIRES_SECURITY",
  73. "ID_PUBLIC_KEY_MISMATCH",
  74. "ID_OUT_OF_BAND_INTERNAL",
  75. "ID_SND_RECEIPT_ACKED",
  76. "ID_SND_RECEIPT_LOSS",
  77. "ID_CONNECTION_REQUEST_ACCEPTED",
  78. "ID_CONNECTION_ATTEMPT_FAILED",
  79. "ID_ALREADY_CONNECTED",
  80. "ID_NEW_INCOMING_CONNECTION",
  81. "ID_NO_FREE_INCOMING_CONNECTIONS",
  82. "ID_DISCONNECTION_NOTIFICATION",
  83. "ID_CONNECTION_LOST",
  84. "ID_CONNECTION_BANNED",
  85. "ID_INVALID_PASSWORD",
  86. "ID_INCOMPATIBLE_PROTOCOL_VERSION",
  87. "ID_IP_RECENTLY_CONNECTED",
  88. "ID_TIMESTAMP",
  89. "ID_UNCONNECTED_PONG",
  90. "ID_ADVERTISE_SYSTEM",
  91. "ID_DOWNLOAD_PROGRESS",
  92. "ID_REMOTE_DISCONNECTION_NOTIFICATION",
  93. "ID_REMOTE_CONNECTION_LOST",
  94. "ID_REMOTE_NEW_INCOMING_CONNECTION",
  95. "ID_FILE_LIST_TRANSFER_HEADER",
  96. "ID_FILE_LIST_TRANSFER_FILE",
  97. "ID_FILE_LIST_REFERENCE_PUSH_ACK",
  98. "ID_DDT_DOWNLOAD_REQUEST",
  99. "ID_TRANSPORT_STRING",
  100. "ID_REPLICA_MANAGER_CONSTRUCTION",
  101. "ID_REPLICA_MANAGER_SCOPE_CHANGE",
  102. "ID_REPLICA_MANAGER_SERIALIZE",
  103. "ID_REPLICA_MANAGER_DOWNLOAD_STARTED",
  104. "ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE",
  105. "ID_RAKVOICE_OPEN_CHANNEL_REQUEST",
  106. "ID_RAKVOICE_OPEN_CHANNEL_REPLY",
  107. "ID_RAKVOICE_CLOSE_CHANNEL",
  108. "ID_RAKVOICE_DATA",
  109. "ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE",
  110. "ID_AUTOPATCHER_CREATION_LIST",
  111. "ID_AUTOPATCHER_DELETION_LIST",
  112. "ID_AUTOPATCHER_GET_PATCH",
  113. "ID_AUTOPATCHER_PATCH_LIST",
  114. "ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR",
  115. "ID_AUTOPATCHER_CANNOT_DOWNLOAD_ORIGINAL_UNMODIFIED_FILES",
  116. "ID_AUTOPATCHER_FINISHED_INTERNAL",
  117. "ID_AUTOPATCHER_FINISHED",
  118. "ID_AUTOPATCHER_RESTART_APPLICATION",
  119. "ID_NAT_PUNCHTHROUGH_REQUEST",
  120. "ID_NAT_CONNECT_AT_TIME",
  121. "ID_NAT_GET_MOST_RECENT_PORT",
  122. "ID_NAT_CLIENT_READY",
  123. "ID_NAT_TARGET_NOT_CONNECTED",
  124. "ID_NAT_TARGET_UNRESPONSIVE",
  125. "ID_NAT_CONNECTION_TO_TARGET_LOST",
  126. "ID_NAT_ALREADY_IN_PROGRESS",
  127. "ID_NAT_PUNCHTHROUGH_FAILED",
  128. "ID_NAT_PUNCHTHROUGH_SUCCEEDED",
  129. "ID_READY_EVENT_SET",
  130. "ID_READY_EVENT_UNSET",
  131. "ID_READY_EVENT_ALL_SET",
  132. "ID_READY_EVENT_QUERY",
  133. "ID_LOBBY_GENERAL",
  134. "ID_RPC_REMOTE_ERROR",
  135. "ID_RPC_PLUGIN",
  136. "ID_FILE_LIST_REFERENCE_PUSH",
  137. "ID_READY_EVENT_FORCE_ALL_SET",
  138. "ID_ROOMS_EXECUTE_FUNC",
  139. "ID_ROOMS_LOGON_STATUS",
  140. "ID_ROOMS_HANDLE_CHANGE",
  141. "ID_LOBBY2_SEND_MESSAGE",
  142. "ID_LOBBY2_SERVER_ERROR",
  143. "ID_FCM2_NEW_HOST",
  144. "ID_FCM2_REQUEST_FCMGUID",
  145. "ID_FCM2_RESPOND_CONNECTION_COUNT",
  146. "ID_FCM2_INFORM_FCMGUID",
  147. "ID_FCM2_UPDATE_MIN_TOTAL_CONNECTION_COUNT",
  148. "ID_FCM2_VERIFIED_JOIN_START",
  149. "ID_FCM2_VERIFIED_JOIN_CAPABLE",
  150. "ID_FCM2_VERIFIED_JOIN_FAILED",
  151. "ID_FCM2_VERIFIED_JOIN_ACCEPTED",
  152. "ID_FCM2_VERIFIED_JOIN_REJECTED",
  153. "ID_UDP_PROXY_GENERAL",
  154. "ID_SQLite3_EXEC",
  155. "ID_SQLite3_UNKNOWN_DB",
  156. "ID_SQLLITE_LOGGER",
  157. "ID_NAT_TYPE_DETECTION_REQUEST",
  158. "ID_NAT_TYPE_DETECTION_RESULT",
  159. "ID_ROUTER_2_INTERNAL",
  160. "ID_ROUTER_2_FORWARDING_NO_PATH",
  161. "ID_ROUTER_2_FORWARDING_ESTABLISHED",
  162. "ID_ROUTER_2_REROUTED",
  163. "ID_TEAM_BALANCER_INTERNAL",
  164. "ID_TEAM_BALANCER_REQUESTED_TEAM_FULL",
  165. "ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED",
  166. "ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED",
  167. "ID_TEAM_BALANCER_TEAM_ASSIGNED",
  168. "ID_LIGHTSPEED_INTEGRATION",
  169. "ID_XBOX_LOBBY",
  170. "ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_SUCCESS",
  171. "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS",
  172. "ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_FAILURE",
  173. "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE",
  174. "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT",
  175. "ID_TWO_WAY_AUTHENTICATION_NEGOTIATION",
  176. "ID_CLOUD_POST_REQUEST",
  177. "ID_CLOUD_RELEASE_REQUEST",
  178. "ID_CLOUD_GET_REQUEST",
  179. "ID_CLOUD_GET_RESPONSE",
  180. "ID_CLOUD_UNSUBSCRIBE_REQUEST",
  181. "ID_CLOUD_SERVER_TO_SERVER_COMMAND",
  182. "ID_CLOUD_SUBSCRIPTION_NOTIFICATION",
  183. "ID_LIB_VOICE",
  184. "ID_RELAY_PLUGIN",
  185. "ID_NAT_REQUEST_BOUND_ADDRESSES",
  186. "ID_NAT_RESPOND_BOUND_ADDRESSES",
  187. "ID_FCM2_UPDATE_USER_CONTEXT",
  188. "ID_RESERVED_3",
  189. "ID_RESERVED_4",
  190. "ID_RESERVED_5",
  191. "ID_RESERVED_6",
  192. "ID_RESERVED_7",
  193. "ID_RESERVED_8",
  194. "ID_RESERVED_9",
  195. "ID_USER_PACKET_ENUM"
  196. };
  197. #endif
  198. static const int DEFAULT_UPDATE_FPS = 30;
  199. static const int SERVER_TIMEOUT_TIME = 10000;
  200. Network::Network(Context* context) :
  201. Object(context),
  202. updateFps_(DEFAULT_UPDATE_FPS),
  203. simulatedLatency_(0),
  204. simulatedPacketLoss_(0.0f),
  205. updateInterval_(1.0f / (float)DEFAULT_UPDATE_FPS),
  206. updateAcc_(0.0f),
  207. isServer_(false),
  208. scene_(nullptr),
  209. natPunchServerAddress_(nullptr),
  210. remoteGUID_(nullptr)
  211. {
  212. wsClient_ = nullptr;
  213. wsServer_ = nullptr;
  214. #ifndef __EMSCRIPTEN__
  215. rakPeer_ = SLNet::RakPeerInterface::GetInstance();
  216. rakPeerClient_ = SLNet::RakPeerInterface::GetInstance();
  217. rakPeer_->SetTimeoutTime(SERVER_TIMEOUT_TIME, SLNet::UNASSIGNED_SYSTEM_ADDRESS);
  218. #endif
  219. SetPassword("");
  220. SetDiscoveryBeacon(VariantMap());
  221. #ifndef __EMSCRIPTEN__
  222. natPunchthroughClient_ = new SLNet::NatPunchthroughClient;
  223. natPunchthroughServerClient_ = new SLNet::NatPunchthroughClient;
  224. SetNATServerInfo("127.0.0.1", 61111);
  225. #endif
  226. // Register Network library object factories
  227. RegisterNetworkLibrary(context_);
  228. SubscribeToEvent(E_BEGINFRAME, URHO3D_HANDLER(Network, HandleBeginFrame));
  229. SubscribeToEvent(E_RENDERUPDATE, URHO3D_HANDLER(Network, HandleRenderUpdate));
  230. // Blacklist remote events which are not to be allowed to be registered in any case
  231. blacklistedRemoteEvents_.Insert(E_CONSOLECOMMAND);
  232. blacklistedRemoteEvents_.Insert(E_LOGMESSAGE);
  233. blacklistedRemoteEvents_.Insert(E_BEGINFRAME);
  234. blacklistedRemoteEvents_.Insert(E_UPDATE);
  235. blacklistedRemoteEvents_.Insert(E_POSTUPDATE);
  236. blacklistedRemoteEvents_.Insert(E_RENDERUPDATE);
  237. blacklistedRemoteEvents_.Insert(E_ENDFRAME);
  238. blacklistedRemoteEvents_.Insert(E_MOUSEBUTTONDOWN);
  239. blacklistedRemoteEvents_.Insert(E_MOUSEBUTTONUP);
  240. blacklistedRemoteEvents_.Insert(E_MOUSEMOVE);
  241. blacklistedRemoteEvents_.Insert(E_MOUSEWHEEL);
  242. blacklistedRemoteEvents_.Insert(E_KEYDOWN);
  243. blacklistedRemoteEvents_.Insert(E_KEYUP);
  244. blacklistedRemoteEvents_.Insert(E_TEXTINPUT);
  245. blacklistedRemoteEvents_.Insert(E_JOYSTICKCONNECTED);
  246. blacklistedRemoteEvents_.Insert(E_JOYSTICKDISCONNECTED);
  247. blacklistedRemoteEvents_.Insert(E_JOYSTICKBUTTONDOWN);
  248. blacklistedRemoteEvents_.Insert(E_JOYSTICKBUTTONUP);
  249. blacklistedRemoteEvents_.Insert(E_JOYSTICKAXISMOVE);
  250. blacklistedRemoteEvents_.Insert(E_JOYSTICKHATMOVE);
  251. blacklistedRemoteEvents_.Insert(E_TOUCHBEGIN);
  252. blacklistedRemoteEvents_.Insert(E_TOUCHEND);
  253. blacklistedRemoteEvents_.Insert(E_TOUCHMOVE);
  254. blacklistedRemoteEvents_.Insert(E_GESTURERECORDED);
  255. blacklistedRemoteEvents_.Insert(E_GESTUREINPUT);
  256. blacklistedRemoteEvents_.Insert(E_MULTIGESTURE);
  257. blacklistedRemoteEvents_.Insert(E_DROPFILE);
  258. blacklistedRemoteEvents_.Insert(E_INPUTFOCUS);
  259. blacklistedRemoteEvents_.Insert(E_MOUSEVISIBLECHANGED);
  260. blacklistedRemoteEvents_.Insert(E_EXITREQUESTED);
  261. blacklistedRemoteEvents_.Insert(E_SERVERCONNECTED);
  262. blacklistedRemoteEvents_.Insert(E_SERVERDISCONNECTED);
  263. blacklistedRemoteEvents_.Insert(E_CONNECTFAILED);
  264. blacklistedRemoteEvents_.Insert(E_CLIENTCONNECTED);
  265. blacklistedRemoteEvents_.Insert(E_CLIENTDISCONNECTED);
  266. blacklistedRemoteEvents_.Insert(E_CLIENTIDENTITY);
  267. blacklistedRemoteEvents_.Insert(E_CLIENTSCENELOADED);
  268. blacklistedRemoteEvents_.Insert(E_NETWORKMESSAGE);
  269. blacklistedRemoteEvents_.Insert(E_NETWORKUPDATE);
  270. blacklistedRemoteEvents_.Insert(E_NETWORKUPDATESENT);
  271. blacklistedRemoteEvents_.Insert(E_NETWORKSCENELOADFAILED);
  272. }
  273. Network::~Network()
  274. {
  275. #ifndef __EMSCRIPTEN__
  276. rakPeer_->DetachPlugin(natPunchthroughServerClient_);
  277. rakPeerClient_->DetachPlugin(natPunchthroughClient_);
  278. #endif
  279. // If server connection exists, disconnect, but do not send an event because we are shutting down
  280. Disconnect(100);
  281. serverConnection_.Reset();
  282. #ifndef __EMSCRIPTEN__
  283. clientConnections_.Clear();
  284. #endif
  285. delete natPunchthroughServerClient_;
  286. natPunchthroughServerClient_ = nullptr;
  287. delete natPunchthroughClient_;
  288. natPunchthroughClient_ = nullptr;
  289. delete remoteGUID_;
  290. remoteGUID_ = nullptr;
  291. delete natPunchServerAddress_;
  292. natPunchServerAddress_ = nullptr;
  293. #ifndef __EMSCRIPTEN__
  294. SLNet::RakPeerInterface::DestroyInstance(rakPeer_);
  295. SLNet::RakPeerInterface::DestroyInstance(rakPeerClient_);
  296. #endif
  297. rakPeer_ = nullptr;
  298. rakPeerClient_ = nullptr;
  299. }
  300. #ifndef __EMSCRIPTEN__
  301. void Network::HandleMessage(const SLNet::AddressOrGUID& source, int packetID, int msgID, const char* data, size_t numBytes)
  302. {
  303. // Only process messages from known sources
  304. Connection* connection = GetConnection(source);
  305. if (connection)
  306. {
  307. MemoryBuffer msg(data, (unsigned)numBytes);
  308. if (connection->ProcessMessage((int)msgID, msg))
  309. return;
  310. }
  311. else
  312. URHO3D_LOGWARNING("Discarding message from unknown MessageConnection " + String(source.ToString()));
  313. }
  314. #endif
  315. void Network::NewConnectionEstablished(const SharedPtr<Connection> newConnection)
  316. {
  317. using namespace ClientConnected;
  318. VariantMap& eventData = GetEventDataMap();
  319. eventData[P_CONNECTION] = newConnection;
  320. newConnection->SendEvent(E_CLIENTCONNECTED, eventData);
  321. }
  322. #ifndef __EMSCRIPTEN__
  323. void Network::NewConnectionEstablished(const SLNet::AddressOrGUID& connection)
  324. {
  325. // Create a new client connection corresponding to this MessageConnection
  326. SharedPtr<Connection> newConnection(new Connection(context_, true, connection, rakPeer_));
  327. newConnection->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
  328. clientConnections_[connection] = newConnection;
  329. URHO3D_LOGINFO("Client " + newConnection->ToString() + " connected");
  330. NewConnectionEstablished(clientConnections_[connection]);
  331. }
  332. #endif
  333. void Network::NewConnectionEstablished(const WSConnection& ws)
  334. {
  335. #ifdef URHO3D_WEBSOCKETS
  336. // Create a new client connection corresponding to this MessageConnection
  337. SharedPtr<Connection> newConnection(new Connection(context_, true, ws, wsServer_));
  338. newConnection->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
  339. websocketClientConnections_[WSConnection(ws)] = newConnection;
  340. URHO3D_LOGINFO("Client " + newConnection->ToString() + " connected");
  341. NewConnectionEstablished(websocketClientConnections_[WSConnection(ws)]);
  342. #else
  343. WEBSOCKETS_NOT_ENABLED();
  344. #endif
  345. }
  346. void Network::ClientDisconnected(const WSConnection& ws)
  347. {
  348. #ifdef URHO3D_WEBSOCKETS
  349. // Remove the client connection that corresponds to this MessageConnection
  350. HashMap<WSConnection, SharedPtr<Connection> >::Iterator i = websocketClientConnections_.Find(ws);
  351. if (i != websocketClientConnections_.End())
  352. {
  353. Connection* connection = i->second_;
  354. URHO3D_LOGINFO("Client " + connection->ToString() + " disconnected");
  355. using namespace ClientDisconnected;
  356. VariantMap& eventData = GetEventDataMap();
  357. eventData[P_CONNECTION] = connection;
  358. connection->SendEvent(E_CLIENTDISCONNECTED, eventData);
  359. websocketClientConnections_.Erase(i);
  360. }
  361. #endif
  362. }
  363. #ifndef __EMSCRIPTEN__
  364. void Network::ClientDisconnected(const SLNet::AddressOrGUID& connection)
  365. {
  366. // Remove the client connection that corresponds to this MessageConnection
  367. HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Find(connection);
  368. if (i != clientConnections_.End())
  369. {
  370. Connection* connection = i->second_;
  371. URHO3D_LOGINFO("Client " + connection->ToString() + " disconnected");
  372. using namespace ClientDisconnected;
  373. VariantMap& eventData = GetEventDataMap();
  374. eventData[P_CONNECTION] = connection;
  375. connection->SendEvent(E_CLIENTDISCONNECTED, eventData);
  376. clientConnections_.Erase(i);
  377. }
  378. }
  379. #endif
  380. void Network::SetDiscoveryBeacon(const VariantMap& data)
  381. {
  382. #ifndef __EMSCRIPTEN__
  383. VectorBuffer buffer;
  384. buffer.WriteVariantMap(data);
  385. if (buffer.GetSize() > 400)
  386. URHO3D_LOGERROR("Discovery beacon of size: " + String(buffer.GetSize()) + " bytes is too large, modify MAX_OFFLINE_DATA_LENGTH in RakNet or reduce size");
  387. rakPeer_->SetOfflinePingResponse((const char*)buffer.GetData(), buffer.GetSize());
  388. #endif
  389. }
  390. void Network::DiscoverHosts(unsigned port)
  391. {
  392. #ifndef __EMSCRIPTEN__
  393. // JSandusky: Contrary to the manual, we actually do have to perform Startup first before we can Ping
  394. if (!rakPeerClient_->IsActive())
  395. {
  396. SLNet::SocketDescriptor socket;
  397. // Startup local connection with max 1 incoming connection(first param) and 1 socket description (third param)
  398. rakPeerClient_->Startup(1, &socket, 1);
  399. }
  400. rakPeerClient_->Ping("255.255.255.255", port, false);
  401. #endif
  402. }
  403. void Network::SetPassword(const String& password)
  404. {
  405. #ifndef __EMSCRIPTEN__
  406. rakPeer_->SetIncomingPassword(password.CString(), password.Length());
  407. #endif
  408. password_ = password;
  409. }
  410. bool Network::Connect(const String& address, unsigned short port, Scene* scene, const VariantMap& identity)
  411. {
  412. #ifndef __EMSCRIPTEN__
  413. URHO3D_PROFILE(Connect);
  414. if (!rakPeerClient_->IsActive())
  415. {
  416. URHO3D_LOGINFO("Initializing client connection...");
  417. SLNet::SocketDescriptor socket;
  418. // Startup local connection with max 2 incoming connections(first param) and 1 socket description (third param)
  419. rakPeerClient_->Startup(2, &socket, 1);
  420. }
  421. //isServer_ = false;
  422. SLNet::ConnectionAttemptResult connectResult = rakPeerClient_->Connect(address.CString(), port, password_.CString(), password_.Length());
  423. if (connectResult == SLNet::CONNECTION_ATTEMPT_STARTED)
  424. {
  425. serverConnection_ = new Connection(context_, false, rakPeerClient_->GetMyBoundAddress(), rakPeerClient_);
  426. serverConnection_->SetScene(scene);
  427. serverConnection_->SetIdentity(identity);
  428. serverConnection_->SetConnectPending(true);
  429. serverConnection_->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
  430. URHO3D_LOGINFO("Connecting to server " + address + ":" + String(port) + ", Client: " + serverConnection_->ToString());
  431. return true;
  432. }
  433. else if (connectResult == SLNet::ALREADY_CONNECTED_TO_ENDPOINT) {
  434. URHO3D_LOGWARNING("Already connected to server!");
  435. SendEvent(E_CONNECTIONINPROGRESS);
  436. return false;
  437. }
  438. else if (connectResult == SLNet::CONNECTION_ATTEMPT_ALREADY_IN_PROGRESS) {
  439. URHO3D_LOGWARNING("Connection attempt already in progress!");
  440. SendEvent(E_CONNECTIONINPROGRESS);
  441. return false;
  442. }
  443. else
  444. {
  445. URHO3D_LOGERROR("Failed to connect to server " + address + ":" + String(port) + ", error code: " + String((int)connectResult));
  446. SendEvent(E_CONNECTFAILED);
  447. return false;
  448. }
  449. #endif
  450. return false;
  451. }
  452. bool Network::ConnectWS(const String& address, unsigned short port, Scene* scene, const VariantMap& identity)
  453. {
  454. #ifdef URHO3D_WEBSOCKETS
  455. URHO3D_PROFILE(ConnectWS);
  456. wsClient_ = new WSClient(context_);
  457. int result = wsClient_->Connect(address, port);
  458. serverConnection_ = new Connection(context_, false, nullptr, wsClient_);
  459. serverConnection_->SetScene(scene);
  460. serverConnection_->SetIdentity(identity);
  461. serverConnection_->SetConnectPending(true);
  462. serverConnection_->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
  463. return result == 0;
  464. #else
  465. WEBSOCKETS_NOT_ENABLED();
  466. return false;
  467. #endif
  468. }
  469. void Network::Disconnect(int waitMSec)
  470. {
  471. if (!serverConnection_)
  472. return;
  473. URHO3D_PROFILE(Disconnect);
  474. serverConnection_->Disconnect(waitMSec);
  475. }
  476. bool Network::StartServer(unsigned short port, unsigned int maxConnections)
  477. {
  478. #ifndef __EMSCRIPTEN__
  479. if (IsUDPServerRunning())
  480. return true;
  481. URHO3D_PROFILE(StartServer);
  482. SLNet::SocketDescriptor socket;//(port, AF_INET);
  483. socket.port = port;
  484. socket.socketFamily = AF_INET;
  485. // Startup local connection with max 128 incoming connection(first param) and 1 socket description (third param)
  486. SLNet::StartupResult startResult = rakPeer_->Startup(maxConnections, &socket, 1);
  487. if (startResult == SLNet::RAKNET_STARTED)
  488. {
  489. URHO3D_LOGINFO("Started server on port " + String(port));
  490. rakPeer_->SetMaximumIncomingConnections(maxConnections);
  491. isServer_ = true;
  492. rakPeer_->SetOccasionalPing(true);
  493. rakPeer_->SetUnreliableTimeout(1000);
  494. //rakPeer_->SetIncomingPassword("Parole", (int)strlen("Parole"));
  495. return true;
  496. }
  497. else
  498. {
  499. URHO3D_LOGINFO("Failed to start server on port " + String(port) + ", error code: " + String((int)startResult));
  500. return false;
  501. }
  502. #else
  503. return false;
  504. #endif
  505. }
  506. bool Network::StartWSServer(unsigned short port, unsigned int maxConnections)
  507. {
  508. if (IsWSServerRunning())
  509. return true;
  510. URHO3D_PROFILE(StartWSServer);
  511. #if defined(URHO3D_WEBSOCKETS) && !defined(__EMSCRIPTEN__)
  512. wsServer_ = new WSServer(context_);
  513. int result = wsServer_->StartServer(port, maxConnections);
  514. if (result != 0) {
  515. delete wsServer_;
  516. wsServer_ = nullptr;
  517. return false;
  518. }
  519. return true;
  520. #else
  521. return false;
  522. #endif
  523. }
  524. void Network::StopServer()
  525. {
  526. #ifndef __EMSCRIPTEN__
  527. clientConnections_.Clear();
  528. URHO3D_PROFILE(StopServer);
  529. StopUDPServer();
  530. StopWSServer();
  531. #endif
  532. }
  533. void Network::StopUDPServer()
  534. {
  535. #ifndef __EMSCRIPTEN__
  536. clientConnections_.Clear();
  537. URHO3D_PROFILE(StopUDPServer);
  538. if (IsUDPServerRunning())
  539. {
  540. if (!rakPeer_)
  541. return;
  542. // Provide 300 ms to notify
  543. rakPeer_->Shutdown(300);
  544. URHO3D_LOGINFO("Stopped UDP server");
  545. }
  546. #endif
  547. }
  548. void Network::StopWSServer()
  549. {
  550. #ifndef __EMSCRIPTEN__
  551. clientConnections_.Clear();
  552. URHO3D_PROFILE(StopWSServer);
  553. #if defined(URHO3D_WEBSOCKETS) && !defined(__EMSCRIPTEN__)
  554. if (IsWSServerRunning())
  555. {
  556. wsServer_->StopServer();
  557. delete wsServer_;
  558. wsServer_ = nullptr;
  559. URHO3D_LOGINFO("Stopped Websockets server");
  560. }
  561. #endif
  562. #endif
  563. }
  564. void Network::SetNATServerInfo(const String& address, unsigned short port)
  565. {
  566. #ifndef __EMSCRIPTEN__
  567. if (!natPunchServerAddress_)
  568. natPunchServerAddress_ = new SLNet::SystemAddress;
  569. natPunchServerAddress_->FromStringExplicitPort(address.CString(), port);
  570. #endif
  571. }
  572. void Network::StartNATClient()
  573. {
  574. #ifndef __EMSCRIPTEN__
  575. if (!rakPeer_) {
  576. URHO3D_LOGERROR("Unable to start NAT client, client not initialized!");
  577. return;
  578. }
  579. if (natPunchServerAddress_->GetPort() == 0) {
  580. URHO3D_LOGERROR("NAT master server address incorrect!");
  581. return;
  582. }
  583. rakPeer_->AttachPlugin(natPunchthroughServerClient_);
  584. guid_ = String(rakPeer_->GetGuidFromSystemAddress(SLNet::UNASSIGNED_SYSTEM_ADDRESS).ToString());
  585. URHO3D_LOGINFO("GUID: " + guid_);
  586. rakPeer_->Connect(natPunchServerAddress_->ToString(false), natPunchServerAddress_->GetPort(), nullptr, 0);
  587. #endif
  588. }
  589. void Network::AttemptNATPunchtrough(const String& guid, Scene* scene, const VariantMap& identity)
  590. {
  591. #ifndef __EMSCRIPTEN__
  592. scene_ = scene;
  593. identity_ = identity;
  594. if (!remoteGUID_)
  595. remoteGUID_ = new SLNet::RakNetGUID;
  596. remoteGUID_->FromString(guid.CString());
  597. rakPeerClient_->AttachPlugin(natPunchthroughClient_);
  598. if (rakPeerClient_->IsActive()) {
  599. natPunchthroughClient_->OpenNAT(*remoteGUID_, *natPunchServerAddress_);
  600. }
  601. else {
  602. SLNet::SocketDescriptor socket;
  603. // Startup local connection with max 2 incoming connections(first param) and 1 socket description (third param)
  604. rakPeerClient_->Startup(2, &socket, 1);
  605. }
  606. rakPeerClient_->Connect(natPunchServerAddress_->ToString(false), natPunchServerAddress_->GetPort(), nullptr, 0);
  607. #endif
  608. }
  609. void Network::BroadcastMessage(int msgID, bool reliable, bool inOrder, const VectorBuffer& msg, unsigned contentID)
  610. {
  611. BroadcastMessage(msgID, reliable, inOrder, msg.GetData(), msg.GetSize(), contentID);
  612. }
  613. void Network::BroadcastMessage(int msgID, bool reliable, bool inOrder, const unsigned char* data, unsigned numBytes,
  614. unsigned contentID)
  615. {
  616. #ifndef __EMSCRIPTEN__
  617. if (!rakPeer_)
  618. return;
  619. VectorBuffer msgData;
  620. msgData.WriteUByte((unsigned char)ID_USER_PACKET_ENUM);
  621. msgData.WriteUInt((unsigned int)msgID);
  622. msgData.Write(data, numBytes);
  623. if (isServer_)
  624. rakPeer_->Send((const char*)msgData.GetData(), (int)msgData.GetSize(), HIGH_PRIORITY, RELIABLE, (char)0, SLNet::UNASSIGNED_RAKNET_GUID, true);
  625. else
  626. URHO3D_LOGERROR("Server not running, can not broadcast messages");
  627. #endif
  628. #if defined(URHO3D_WEBSOCKETS) && !defined(__EMSCRIPTEN__)
  629. if (wsServer_) {
  630. VectorBuffer msgData;
  631. msgData.WriteUByte((unsigned char)URHO3D_MESSAGE);
  632. msgData.WriteUInt((unsigned int)msgID);
  633. msgData.Write(data, numBytes);
  634. for (HashMap<WSConnection, SharedPtr<Connection> >::ConstIterator i = websocketClientConnections_.Begin();
  635. i != websocketClientConnections_.End(); ++i)
  636. {
  637. wsServer_->AddOutgoingPacket(WSPacket(i->second_->GetWS(), msgData));
  638. }
  639. }
  640. #endif
  641. }
  642. void Network::BroadcastRemoteEvent(StringHash eventType, bool inOrder, const VariantMap& eventData)
  643. {
  644. #ifndef __EMSCRIPTEN__
  645. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Begin(); i != clientConnections_.End(); ++i)
  646. i->second_->SendRemoteEvent(eventType, inOrder, eventData);
  647. #endif
  648. #ifdef URHO3D_WEBSOCKETS
  649. for (HashMap<WSConnection, SharedPtr<Connection> >::ConstIterator i = websocketClientConnections_.Begin();
  650. i != websocketClientConnections_.End(); ++i)
  651. i->second_->SendRemoteEvent(eventType, inOrder, eventData);
  652. #endif
  653. }
  654. void Network::BroadcastRemoteEvent(Scene* scene, StringHash eventType, bool inOrder, const VariantMap& eventData)
  655. {
  656. #ifndef __EMSCRIPTEN__
  657. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Begin();
  658. i != clientConnections_.End(); ++i)
  659. {
  660. if (i->second_->GetScene() == scene)
  661. i->second_->SendRemoteEvent(eventType, inOrder, eventData);
  662. }
  663. #endif
  664. #ifdef URHO3D_WEBSOCKETS
  665. for (HashMap<WSConnection, SharedPtr<Connection> >::ConstIterator i = websocketClientConnections_.Begin();
  666. i != websocketClientConnections_.End(); ++i)
  667. i->second_->SendRemoteEvent(eventType, inOrder, eventData);
  668. #endif
  669. }
  670. void Network::BroadcastRemoteEvent(Node* node, StringHash eventType, bool inOrder, const VariantMap& eventData)
  671. {
  672. if (!node)
  673. {
  674. URHO3D_LOGERROR("Null sender node for remote node event");
  675. return;
  676. }
  677. if (!node->IsReplicated())
  678. {
  679. URHO3D_LOGERROR("Sender node has a local ID, can not send remote node event");
  680. return;
  681. }
  682. Scene* scene = node->GetScene();
  683. #ifndef __EMSCRIPTEN__
  684. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Begin();
  685. i != clientConnections_.End(); ++i)
  686. {
  687. if (i->second_->GetScene() == scene)
  688. i->second_->SendRemoteEvent(node, eventType, inOrder, eventData);
  689. }
  690. #endif
  691. #ifdef URHO3D_WEBSOCKETS
  692. for (HashMap<WSConnection, SharedPtr<Connection> >::ConstIterator i = websocketClientConnections_.Begin();
  693. i != websocketClientConnections_.End(); ++i)
  694. if (i->second_->GetScene() == scene)
  695. i->second_->SendRemoteEvent(node, eventType, inOrder, eventData);
  696. #endif
  697. }
  698. void Network::SetUpdateFps(int fps)
  699. {
  700. updateFps_ = Max(fps, 1);
  701. updateInterval_ = 1.0f / (float)updateFps_;
  702. updateAcc_ = 0.0f;
  703. }
  704. void Network::SetSimulatedLatency(int ms)
  705. {
  706. simulatedLatency_ = Max(ms, 0);
  707. ConfigureNetworkSimulator();
  708. }
  709. void Network::SetSimulatedPacketLoss(float probability)
  710. {
  711. simulatedPacketLoss_ = Clamp(probability, 0.0f, 1.0f);
  712. ConfigureNetworkSimulator();
  713. }
  714. void Network::RegisterRemoteEvent(StringHash eventType)
  715. {
  716. if (blacklistedRemoteEvents_.Find(eventType) != blacklistedRemoteEvents_.End())
  717. {
  718. URHO3D_LOGERROR("Attempted to register blacklisted remote event type " + String(eventType));
  719. return;
  720. }
  721. allowedRemoteEvents_.Insert(eventType);
  722. }
  723. void Network::UnregisterRemoteEvent(StringHash eventType)
  724. {
  725. allowedRemoteEvents_.Erase(eventType);
  726. }
  727. void Network::UnregisterAllRemoteEvents()
  728. {
  729. allowedRemoteEvents_.Clear();
  730. }
  731. void Network::SetPackageCacheDir(const String& path)
  732. {
  733. packageCacheDir_ = AddTrailingSlash(path);
  734. }
  735. void Network::SendPackageToClients(Scene* scene, PackageFile* package)
  736. {
  737. if (!scene)
  738. {
  739. URHO3D_LOGERROR("Null scene specified for SendPackageToClients");
  740. return;
  741. }
  742. if (!package)
  743. {
  744. URHO3D_LOGERROR("Null package specified for SendPackageToClients");
  745. return;
  746. }
  747. #ifndef __EMSCRIPTEN__
  748. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Begin();
  749. i != clientConnections_.End(); ++i)
  750. {
  751. if (i->second_->GetScene() == scene)
  752. i->second_->SendPackageToClient(package);
  753. }
  754. #endif
  755. for (HashMap<WSConnection, SharedPtr<Connection> >::Iterator i = websocketClientConnections_.Begin();
  756. i != websocketClientConnections_.End(); ++i)
  757. {
  758. if (i->second_->GetScene() == scene)
  759. i->second_->SendPackageToClient(package);
  760. }
  761. }
  762. SharedPtr<HttpRequest> Network::MakeHttpRequest(const String& url, const String& verb, const Vector<String>& headers,
  763. const String& postData)
  764. {
  765. URHO3D_PROFILE(MakeHttpRequest);
  766. // The initialization of the request will take time, can not know at this point if it has an error or not
  767. SharedPtr<HttpRequest> request(new HttpRequest(url, verb, headers, postData));
  768. return request;
  769. }
  770. void Network::BanAddress(const String& address)
  771. {
  772. #ifndef __EMSCRIPTEN__
  773. rakPeer_->AddToBanList(address.CString(), 0);
  774. #endif
  775. }
  776. #ifndef __EMSCRIPTEN__
  777. Connection* Network::GetConnection(const SLNet::AddressOrGUID& connection) const
  778. {
  779. if (serverConnection_ && serverConnection_->GetAddressOrGUID() == connection)
  780. return serverConnection_;
  781. else
  782. {
  783. HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::ConstIterator i = clientConnections_.Find(connection);
  784. if (i != clientConnections_.End())
  785. return i->second_;
  786. else
  787. return nullptr;
  788. }
  789. }
  790. #endif
  791. Connection* Network::GetConnection(const WSConnection& ws) const
  792. {
  793. #ifdef URHO3D_WEBSOCKETS
  794. if (serverConnection_ && serverConnection_->GetWSHandler() == wsClient_)
  795. return serverConnection_;
  796. else
  797. {
  798. HashMap<WSConnection, SharedPtr<Connection> >::ConstIterator i = websocketClientConnections_.Find(WSConnection(ws));
  799. if (i != websocketClientConnections_.End())
  800. return i->second_;
  801. else
  802. return nullptr;
  803. }
  804. #else
  805. WEBSOCKETS_NOT_ENABLED();
  806. return nullptr;
  807. #endif
  808. }
  809. Connection* Network::GetServerConnection() const
  810. {
  811. return serverConnection_;
  812. }
  813. Vector<SharedPtr<Connection> > Network::GetClientConnections() const
  814. {
  815. Vector<SharedPtr<Connection> > ret;
  816. #ifndef __EMSCRIPTEN__
  817. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::ConstIterator i = clientConnections_.Begin();
  818. i != clientConnections_.End(); ++i)
  819. ret.Push(i->second_);
  820. #endif
  821. #ifdef URHO3D_WEBSOCKETS
  822. for (HashMap<WSConnection, SharedPtr<Connection> >::ConstIterator i = websocketClientConnections_.Begin();
  823. i != websocketClientConnections_.End(); ++i)
  824. ret.Push(i->second_);
  825. #endif
  826. return ret;
  827. }
  828. bool Network::IsServerRunning() const
  829. {
  830. return IsWSServerRunning() || IsUDPServerRunning();
  831. }
  832. bool Network::IsUDPServerRunning() const
  833. {
  834. #ifndef __EMSCRIPTEN__
  835. if (!rakPeer_)
  836. return false;
  837. return rakPeer_->IsActive() && isServer_;
  838. #else
  839. return false;
  840. #endif
  841. }
  842. bool Network::IsWSServerRunning() const
  843. {
  844. if (wsServer_)
  845. return true;
  846. return false;
  847. }
  848. bool Network::CheckRemoteEvent(StringHash eventType) const
  849. {
  850. return allowedRemoteEvents_.Contains(eventType);
  851. }
  852. void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
  853. {
  854. #ifndef __EMSCRIPTEN__
  855. unsigned char packetID = packet->data[0];
  856. bool packetHandled = false;
  857. // Deal with timestamped backents
  858. unsigned dataStart = sizeof(char);
  859. if (packetID == ID_TIMESTAMP)
  860. {
  861. dataStart += sizeof(SLNet::Time);
  862. packetID = packet->data[dataStart];
  863. dataStart += sizeof(char);
  864. }
  865. if (packetID == ID_NEW_INCOMING_CONNECTION)
  866. {
  867. if (isServer)
  868. {
  869. NewConnectionEstablished(packet->systemAddress);
  870. packetHandled = true;
  871. }
  872. }
  873. else if (packetID == ID_ALREADY_CONNECTED)
  874. {
  875. if (natPunchServerAddress_ && packet->systemAddress == *natPunchServerAddress_) {
  876. URHO3D_LOGINFO("Already connected to NAT server! ");
  877. if (!isServer)
  878. {
  879. natPunchthroughClient_->OpenNAT(*remoteGUID_, *natPunchServerAddress_);
  880. }
  881. }
  882. packetHandled = true;
  883. }
  884. else if (packetID == ID_CONNECTION_REQUEST_ACCEPTED) // We're a client, our connection as been accepted
  885. {
  886. if(natPunchServerAddress_ && packet->systemAddress == *natPunchServerAddress_) {
  887. URHO3D_LOGINFO("Succesfully connected to NAT punchtrough server! ");
  888. SendEvent(E_NATMASTERCONNECTIONSUCCEEDED);
  889. if (!isServer)
  890. {
  891. natPunchthroughClient_->OpenNAT(*remoteGUID_, *natPunchServerAddress_);
  892. }
  893. } else {
  894. if (!isServer)
  895. {
  896. OnServerConnected(packet->systemAddress);
  897. }
  898. }
  899. packetHandled = true;
  900. }
  901. else if (packetID == ID_NAT_TARGET_NOT_CONNECTED)
  902. {
  903. URHO3D_LOGERROR("Target server not connected to NAT master server!");
  904. packetHandled = true;
  905. }
  906. else if (packetID == ID_CONNECTION_LOST) // We've lost connectivity with the packet source
  907. {
  908. if (isServer)
  909. {
  910. ClientDisconnected(packet->systemAddress);
  911. }
  912. else
  913. {
  914. OnServerDisconnected(packet->systemAddress);
  915. }
  916. packetHandled = true;
  917. }
  918. else if (packetID == ID_DISCONNECTION_NOTIFICATION) // We've lost connection with the other side
  919. {
  920. if (isServer)
  921. {
  922. ClientDisconnected(packet->systemAddress);
  923. }
  924. else
  925. {
  926. OnServerDisconnected(packet->systemAddress);
  927. }
  928. packetHandled = true;
  929. }
  930. else if (packetID == ID_CONNECTION_ATTEMPT_FAILED) // We've failed to connect to the server/peer
  931. {
  932. if (natPunchServerAddress_ && packet->systemAddress == *natPunchServerAddress_) {
  933. URHO3D_LOGERROR("Connection to NAT punchtrough server failed!");
  934. SendEvent(E_NATMASTERCONNECTIONFAILED);
  935. } else {
  936. if (!isServer)
  937. {
  938. OnServerDisconnected(packet->systemAddress);
  939. }
  940. }
  941. packetHandled = true;
  942. }
  943. else if (packetID == ID_NAT_PUNCHTHROUGH_SUCCEEDED)
  944. {
  945. SLNet::SystemAddress remotePeer = packet->systemAddress;
  946. URHO3D_LOGINFO("NAT punchtrough succeeded! Remote peer: " + String(remotePeer.ToString()));
  947. if (!isServer)
  948. {
  949. using namespace NetworkNatPunchtroughSucceeded;
  950. VariantMap eventMap;
  951. eventMap[P_ADDRESS] = remotePeer.ToString(false);
  952. eventMap[P_PORT] = remotePeer.GetPort();
  953. SendEvent(E_NETWORKNATPUNCHTROUGHSUCCEEDED, eventMap);
  954. URHO3D_LOGINFO("Connecting to server behind NAT: " + String(remotePeer.ToString()));
  955. Connect(String(remotePeer.ToString(false)), remotePeer.GetPort(), scene_, identity_);
  956. }
  957. packetHandled = true;
  958. }
  959. else if (packetID == ID_NAT_PUNCHTHROUGH_FAILED)
  960. {
  961. URHO3D_LOGERROR("NAT punchtrough failed!");
  962. SLNet::SystemAddress remotePeer = packet->systemAddress;
  963. using namespace NetworkNatPunchtroughFailed;
  964. VariantMap eventMap;
  965. eventMap[P_ADDRESS] = remotePeer.ToString(false);
  966. eventMap[P_PORT] = remotePeer.GetPort();
  967. SendEvent(E_NETWORKNATPUNCHTROUGHFAILED, eventMap);
  968. packetHandled = true;
  969. }
  970. else if (packetID == ID_CONNECTION_BANNED) // We're a client and we're on the ban list
  971. {
  972. URHO3D_LOGERROR("Connection failed, you're banned!");
  973. SendEvent(E_NETWORKBANNED);
  974. packetHandled = true;
  975. }
  976. else if (packetID == ID_INVALID_PASSWORD) // We're a client, and we gave an invalid password
  977. {
  978. URHO3D_LOGERROR("Invalid password provided for connection!");
  979. SendEvent(E_NETWORKINVALIDPASSWORD);
  980. packetHandled = true;
  981. }
  982. else if (packetID == ID_DOWNLOAD_PROGRESS) // Part of a file transfer
  983. {
  984. //URHO3D_LOGINFO("101010");
  985. }
  986. else if (packetID == ID_UNCONNECTED_PING)
  987. {
  988. packetHandled = true;
  989. }
  990. else if (packetID == ID_UNCONNECTED_PONG) // Host discovery response
  991. {
  992. if (!isServer)
  993. {
  994. using namespace NetworkHostDiscovered;
  995. dataStart += sizeof(SLNet::TimeMS);
  996. VariantMap& eventMap = context_->GetEventDataMap();
  997. if (packet->length > packet->length - dataStart) {
  998. VectorBuffer buffer(packet->data + dataStart, packet->length - dataStart);
  999. VariantMap srcData = buffer.ReadVariantMap();
  1000. eventMap[P_BEACON] = srcData;
  1001. }
  1002. else {
  1003. eventMap[P_BEACON] = VariantMap();
  1004. }
  1005. eventMap[P_ADDRESS] = String(packet->systemAddress.ToString(false));
  1006. eventMap[P_PORT] = (int)packet->systemAddress.GetPort();
  1007. SendEvent(E_NETWORKHOSTDISCOVERED, eventMap);
  1008. }
  1009. packetHandled = true;
  1010. }
  1011. // Urho3D messages
  1012. if (packetID >= ID_USER_PACKET_ENUM)
  1013. {
  1014. unsigned int messageID = *(unsigned int*)(packet->data + dataStart);
  1015. dataStart += sizeof(unsigned int);
  1016. if (isServer)
  1017. {
  1018. HandleMessage(packet->systemAddress, 0, messageID, (const char*)(packet->data + dataStart), packet->length - dataStart);
  1019. }
  1020. else
  1021. {
  1022. MemoryBuffer buffer(packet->data + dataStart, packet->length - dataStart);
  1023. bool processed = serverConnection_ && serverConnection_->ProcessMessage(messageID, buffer);
  1024. if (!processed)
  1025. {
  1026. HandleMessage(packet->systemAddress, 0, messageID, (const char*)(packet->data + dataStart), packet->length - dataStart);
  1027. }
  1028. }
  1029. packetHandled = true;
  1030. }
  1031. if (!packetHandled && packetID < sizeof(RAKNET_MESSAGEID_STRINGS))
  1032. URHO3D_LOGERROR("Unhandled network packet: " + String(RAKNET_MESSAGEID_STRINGS[packetID]));
  1033. else if (!packetHandled)
  1034. URHO3D_LOGERRORF("Unhandled network packet: %i", packetID);
  1035. #endif
  1036. }
  1037. void Network::HandleIncomingPacket(const WSPacket* packet, bool isServer)
  1038. {
  1039. auto buffer = packet->second_;
  1040. // SLikeNet reserved byte must be ignored
  1041. int id = buffer.ReadUByte();
  1042. int messageID = buffer.ReadUInt();
  1043. int padding = sizeof(char) + sizeof(int);
  1044. if (buffer.GetBuffer().Size() < padding) {
  1045. URHO3D_LOGERRORF("Invalid packet received with length %d", buffer.GetBuffer().Size());
  1046. return;
  1047. }
  1048. MemoryBuffer msg(buffer.GetData() + padding, buffer.GetSize() - padding);
  1049. // Only process messages from known sources
  1050. Connection * connection = GetConnection(packet->first_);
  1051. if (isServer) {
  1052. if (connection) {
  1053. if (connection->ProcessMessage((int) messageID, msg)) {
  1054. return;
  1055. } else {
  1056. URHO3D_LOGERRORF("Unable to process incoming message as server %d", messageID);
  1057. }
  1058. }
  1059. } else {
  1060. bool processed = serverConnection_ && serverConnection_->ProcessMessage(messageID, msg);
  1061. if (!processed)
  1062. {
  1063. if (connection) {
  1064. if (connection->ProcessMessage((int) messageID, msg)) {
  1065. return;
  1066. } else {
  1067. URHO3D_LOGERRORF("Unable to process incoming message as client %d", messageID);
  1068. }
  1069. }
  1070. }
  1071. }
  1072. }
  1073. void Network::Update(float timeStep)
  1074. {
  1075. URHO3D_PROFILE(UpdateNetwork);
  1076. #if defined(URHO3D_WEBSOCKETS) && !defined(__EMSCRIPTEN__)
  1077. if (wsServer_) {
  1078. wsServer_->Update(timeStep);
  1079. }
  1080. #endif
  1081. #if defined(URHO3D_WEBSOCKETS)
  1082. if (wsClient_) {
  1083. wsClient_->Update(timeStep);
  1084. }
  1085. #endif
  1086. #ifndef __EMSCRIPTEN__
  1087. //Process all incoming messages for the server
  1088. if (rakPeer_->IsActive())
  1089. {
  1090. while (SLNet::Packet* packet = rakPeer_->Receive())
  1091. {
  1092. HandleIncomingPacket(packet, true);
  1093. rakPeer_->DeallocatePacket(packet);
  1094. }
  1095. }
  1096. // Process all incoming messages for the client
  1097. if (rakPeerClient_->IsActive())
  1098. {
  1099. while (SLNet::Packet* packet = rakPeerClient_->Receive())
  1100. {
  1101. HandleIncomingPacket(packet, false);
  1102. rakPeerClient_->DeallocatePacket(packet);
  1103. }
  1104. }
  1105. #endif
  1106. }
  1107. void Network::PostUpdate(float timeStep)
  1108. {
  1109. URHO3D_PROFILE(PostUpdateNetwork);
  1110. // Check if periodic update should happen now
  1111. updateAcc_ += timeStep;
  1112. bool updateNow = updateAcc_ >= updateInterval_;
  1113. if (updateNow)
  1114. {
  1115. // Notify of the impending update to allow for example updated client controls to be set
  1116. SendEvent(E_NETWORKUPDATE);
  1117. updateAcc_ = fmodf(updateAcc_, updateInterval_);
  1118. if (IsServerRunning())
  1119. {
  1120. // Collect and prepare all networked scenes
  1121. {
  1122. URHO3D_PROFILE(PrepareServerUpdate);
  1123. networkScenes_.Clear();
  1124. #ifndef __EMSCRIPTEN__
  1125. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Begin();
  1126. i != clientConnections_.End(); ++i)
  1127. {
  1128. Scene* scene = i->second_->GetScene();
  1129. if (scene)
  1130. networkScenes_.Insert(scene);
  1131. }
  1132. #endif
  1133. #ifdef URHO3D_WEBSOCKETS
  1134. for (HashMap<WSConnection, SharedPtr<Connection> >::Iterator i = websocketClientConnections_.Begin();
  1135. i != websocketClientConnections_.End(); ++i)
  1136. {
  1137. Scene* scene = i->second_->GetScene();
  1138. if (scene)
  1139. networkScenes_.Insert(scene);
  1140. }
  1141. #endif
  1142. for (HashSet<Scene*>::ConstIterator i = networkScenes_.Begin(); i != networkScenes_.End(); ++i)
  1143. (*i)->PrepareNetworkUpdate();
  1144. }
  1145. {
  1146. URHO3D_PROFILE(SendServerUpdate);
  1147. #ifndef __EMSCRIPTEN__
  1148. // Then send server updates for each UDP client connection
  1149. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Begin();
  1150. i != clientConnections_.End(); ++i)
  1151. {
  1152. i->second_->SendServerUpdate();
  1153. i->second_->SendRemoteEvents();
  1154. i->second_->SendPackages();
  1155. i->second_->SendAllBuffers();
  1156. }
  1157. #endif
  1158. #ifdef URHO3D_WEBSOCKETS
  1159. // Then send server updates for each Websocket client connection
  1160. for (HashMap<WSConnection, SharedPtr<Connection> >::Iterator i = websocketClientConnections_.Begin();
  1161. i != websocketClientConnections_.End(); ++i)
  1162. {
  1163. i->second_->SendServerUpdate();
  1164. i->second_->SendRemoteEvents();
  1165. i->second_->SendPackages();
  1166. i->second_->SendAllBuffers();
  1167. }
  1168. #endif
  1169. }
  1170. }
  1171. if (serverConnection_)
  1172. {
  1173. // Send the client update
  1174. serverConnection_->SendClientUpdate();
  1175. serverConnection_->SendRemoteEvents();
  1176. serverConnection_->SendAllBuffers();
  1177. }
  1178. // Notify that the update was sent
  1179. SendEvent(E_NETWORKUPDATESENT);
  1180. }
  1181. }
  1182. void Network::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
  1183. {
  1184. using namespace BeginFrame;
  1185. Update(eventData[P_TIMESTEP].GetFloat());
  1186. }
  1187. void Network::HandleRenderUpdate(StringHash eventType, VariantMap& eventData)
  1188. {
  1189. using namespace RenderUpdate;
  1190. PostUpdate(eventData[P_TIMESTEP].GetFloat());
  1191. }
  1192. #ifndef __EMSCRIPTEN__
  1193. void Network::OnServerConnected(const SLNet::AddressOrGUID& address)
  1194. {
  1195. serverConnection_->SetConnectPending(false);
  1196. serverConnection_->SetAddressOrGUID(address);
  1197. URHO3D_LOGINFO("Connected to server!");
  1198. // Send the identity map now
  1199. VectorBuffer msg;
  1200. msg.WriteVariantMap(serverConnection_->GetIdentity());
  1201. serverConnection_->SendMessage(MSG_IDENTITY, true, true, msg);
  1202. SendEvent(E_SERVERCONNECTED);
  1203. }
  1204. #endif
  1205. void Network::OnServerConnected(const WSConnection& ws)
  1206. {
  1207. #ifdef URHO3D_WEBSOCKETS
  1208. serverConnection_->SetWS(ws);
  1209. serverConnection_->SetConnectPending(false);
  1210. URHO3D_LOGINFO("Connected to server!");
  1211. // Send the identity map now
  1212. VectorBuffer msg;
  1213. msg.WriteVariantMap(serverConnection_->GetIdentity());
  1214. serverConnection_->SendMessage(MSG_IDENTITY, true, true, msg);
  1215. SendEvent(E_SERVERCONNECTED);
  1216. #endif
  1217. }
  1218. #ifndef __EMSCRIPTEN__
  1219. void Network::OnServerDisconnected(const SLNet::AddressOrGUID& address)
  1220. {
  1221. if (natPunchServerAddress_ && *natPunchServerAddress_ == address.systemAddress) {
  1222. SendEvent(E_NATMASTERDISCONNECTED);
  1223. return;
  1224. }
  1225. // Differentiate between failed connection, and disconnection
  1226. bool failedConnect = serverConnection_ && serverConnection_->IsConnectPending();
  1227. serverConnection_.Reset();
  1228. if (!failedConnect)
  1229. {
  1230. URHO3D_LOGINFO("Disconnected from server");
  1231. SendEvent(E_SERVERDISCONNECTED);
  1232. }
  1233. else
  1234. {
  1235. URHO3D_LOGERROR("Failed to connect to server");
  1236. SendEvent(E_CONNECTFAILED);
  1237. }
  1238. }
  1239. #endif
  1240. void Network::OnServerDisconnected(const WSConnection& ws, bool failedConnect)
  1241. {
  1242. #ifdef URHO3D_WEBSOCKETS
  1243. serverConnection_.Reset();
  1244. if (wsClient_)
  1245. {
  1246. delete wsClient_;
  1247. wsClient_ = nullptr;
  1248. }
  1249. if (!failedConnect)
  1250. {
  1251. URHO3D_LOGINFO("Disconnected from server");
  1252. SendEvent(E_SERVERDISCONNECTED);
  1253. }
  1254. else
  1255. {
  1256. URHO3D_LOGERROR("Failed to connect to server");
  1257. SendEvent(E_CONNECTFAILED);
  1258. }
  1259. #endif
  1260. }
  1261. void Network::ConfigureNetworkSimulator()
  1262. {
  1263. if (serverConnection_)
  1264. serverConnection_->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
  1265. #ifndef __EMSCRIPTEN__
  1266. for (HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::Iterator i = clientConnections_.Begin();
  1267. i != clientConnections_.End(); ++i)
  1268. i->second_->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
  1269. #endif
  1270. }
  1271. void RegisterNetworkLibrary(Context* context)
  1272. {
  1273. NetworkPriority::RegisterObject(context);
  1274. }
  1275. }