Network.cpp 36 KB

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