Network.cpp 34 KB

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