NotificationNetwork.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. // Original file Copyright Crytek GMBH or its affiliates, used under license.
  13. #include "CrySystem_precompiled.h"
  14. #include "NotificationNetwork.h"
  15. #include <ISystem.h>
  16. #include <AzCore/Socket/AzSocket.h>
  17. #include <AzCore/Utils/Utils.h>
  18. #undef LockDebug
  19. //#define LockDebug(str1,str2) {string strMessage;strMessage.Format(str1,str2);if (m_clients.size()) OutputDebugString(strMessage.c_str());}
  20. #define LockDebug(str1, str2)
  21. //
  22. extern bool RCON_IsRemoteAllowedToConnect(const AZ::AzSock::AzSocketAddress& connectee);
  23. using namespace NotificationNetwork;
  24. //
  25. #include <CryPath.h>
  26. class CQueryNotification
  27. : public INotificationNetworkListener
  28. {
  29. // INotificationNetworkListener
  30. public:
  31. virtual void OnNotificationNetworkReceive([[maybe_unused]] const void* pBuffer, [[maybe_unused]] size_t length)
  32. {
  33. INotificationNetwork* pNotificationNetwork =
  34. gEnv->pSystem->GetINotificationNetwork();
  35. if (!pNotificationNetwork)
  36. {
  37. return;
  38. }
  39. const char* path = nullptr; // Don't call GetGameFolder here, it returns a full absolute path and we just really want the game name
  40. AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
  41. if (projectPath.empty())
  42. {
  43. return;
  44. }
  45. pNotificationNetwork->Send("SystemInfo", projectPath.c_str(), projectPath.size());
  46. }
  47. } g_queryNotification;
  48. AZSOCKET CConnectionBase::CreateSocket()
  49. {
  50. AZSOCKET sock = AZ::AzSock::Socket();
  51. if (!AZ::AzSock::IsAzSocketValid(sock))
  52. {
  53. CryLog("CNotificationNetworkClient::Create: Failed to create socket.");
  54. return AZ_SOCKET_INVALID;
  55. }
  56. if (AZ::AzSock::SetSocketOption(sock, AZ::AzSock::AzSocketOption::REUSEADDR, true))
  57. {
  58. AZ::AzSock::CloseSocket(sock);
  59. CryLog("CNotificationNetworkClient::Create: Failed to set SO_REUSEADDR option.");
  60. return AZ_SOCKET_INVALID;
  61. }
  62. #if defined (WIN32) || defined(WIN64) //MS Platforms
  63. if (AZ::AzSock::SetSocketBlockingMode(sock, false))
  64. {
  65. AZ::AzSock::CloseSocket(sock);
  66. CryLog("CNotificationNetworkClient::Connect: Failed to set socket to asynchronous operation.");
  67. return AZ_SOCKET_INVALID;
  68. }
  69. #endif
  70. // TCP_NODELAY required for win32 because of high latency connection otherwise
  71. #if defined(WIN32)
  72. if (AZ::AzSock::EnableTCPNoDelay(sock, true))
  73. {
  74. AZ::AzSock::CloseSocket(sock);
  75. CryLog("CNotificationNetworkClient::Create: Failed to set TCP_NODELAY option.");
  76. return AZ_SOCKET_INVALID;
  77. }
  78. #endif
  79. return sock;
  80. }
  81. bool CConnectionBase::Connect(const char* address, uint16 port)
  82. {
  83. AZ::AzSock::AzSocketAddress socketAddress;
  84. socketAddress.SetAddress(address, port);
  85. int result = AZ::AzSock::Connect(m_socket, socketAddress);
  86. if (AZ::AzSock::SocketErrorOccured(result))
  87. {
  88. AZ::AzSock::AzSockError err = AZ::AzSock::AzSockError(result);
  89. if (err == AZ::AzSock::AzSockError::eASE_EWOULDBLOCK_CONN)
  90. {
  91. return true;
  92. }
  93. if (err == AZ::AzSock::AzSockError::eASE_EISCONN)
  94. {
  95. if (!m_boIsConnected)
  96. {
  97. m_boIsConnected = true;
  98. m_boIsFailedToConnect = false;
  99. OnConnect(true);
  100. }
  101. return true;
  102. }
  103. if (err == AZ::AzSock::AzSockError::eASE_EALREADY)
  104. {
  105. // It will happen, in case of DNS problems, or if the console is not
  106. // reachable or turned off.
  107. //CryLog("CNotificationNetworkClient::Connect: Failed to connect. Reason: already conencted.");
  108. return true;
  109. }
  110. AZ::AzSock::CloseSocket(m_socket);
  111. m_socket = AZ_SOCKET_INVALID;
  112. CryLog("CNotificationNetworkClient::Connect: Failed to connect. Reason: %d ", result);
  113. return false;
  114. }
  115. return true;
  116. }
  117. /*
  118. CChannel
  119. */
  120. bool CChannel::IsNameValid(const char* name)
  121. {
  122. if (!name)
  123. {
  124. return false;
  125. }
  126. if (!*name)
  127. {
  128. return false;
  129. }
  130. if (::strlen(name) > NN_CHANNEL_NAME_LENGTH_MAX)
  131. {
  132. return false;
  133. }
  134. return true;
  135. }
  136. //
  137. CChannel::CChannel()
  138. {
  139. }
  140. CChannel::CChannel(const char* name)
  141. {
  142. if (!name)
  143. {
  144. return;
  145. }
  146. if (!*name)
  147. {
  148. return;
  149. }
  150. size_t length = MIN(::strlen(name), NN_CHANNEL_NAME_LENGTH_MAX);
  151. ::memset(m_name, 0, NN_CHANNEL_NAME_LENGTH_MAX);
  152. ::memcpy(m_name, name, length);
  153. }
  154. CChannel::~CChannel()
  155. {
  156. }
  157. //
  158. void CChannel::WriteToPacketHeader(void* pPacket) const
  159. {
  160. ::memcpy((uint8*)pPacket + NN_PACKET_HEADER_OFFSET_CHANNEL,
  161. m_name, NN_CHANNEL_NAME_LENGTH_MAX);
  162. }
  163. void CChannel::ReadFromPacketHeader(void* pPacket)
  164. {
  165. ::memcpy(m_name, (uint8*)pPacket + NN_PACKET_HEADER_OFFSET_CHANNEL,
  166. NN_CHANNEL_NAME_LENGTH_MAX);
  167. }
  168. //
  169. bool CChannel::operator ==(const CChannel& channel) const
  170. {
  171. return ::strncmp(m_name, channel.m_name, NN_CHANNEL_NAME_LENGTH_MAX) == 0;
  172. }
  173. bool CChannel::operator !=(const CChannel& channel) const
  174. {
  175. return ::strncmp(m_name, channel.m_name, NN_CHANNEL_NAME_LENGTH_MAX) != 0;
  176. }
  177. /*
  178. CListeners
  179. */
  180. CListeners::CListeners()
  181. {
  182. m_pNotificationWrite = &m_notifications[0];
  183. m_pNotificationRead = &m_notifications[1];
  184. }
  185. CListeners::~CListeners()
  186. {
  187. while (!m_pNotificationRead->empty())
  188. {
  189. SBuffer buffer = m_pNotificationRead->front();
  190. m_pNotificationRead->pop();
  191. delete[] buffer.pData;
  192. }
  193. while (!m_pNotificationWrite->empty())
  194. {
  195. SBuffer buffer = m_pNotificationWrite->front();
  196. m_pNotificationWrite->pop();
  197. delete[] buffer.pData;
  198. }
  199. }
  200. //
  201. size_t CListeners::Count(const CChannel& channel)
  202. {
  203. size_t count = 0;
  204. for (size_t i = 0; i < m_listeners.size(); ++i)
  205. {
  206. if (m_listeners[i].second != channel)
  207. {
  208. continue;
  209. }
  210. ++count;
  211. }
  212. return count;
  213. }
  214. CChannel* CListeners::Channel(INotificationNetworkListener* pListener)
  215. {
  216. for (size_t i = 0; i < m_listeners.size(); ++i)
  217. {
  218. if (m_listeners[i].first != pListener)
  219. {
  220. continue;
  221. }
  222. return &m_listeners[i].second;
  223. }
  224. return nullptr;
  225. }
  226. bool CListeners::Bind(const CChannel& channel, INotificationNetworkListener* pListener)
  227. {
  228. for (size_t i = 0; i < m_listeners.size(); ++i)
  229. {
  230. if (m_listeners[i].first == pListener)
  231. {
  232. m_listeners[i].second = channel;
  233. return true;
  234. }
  235. }
  236. m_listeners.push_back(std::pair<INotificationNetworkListener*, CChannel>());
  237. m_listeners.back().first = pListener;
  238. m_listeners.back().second = channel;
  239. return true;
  240. }
  241. bool CListeners::Remove(INotificationNetworkListener* pListener)
  242. {
  243. for (size_t i = 0; i < m_listeners.size(); ++i)
  244. {
  245. if (m_listeners[i].first != pListener)
  246. {
  247. continue;
  248. }
  249. m_listeners[i] = m_listeners.back();
  250. m_listeners.pop_back();
  251. return true;
  252. }
  253. return false;
  254. }
  255. void CListeners::NotificationPush(const SBuffer& buffer)
  256. {
  257. // TODO: Use auto lock.
  258. m_notificationCriticalSection.Lock();
  259. m_pNotificationWrite->push(buffer);
  260. m_notificationCriticalSection.Unlock();
  261. }
  262. void CListeners::NotificationsProcess()
  263. {
  264. m_notificationCriticalSection.Lock();
  265. std::swap(m_pNotificationWrite, m_pNotificationRead);
  266. m_notificationCriticalSection.Unlock();
  267. while (!m_pNotificationRead->empty())
  268. {
  269. SBuffer buffer = m_pNotificationRead->front();
  270. m_pNotificationRead->pop();
  271. for (size_t i = 0; i < m_listeners.size(); ++i)
  272. {
  273. if (m_listeners[i].second != buffer.channel)
  274. {
  275. continue;
  276. }
  277. m_listeners[i].first->OnNotificationNetworkReceive(
  278. buffer.pData, buffer.length);
  279. }
  280. delete[] buffer.pData;
  281. }
  282. }
  283. /*
  284. CConnectionBase
  285. */
  286. CConnectionBase::CConnectionBase(CNotificationNetwork* pNotificationNetwork)
  287. {
  288. m_pNotificationNetwork = pNotificationNetwork;
  289. m_port = 0;
  290. m_socket = AZ_SOCKET_INVALID;
  291. m_buffer.pData = nullptr;
  292. m_buffer.length = 0;
  293. m_dataLeft = 0;
  294. m_boIsConnected = false;
  295. m_boIsFailedToConnect = false;
  296. }
  297. CConnectionBase::~CConnectionBase()
  298. {
  299. if (m_buffer.pData)
  300. {
  301. delete[] m_buffer.pData;
  302. }
  303. if (m_socket != AZ_SOCKET_INVALID)
  304. {
  305. CloseSocket_Internal();
  306. }
  307. }
  308. //
  309. void CConnectionBase::SetAddress(const char* address, uint16 port)
  310. {
  311. size_t length = MIN(::strlen(address), 15);
  312. ::memset(m_address, 0, sizeof(m_address));
  313. ::memcpy(m_address, address, length);
  314. m_port = port;
  315. }
  316. bool CConnectionBase::Validate()
  317. {
  318. if (m_socket != AZ_SOCKET_INVALID)
  319. {
  320. if (!m_port)
  321. {
  322. AZ::AzSock::AzSocketAddress socketAddress;
  323. int result = AZ::AzSock::GetSockName(m_socket, socketAddress);
  324. if (AZ::AzSock::SocketErrorOccured(result))
  325. {
  326. return false;
  327. }
  328. }
  329. return Select_Internal();
  330. }
  331. if (!m_port) // If port is not set we don't want to try to reconnect.
  332. {
  333. return false;
  334. }
  335. m_socket = CreateSocket();
  336. // If the create sockect will fail, it is likely that we will never be able to connect,
  337. // we might want to signal that.
  338. Connect(m_address, m_port);
  339. return false;
  340. }
  341. bool CConnectionBase::Send(const void* pBuffer, size_t length)
  342. {
  343. if (!Validate())
  344. {
  345. return false;
  346. }
  347. size_t sent = 0;
  348. while (sent < length)
  349. {
  350. int r = AZ::AzSock::Send(m_socket, (const char*)pBuffer + sent, length - sent, 0);
  351. if (AZ::AzSock::SocketErrorOccured(r))
  352. {
  353. AZ::AzSock::AzSockError nCurrentError = AZ::AzSock::AzSockError(r);
  354. if (nCurrentError == AZ::AzSock::AzSockError::eASE_ENOTCONN)
  355. {
  356. r = 0;
  357. break;
  358. }
  359. else if (nCurrentError == AZ::AzSock::AzSockError::eASE_EWOULDBLOCK)
  360. {
  361. r = 0;
  362. }
  363. else
  364. {
  365. CryLog("CNotificationNetworkClient::Send: Failed to send package. Reason: %s", AZ::AzSock::GetStringForError(r));
  366. CloseSocket_Internal();
  367. return false;
  368. }
  369. }
  370. sent += r;
  371. }
  372. return true;
  373. }
  374. bool CConnectionBase::SendMessage(EMessage eMessage, const CChannel& channel, uint32 data)
  375. {
  376. char header[NN_PACKET_HEADER_LENGTH];
  377. ::memset(header, 0, NN_PACKET_HEADER_LENGTH);
  378. *(uint32*)&header[NN_PACKET_HEADER_OFFSET_MESSAGE] = AZ::AzSock::HostToNetLong(eMessage);
  379. *(uint32*)&header[NN_PACKET_HEADER_OFFSET_DATA_LENGTH] = AZ::AzSock::HostToNetLong(data);
  380. channel.WriteToPacketHeader(header);
  381. if (!Send(header, NN_PACKET_HEADER_LENGTH))
  382. {
  383. return false;
  384. }
  385. return true;
  386. }
  387. bool CConnectionBase::Select_Internal()
  388. {
  389. if (m_socket == AZ_SOCKET_INVALID)
  390. {
  391. return false;
  392. }
  393. AZFD_SET stExceptions;
  394. AZFD_SET stWriteSockets;
  395. FD_ZERO(&stExceptions);
  396. FD_SET(m_socket, &stExceptions);
  397. FD_ZERO(&stWriteSockets);
  398. FD_SET(m_socket, &stWriteSockets);
  399. AZTIMEVAL timeOut = { 0, 0 };
  400. int r = AZ::AzSock::Select(m_socket, nullptr, &stWriteSockets, &stExceptions, &timeOut);
  401. if (AZ::AzSock::SocketErrorOccured(r))
  402. {
  403. CryLog("CNotificationNetworkClient:: Failed to select socket. Reason: %s", AZ::AzSock::GetStringForError(r));
  404. CloseSocket_Internal();
  405. m_boIsFailedToConnect = true;
  406. return false;
  407. }
  408. else if (!r)
  409. {
  410. return m_boIsConnected;
  411. }
  412. if (FD_ISSET(m_socket, &stExceptions))
  413. {
  414. CloseSocket_Internal();
  415. m_boIsFailedToConnect = true;
  416. OnConnect(m_boIsConnected); // Handles failed attempt to connect.
  417. return false;
  418. }
  419. else if (FD_ISSET(m_socket, &stWriteSockets)) // In Windows a socket can be in both lists.
  420. {
  421. if (!m_boIsConnected)
  422. {
  423. m_boIsConnected = true;
  424. m_boIsFailedToConnect = false;
  425. OnConnect(m_boIsConnected); // Handles successful attempt to connect.
  426. }
  427. return true;
  428. }
  429. return false;
  430. }
  431. void CConnectionBase::CloseSocket_Internal()
  432. {
  433. AZ::AzSock::CloseSocket(m_socket);
  434. m_socket = AZ_SOCKET_INVALID;
  435. if (m_boIsConnected)
  436. {
  437. OnDisconnect();
  438. }
  439. m_boIsConnected = false;
  440. }
  441. bool CConnectionBase::SendNotification(const CChannel& channel, const void* pBuffer, size_t length)
  442. {
  443. if (!SendMessage(eMessage_DataTransfer, channel, length))
  444. {
  445. return false;
  446. }
  447. if (!length)
  448. {
  449. return true;
  450. }
  451. if (!Send(pBuffer, length))
  452. {
  453. return false;
  454. }
  455. return true;
  456. }
  457. bool CConnectionBase::ReceiveMessage(CListeners& listeners)
  458. {
  459. if (!Validate())
  460. {
  461. return false;
  462. }
  463. if (!m_dataLeft)
  464. {
  465. m_dataLeft = NN_PACKET_HEADER_LENGTH;
  466. }
  467. int r = AZ::AzSock::Recv(m_socket, (char*)&m_bufferHeader[NN_PACKET_HEADER_LENGTH - m_dataLeft], m_dataLeft, 0);
  468. if (!r)
  469. {
  470. // Connection terminated.
  471. m_dataLeft = 0;
  472. CloseSocket_Internal();
  473. return false;
  474. }
  475. if (AZ::AzSock::SocketErrorOccured(r))
  476. {
  477. m_dataLeft = 0;
  478. CryLog("CNotificationNetworkClient::ReceiveMessage: Failed to receive package. Reason: %s", AZ::AzSock::GetStringForError(r));
  479. CloseSocket_Internal();
  480. return false;
  481. }
  482. if (m_dataLeft -= r)
  483. {
  484. return true;
  485. }
  486. // The whole message was received, process it...
  487. EMessage eMessage = (EMessage)AZ::AzSock::NetToHostLong(
  488. *(uint32*)&m_bufferHeader[NN_PACKET_HEADER_OFFSET_MESSAGE]);
  489. const CChannel& channel = *(CChannel*)&m_bufferHeader[NN_PACKET_HEADER_OFFSET_CHANNEL];
  490. if (eMessage == eMessage_DataTransfer)
  491. {
  492. m_dataLeft = AZ::AzSock::NetToHostLong(*(uint32*)&m_bufferHeader[NN_PACKET_HEADER_OFFSET_DATA_LENGTH]);
  493. if (!m_dataLeft)
  494. {
  495. SBuffer buffer;
  496. buffer.channel = channel;
  497. buffer.pData = nullptr;
  498. buffer.length = 0;
  499. listeners.NotificationPush(buffer);
  500. return true;
  501. }
  502. m_buffer.pData = new uint8[m_buffer.length = m_dataLeft];
  503. if (!m_buffer.pData)
  504. {
  505. CryLog("CNotificationNetwork::CConnection::Receive: Failed to allocate buffer.\n");
  506. m_dataLeft = 0;
  507. CloseSocket_Internal();
  508. return false;
  509. }
  510. m_buffer.channel.ReadFromPacketHeader(m_bufferHeader);
  511. return +1;
  512. }
  513. if (!OnMessage(eMessage, channel))
  514. {
  515. CryLog("NotificationNetwork::CConnectionBase::ReceiveMessage: "
  516. "Unknown message received, terminating Connection...\n");
  517. m_dataLeft = 0;
  518. CloseSocket_Internal();
  519. return false;
  520. }
  521. return true;
  522. }
  523. bool CConnectionBase::ReceiveNotification(CListeners& listeners)
  524. {
  525. int r = AZ::AzSock::Recv(m_socket, (char*)&m_buffer.pData[m_buffer.length - m_dataLeft], m_dataLeft, 0);
  526. if (!r)
  527. {
  528. CryLog("CNotificationNetworkClient::ReceiveNotification: Failed to receive package. Reason: Connection terminated.");
  529. // Connection terminated.
  530. m_dataLeft = 0;
  531. CloseSocket_Internal();
  532. return false;
  533. }
  534. if (AZ::AzSock::SocketErrorOccured(r))
  535. {
  536. m_dataLeft = 0;
  537. CryLog("CNotificationNetworkClient::ReceiveNotification: Failed to receive package. Reason: %s", AZ::AzSock::GetStringForError(r));
  538. CloseSocket_Internal();
  539. return false;
  540. }
  541. if (m_dataLeft -= r)
  542. {
  543. return true;
  544. }
  545. listeners.NotificationPush(m_buffer);
  546. m_buffer.pData = nullptr;
  547. m_buffer.length = 0;
  548. m_dataLeft = 0;
  549. return true;
  550. }
  551. bool CConnectionBase::Receive(CListeners& listeners)
  552. {
  553. if (m_buffer.pData)
  554. {
  555. return ReceiveNotification(listeners);
  556. }
  557. return ReceiveMessage(listeners);
  558. }
  559. bool CConnectionBase::GetIsConnectedFlag()
  560. {
  561. return Select_Internal() || m_boIsConnected;
  562. }
  563. bool CConnectionBase::GetIsFailedToConnectFlag() const
  564. {
  565. return m_boIsFailedToConnect;
  566. }
  567. /*
  568. CClient
  569. */
  570. CClient* CClient::Create(CNotificationNetwork* pNotificationNetwork, const char* address, uint16 port)
  571. {
  572. CClient* pClient = new CClient(pNotificationNetwork);
  573. AZSOCKET sock = pClient->CreateSocket();
  574. // In the current implementation, this is REALLY UNLIKELY to happen.
  575. if (sock == AZ_SOCKET_INVALID)
  576. {
  577. delete pClient;
  578. return nullptr;
  579. }
  580. //
  581. pClient->SetSocket(sock);
  582. pClient->Connect(address, port);
  583. pClient->SetAddress(address, port);
  584. pClient->SetSocket(sock);
  585. return pClient;
  586. }
  587. CClient* CClient::Create(CNotificationNetwork* pNotificationNetwork)
  588. {
  589. CClient* pClient = new CClient(pNotificationNetwork);
  590. return pClient;
  591. }
  592. //
  593. CClient::CClient(CNotificationNetwork* pNotificationNetwork)
  594. : CConnectionBase(pNotificationNetwork)
  595. {
  596. }
  597. CClient::~CClient()
  598. {
  599. GetNotificationNetwork()->ReleaseClients(this);
  600. }
  601. //
  602. void CClient::Update()
  603. {
  604. m_listeners.NotificationsProcess();
  605. }
  606. // CConnectionBase
  607. bool CClient::OnConnect(bool boConnected)
  608. {
  609. if (boConnected)
  610. {
  611. for (size_t i = 0; i < m_listeners.Count(); ++i)
  612. {
  613. if (!SendMessage(eMessage_ChannelRegister, m_listeners.Channel(i), 0))
  614. {
  615. return false;
  616. }
  617. }
  618. }
  619. CryAutoLock<CryCriticalSection> lock(m_stConnectionCallbacksLock);
  620. for (size_t nCount = 0; nCount < m_cNotificationNetworkConnectionCallbacks.size(); ++nCount)
  621. {
  622. m_cNotificationNetworkConnectionCallbacks[nCount]->OnConnect(this, boConnected);
  623. }
  624. return boConnected;
  625. }
  626. bool CClient::OnDisconnect()
  627. {
  628. CryAutoLock<CryCriticalSection> lock(m_stConnectionCallbacksLock);
  629. for (size_t nCount = 0; nCount < m_cNotificationNetworkConnectionCallbacks.size(); ++nCount)
  630. {
  631. m_cNotificationNetworkConnectionCallbacks[nCount]->OnDisconnected(this);
  632. }
  633. return true;
  634. }
  635. bool CClient::OnMessage([[maybe_unused]] EMessage eMessage, [[maybe_unused]] const CChannel& channel)
  636. {
  637. return false;
  638. }
  639. // INotificationNetworkClient
  640. bool CClient::Connect(const char* address, uint16 port)
  641. {
  642. bool bReturnValue(false);
  643. if (m_socket == AZ_SOCKET_INVALID)
  644. {
  645. m_socket = CreateSocket();
  646. }
  647. bReturnValue = CConnectionBase::Connect(address, port);
  648. if (bReturnValue)
  649. {
  650. SetAddress(address, port);
  651. }
  652. return bReturnValue;
  653. }
  654. bool CClient::ListenerBind(const char* channelName, INotificationNetworkListener* pListener)
  655. {
  656. if (!CChannel::IsNameValid(channelName))
  657. {
  658. return false;
  659. }
  660. if (!m_listeners.Bind(CChannel(channelName), pListener))
  661. {
  662. return false;
  663. }
  664. if (!SendMessage(eMessage_ChannelRegister, CChannel(channelName), 0))
  665. {
  666. return false;
  667. }
  668. return true;
  669. }
  670. bool CClient::ListenerRemove(INotificationNetworkListener* pListener)
  671. {
  672. CChannel* pChannel = m_listeners.Channel(pListener);
  673. if (!pChannel)
  674. {
  675. return false;
  676. }
  677. if (!m_listeners.Remove(pListener))
  678. {
  679. return false;
  680. }
  681. if (!SendMessage(eMessage_ChannelUnregister, *pChannel, 0))
  682. {
  683. return false;
  684. }
  685. return true;
  686. }
  687. bool CClient::Send(const char* channelName, const void* pBuffer, size_t length)
  688. {
  689. CRY_ASSERT(CChannel::IsNameValid(channelName));
  690. // CRY_ASSERT_MESSAGE(channelLength <= NN_CHANNEL_NAME_LENGTH_MAX,
  691. // "Channel name \"%s\" was passed to a Notification Network method, the name cannot be longer than %d chars.",
  692. // channel, NN_CHANNEL_NAME_LENGTH_MAX);
  693. if (!CChannel::IsNameValid(channelName))
  694. {
  695. return false;
  696. }
  697. if (!SendNotification(CChannel(channelName), pBuffer, length))
  698. {
  699. return false;
  700. }
  701. return true;
  702. }
  703. bool CClient::RegisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback)
  704. {
  705. CryAutoLock<CryCriticalSection> lock(m_stConnectionCallbacksLock);
  706. return stl::push_back_unique(m_cNotificationNetworkConnectionCallbacks, pConnectionCallback);
  707. }
  708. bool CClient::UnregisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback)
  709. {
  710. CryAutoLock<CryCriticalSection> lock(m_stConnectionCallbacksLock);
  711. return stl::find_and_erase(m_cNotificationNetworkConnectionCallbacks, pConnectionCallback);
  712. }
  713. /*
  714. CNotificationNetwork::CConnection
  715. */
  716. CNotificationNetwork::CConnection::CConnection(CNotificationNetwork* pNotificationNetwork, AZSOCKET sock)
  717. : CConnectionBase(pNotificationNetwork)
  718. {
  719. SetSocket(sock);
  720. m_listeningChannels.reserve(8);
  721. }
  722. CNotificationNetwork::CConnection::~CConnection()
  723. {
  724. }
  725. //
  726. bool CNotificationNetwork::CConnection::IsListening(const CChannel& channel)
  727. {
  728. for (size_t i = 0; i < m_listeningChannels.size(); ++i)
  729. {
  730. if (m_listeningChannels[i] == channel)
  731. {
  732. return true;
  733. }
  734. }
  735. return false;
  736. }
  737. // CConnectionBase
  738. bool CNotificationNetwork::CConnection::OnMessage(EMessage eMessage, const CChannel& channel)
  739. {
  740. switch (eMessage)
  741. {
  742. case eMessage_ChannelRegister:
  743. for (size_t i = 0; i < m_listeningChannels.size(); ++i)
  744. {
  745. if (m_listeningChannels[i] == channel)
  746. {
  747. return true;
  748. }
  749. }
  750. m_listeningChannels.push_back(channel);
  751. return true;
  752. case eMessage_ChannelUnregister:
  753. for (size_t i = 0; i < m_listeningChannels.size(); ++i)
  754. {
  755. if (m_listeningChannels[i] != channel)
  756. {
  757. continue;
  758. }
  759. m_listeningChannels[i] = m_listeningChannels.back();
  760. m_listeningChannels.pop_back();
  761. return true;
  762. }
  763. return true;
  764. }
  765. return false;
  766. }
  767. /*
  768. CNotificationNetwork::CThread
  769. */
  770. CNotificationNetwork::CThread::CThread()
  771. {
  772. m_pNotificationNetwork = nullptr;
  773. m_bRun = true;
  774. }
  775. CNotificationNetwork::CThread::~CThread()
  776. {
  777. }
  778. //
  779. bool CNotificationNetwork::CThread::Begin(CNotificationNetwork* pNotificationNetwork)
  780. {
  781. m_pNotificationNetwork = pNotificationNetwork;
  782. Start(-1, (char*)NN_THREAD_NAME);
  783. return true;
  784. }
  785. void CNotificationNetwork::CThread::End()
  786. {
  787. m_bRun = false;
  788. // WaitForThread();
  789. // TODO: Should properly close!
  790. }
  791. // CryRunnable
  792. void CNotificationNetwork::CThread::Run()
  793. {
  794. CryThreadSetName(threadID(THREADID_NULL), NN_THREAD_NAME);
  795. while (m_bRun)
  796. {
  797. m_pNotificationNetwork->ProcessSockets();
  798. }
  799. }
  800. /*
  801. CNotificationNetwork
  802. */
  803. CNotificationNetwork* CNotificationNetwork::Create()
  804. {
  805. AZ::AzSock::Startup();
  806. AZSOCKET sock = AZ::AzSock::Socket();
  807. if (!AZ::AzSock::IsAzSocketValid(sock))
  808. {
  809. CryLog("CNotificationNetwork::Create: Failed to create socket.\n");
  810. return nullptr;
  811. }
  812. // Disable nagling of small blocks to fight high latency connection
  813. int result = AZ::AzSock::EnableTCPNoDelay(sock, true);
  814. if (AZ::AzSock::SocketErrorOccured(result))
  815. {
  816. AZ::AzSock::CloseSocket(sock);
  817. CryLog("CNotificationNetworkClient::Create: Failed to set TCP_NODELAY option.");
  818. return nullptr;
  819. }
  820. result = AZ::AzSock::SetSocketBlockingMode(sock, false);
  821. if (AZ::AzSock::SocketErrorOccured(result))
  822. {
  823. AZ::AzSock::CloseSocket(sock);
  824. CryLog("CNotificationNetworkClient::Connect: Failed to set socket to asynchronous operation.");
  825. return nullptr;
  826. }
  827. // Editor uses a different port to avoid conflicts when running both editor and game on same PC
  828. // But allows the lua remote debugger to connect to the editor
  829. unsigned short port = gEnv && gEnv->IsEditor() ? 9433 : 9432;
  830. AZ::AzSock::AzSocketAddress addr;
  831. addr.SetAddrPort(port);
  832. result = AZ::AzSock::Bind(sock, addr);
  833. if (AZ::AzSock::SocketErrorOccured(result))
  834. {
  835. CryLog("CNotificationNetwork::Create: Failed to bind socket.\n");
  836. AZ::AzSock::CloseSocket(sock);
  837. return nullptr;
  838. }
  839. result = AZ::AzSock::Listen(sock, 8);
  840. if (AZ::AzSock::SocketErrorOccured(result))
  841. {
  842. CryLog("CNotificationNetwork::Create: Failed to listen.\n");
  843. AZ::AzSock::CloseSocket(sock);
  844. return nullptr;
  845. }
  846. CNotificationNetwork* pNotificationNetwork = new CNotificationNetwork();
  847. pNotificationNetwork->m_socket = sock;
  848. pNotificationNetwork->m_thread.Begin(pNotificationNetwork);
  849. return pNotificationNetwork;
  850. }
  851. //
  852. CNotificationNetwork::CNotificationNetwork()
  853. {
  854. m_socket = AZ_SOCKET_INVALID;
  855. m_connections.reserve(4);
  856. m_listeners.Bind("Query", &g_queryNotification);
  857. }
  858. CNotificationNetwork::~CNotificationNetwork()
  859. {
  860. m_thread.End();
  861. m_thread.Stop();
  862. m_thread.WaitForThread();
  863. while (!m_connections.empty())
  864. {
  865. delete m_connections.back();
  866. m_connections.pop_back();
  867. }
  868. if (m_socket != AZ_SOCKET_INVALID)
  869. {
  870. AZ::AzSock::CloseSocket(m_socket);
  871. m_socket = AZ_SOCKET_INVALID;
  872. }
  873. AZ::AzSock::Cleanup();
  874. }
  875. //
  876. void CNotificationNetwork::ReleaseClients(CClient* pClient)
  877. {
  878. // TODO: Use CryAutoLock
  879. LockDebug("Lock %s\n", "CNotificationNetwork::ReleaseClients()");
  880. m_clientsCriticalSection.Lock();
  881. for (size_t i = 0; i < m_clients.size(); ++i)
  882. {
  883. if (m_clients[i] != pClient)
  884. {
  885. continue;
  886. }
  887. m_clients[i] = m_clients.back();
  888. m_clients.pop_back();
  889. break;
  890. }
  891. m_clientsCriticalSection.Unlock();
  892. LockDebug("Unlock %s\n", "CNotificationNetwork::ReleaseClients()");
  893. }
  894. void CNotificationNetwork::ProcessSockets()
  895. {
  896. fd_set read;
  897. FD_ZERO(&read);
  898. AZSOCKET socketMax = 0;
  899. if (m_socket != AZ_SOCKET_INVALID)
  900. {
  901. FD_SET(m_socket, &read);
  902. socketMax = m_socket;
  903. }
  904. for (size_t i = 0; i < m_connections.size(); ++i)
  905. {
  906. if (m_connections[i]->Validate())
  907. {
  908. AZSOCKET sock = m_connections[i]->GetSocket();
  909. FD_SET(sock, &read);
  910. if (socketMax < sock)
  911. {
  912. socketMax = sock;
  913. }
  914. continue;
  915. }
  916. // The Connection is invalid, remove it.
  917. CConnection* pConnection = m_connections[i];
  918. m_connections[i] = m_connections.back();
  919. m_connections.pop_back();
  920. delete pConnection;
  921. // Invalidate the loop increment since we just removed a Connection and
  922. // in the process potentially replaced its slot with an unprocessed one.
  923. --i;
  924. CryLog("Notification Network Connection terminated, current total: %d\n",
  925. (int)m_connections.size());
  926. }
  927. LockDebug("Lock %s\n", "CNotificationNetwork::ProcessSockets()");
  928. m_clientsCriticalSection.Lock();
  929. for (size_t i = 0; i < m_clients.size(); ++i)
  930. {
  931. if (!m_clients[i]->Validate())
  932. {
  933. continue;
  934. }
  935. AZSOCKET sock = m_clients[i]->GetSocket();
  936. FD_SET(sock, &read);
  937. if (socketMax < sock)
  938. {
  939. socketMax = sock;
  940. }
  941. }
  942. m_clientsCriticalSection.Unlock();
  943. LockDebug("Unlock %s\n", "CNotificationNetwork::ProcessSockets()");
  944. AZTIMEVAL timeOut = { 1, 0 };
  945. int r = AZ::AzSock::Select(socketMax, &read, nullptr, nullptr, &timeOut);
  946. if (r == 0)
  947. {
  948. return;
  949. }
  950. // When we have no sockets, the select statement will fail and not
  951. // block for even 1 second, as it should...
  952. if (AZ::AzSock::SocketErrorOccured(r))
  953. {
  954. // So we force the sleep here for now.
  955. Sleep(1000);
  956. return;
  957. }
  958. for (size_t i = 0; i < m_connections.size(); ++i)
  959. {
  960. if (!FD_ISSET(m_connections[i]->GetSocket(), &read))
  961. {
  962. continue;
  963. }
  964. m_connections[i]->Receive(m_listeners);
  965. }
  966. LockDebug("Lock 2 %s\n", "CNotificationNetwork::ProcessSockets()");
  967. m_clientsCriticalSection.Lock();
  968. for (size_t i = 0; i < m_clients.size(); ++i)
  969. {
  970. if (!FD_ISSET(m_clients[i]->GetSocket(), &read))
  971. {
  972. continue;
  973. }
  974. m_clients[i]->Receive();
  975. }
  976. m_clientsCriticalSection.Unlock();
  977. LockDebug("Unlock 2 %s\n", "CNotificationNetwork::ProcessSockets()");
  978. if (m_socket == AZ_SOCKET_INVALID)
  979. {
  980. return;
  981. }
  982. if (!FD_ISSET(m_socket, &read))
  983. {
  984. return;
  985. }
  986. AZ::AzSock::AzSocketAddress addr;
  987. AZSOCKET sock = AZ::AzSock::Accept(m_socket, addr);
  988. if (!AZ::AzSock::IsAzSocketValid(sock))
  989. {
  990. return;
  991. }
  992. if (!RCON_IsRemoteAllowedToConnect(addr))
  993. {
  994. AZ::AzSock::CloseSocket(sock);
  995. return;
  996. }
  997. m_connections.push_back(new CConnection(this, sock));
  998. CryLog("Notification Network accepted new Connection, current total: %d\n",
  999. (int)m_connections.size());
  1000. }
  1001. // INotificationNetwork
  1002. INotificationNetworkClient* CNotificationNetwork::CreateClient()
  1003. {
  1004. CClient* pClient = CClient::Create(this);
  1005. LockDebug("Lock %s\n", "CNotificationNetwork::CreateClient()");
  1006. m_clientsCriticalSection.Lock();
  1007. m_clients.push_back(pClient);
  1008. m_clientsCriticalSection.Unlock();
  1009. LockDebug("Unlock %s\n", "CNotificationNetwork::CreateClient()");
  1010. return pClient;
  1011. }
  1012. INotificationNetworkClient* CNotificationNetwork::Connect(const char* address, uint16 port)
  1013. {
  1014. CClient* pClient = CClient::Create(this, address, port);
  1015. if (!pClient)
  1016. {
  1017. return nullptr;
  1018. }
  1019. LockDebug("Lock %s\n", "CNotificationNetwork::Connect()");
  1020. m_clientsCriticalSection.Lock();
  1021. m_clients.push_back(pClient);
  1022. m_clientsCriticalSection.Unlock();
  1023. LockDebug("Unlock %s\n", "CNotificationNetwork::Connect()");
  1024. return pClient;
  1025. }
  1026. size_t CNotificationNetwork::GetConnectionCount(const char* channelName)
  1027. {
  1028. if (!channelName)
  1029. {
  1030. return m_connections.size();
  1031. }
  1032. if (!CChannel::IsNameValid(channelName))
  1033. {
  1034. return 0;
  1035. }
  1036. CChannel channel(channelName);
  1037. size_t count = 0;
  1038. for (size_t i = 0; i < m_connections.size(); ++i)
  1039. {
  1040. if (!m_connections[i]->IsListening(channel))
  1041. {
  1042. continue;
  1043. }
  1044. ++count;
  1045. }
  1046. return count;
  1047. }
  1048. bool CNotificationNetwork::ListenerBind(const char* channelName, INotificationNetworkListener* pListener)
  1049. {
  1050. if (!CChannel::IsNameValid(channelName))
  1051. {
  1052. return false;
  1053. }
  1054. return m_listeners.Bind(CChannel(channelName), pListener);
  1055. }
  1056. bool CNotificationNetwork::ListenerRemove(INotificationNetworkListener* pListener)
  1057. {
  1058. return m_listeners.Remove(pListener);
  1059. }
  1060. void CNotificationNetwork::Update()
  1061. {
  1062. m_listeners.NotificationsProcess();
  1063. LockDebug("Lock %s\n", "CNotificationNetwork::Update()");
  1064. m_clientsCriticalSection.Lock();
  1065. for (size_t i = 0; i < m_clients.size(); ++i)
  1066. {
  1067. m_clients[i]->Update();
  1068. }
  1069. m_clientsCriticalSection.Unlock();
  1070. LockDebug("Unlock %s\n", "CNotificationNetwork::Update()");
  1071. }
  1072. uint32 CNotificationNetwork::Send(const char* channelName, const void* pBuffer, size_t length)
  1073. {
  1074. if (!CChannel::IsNameValid(channelName))
  1075. {
  1076. return 0;
  1077. }
  1078. CChannel channel(channelName);
  1079. // TODO: There should be a mutex lock here to ensure thread safety.
  1080. uint32 count = 0;
  1081. for (size_t i = 0; i < m_connections.size(); ++i)
  1082. {
  1083. if (!m_connections[i]->IsListening(channel))
  1084. {
  1085. continue;
  1086. }
  1087. if (m_connections[i]->SendNotification(channel, pBuffer, length))
  1088. {
  1089. ++count;
  1090. }
  1091. }
  1092. return count;
  1093. }