Network.cpp 42 KB

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