UdpTransportTests.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzNetworking/UdpTransport/UdpNetworkInterface.h>
  9. #include <AzNetworking/UdpTransport/UdpPacketTracker.h>
  10. #include <AzNetworking/UdpTransport/UdpPacketIdWindow.h>
  11. #include <AzNetworking/ConnectionLayer/IConnectionListener.h>
  12. #include <AzNetworking/Framework/NetworkingSystemComponent.h>
  13. #include <AzNetworking/AutoGen/CorePackets.AutoPackets.h>
  14. #include <AzCore/Interface/Interface.h>
  15. #include <AzCore/Console/LoggerSystemComponent.h>
  16. #include <AzCore/Time/TimeSystem.h>
  17. #include <AzCore/Name/NameDictionary.h>
  18. #include <AzCore/UnitTest/TestTypes.h>
  19. namespace UnitTest
  20. {
  21. using namespace AzNetworking;
  22. class TestUdpConnectionListener
  23. : public IConnectionListener
  24. {
  25. public:
  26. ConnectResult ValidateConnect([[maybe_unused]] const IpAddress& remoteAddress, [[maybe_unused]] const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) override
  27. {
  28. return ConnectResult::Accepted;
  29. }
  30. void OnConnect([[maybe_unused]] IConnection* connection) override
  31. {
  32. ;
  33. }
  34. PacketDispatchResult OnPacketReceived([[maybe_unused]] IConnection* connection, const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) override
  35. {
  36. EXPECT_TRUE((packetHeader.GetPacketType() == static_cast<PacketType>(CorePackets::PacketType::InitiateConnectionPacket))
  37. || (packetHeader.GetPacketType() == static_cast<PacketType>(CorePackets::PacketType::HeartbeatPacket)));
  38. return PacketDispatchResult::Failure;
  39. }
  40. void OnPacketLost([[maybe_unused]] IConnection* connection, [[maybe_unused]] PacketId packetId) override
  41. {
  42. }
  43. void OnDisconnect([[maybe_unused]] IConnection* connection, [[maybe_unused]] DisconnectReason reason, [[maybe_unused]] TerminationEndpoint endpoint) override
  44. {
  45. // This should fail given we should be in a disconnecting state
  46. EXPECT_FALSE(connection->Disconnect(reason, endpoint));
  47. }
  48. };
  49. class TestUdpClient
  50. {
  51. public:
  52. TestUdpClient()
  53. {
  54. AZStd::string name = AZStd::string::format("UdpClient%d", ++s_numClients);
  55. m_name = name;
  56. m_clientNetworkInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(m_name, ProtocolType::Udp, TrustZone::ExternalClientToServer, m_connectionListener);
  57. m_clientNetworkInterface->Connect(IpAddress(127, 0, 0, 1, 12345));
  58. }
  59. ~TestUdpClient()
  60. {
  61. AZ::Interface<INetworking>::Get()->DestroyNetworkInterface(m_name);
  62. }
  63. AZ::Name m_name;
  64. TestUdpConnectionListener m_connectionListener;
  65. INetworkInterface* m_clientNetworkInterface;
  66. static inline int32_t s_numClients = 0;
  67. };
  68. class TestUdpServer
  69. {
  70. public:
  71. TestUdpServer()
  72. {
  73. m_serverNetworkInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(m_name, ProtocolType::Udp, TrustZone::ExternalClientToServer, m_connectionListener);
  74. m_serverNetworkInterface->Listen(12345);
  75. }
  76. ~TestUdpServer()
  77. {
  78. AZ::Interface<INetworking>::Get()->DestroyNetworkInterface(m_name);
  79. }
  80. AZ::Name m_name = AZ::Name(AZStd::string_view("UdpServer"));
  81. TestUdpConnectionListener m_connectionListener;
  82. INetworkInterface* m_serverNetworkInterface;
  83. };
  84. class UdpTransportTests
  85. : public LeakDetectionFixture
  86. {
  87. public:
  88. void SetUp() override
  89. {
  90. AZ::NameDictionary::Create();
  91. m_loggerComponent = AZStd::make_unique<AZ::LoggerSystemComponent>();
  92. m_timeSystem = AZStd::make_unique<AZ::TimeSystem>();
  93. m_networkingSystemComponent = AZStd::make_unique<AzNetworking::NetworkingSystemComponent>();
  94. }
  95. void TearDown() override
  96. {
  97. m_networkingSystemComponent.reset();
  98. m_timeSystem.reset();
  99. m_loggerComponent.reset();
  100. AZ::NameDictionary::Destroy();
  101. }
  102. AZStd::unique_ptr<AZ::LoggerSystemComponent> m_loggerComponent;
  103. AZStd::unique_ptr<AZ::TimeSystem> m_timeSystem;
  104. AZStd::unique_ptr<AzNetworking::NetworkingSystemComponent> m_networkingSystemComponent;
  105. };
  106. TEST_F(UdpTransportTests, PacketIdWrap)
  107. {
  108. const uint32_t SEQUENCE_BOUNDARY = 0xFFFF;
  109. UdpPacketTracker tracker;
  110. for (uint32_t i = 0; i < SEQUENCE_BOUNDARY; ++i)
  111. {
  112. tracker.GetNextPacketId();
  113. }
  114. EXPECT_EQ(tracker.GetNextPacketId(), PacketId(SEQUENCE_BOUNDARY + 1));
  115. }
  116. TEST_F(UdpTransportTests, AckReplication)
  117. {
  118. static const SequenceId TestReliableSequenceId = InvalidSequenceId;
  119. static const PacketType TestPacketId = PacketType{ 0 };
  120. UdpPacketTracker send;
  121. UdpPacketTracker recv;
  122. for (uint32_t i = 0; i < 128; i++)
  123. {
  124. UdpPacketHeader sendHeader1(send, TestPacketId, TestReliableSequenceId);
  125. UdpPacketHeader sendHeader2(send, TestPacketId, TestReliableSequenceId);
  126. UdpPacketHeader sendHeader3(send, TestPacketId, TestReliableSequenceId);
  127. UdpPacketHeader sendHeader4(send, TestPacketId, TestReliableSequenceId);
  128. UdpPacketHeader sendHeader5(send, TestPacketId, TestReliableSequenceId);
  129. UdpPacketHeader sendHeader6(send, TestPacketId, TestReliableSequenceId);
  130. UdpPacketHeader sendHeader7(send, TestPacketId, TestReliableSequenceId);
  131. UdpPacketHeader sendHeader8(send, TestPacketId, TestReliableSequenceId);
  132. UdpPacketHeader recvHeader1(recv, TestPacketId, TestReliableSequenceId);
  133. UdpPacketHeader recvHeader2(recv, TestPacketId, TestReliableSequenceId);
  134. UdpPacketHeader recvHeader3(recv, TestPacketId, TestReliableSequenceId);
  135. UdpPacketHeader recvHeader4(recv, TestPacketId, TestReliableSequenceId);
  136. UdpPacketHeader recvHeader5(recv, TestPacketId, TestReliableSequenceId);
  137. UdpPacketHeader recvHeader6(recv, TestPacketId, TestReliableSequenceId);
  138. UdpPacketHeader recvHeader7(recv, TestPacketId, TestReliableSequenceId);
  139. UdpPacketHeader recvHeader8(recv, TestPacketId, TestReliableSequenceId);
  140. send.ProcessReceived(nullptr, recvHeader3);
  141. recv.ProcessReceived(nullptr, sendHeader3);
  142. recv.ProcessReceived(nullptr, sendHeader2);
  143. send.ProcessReceived(nullptr, recvHeader3);
  144. recv.ProcessReceived(nullptr, sendHeader1);
  145. recv.ProcessReceived(nullptr, sendHeader5);
  146. recv.ProcessReceived(nullptr, sendHeader8);
  147. send.ProcessReceived(nullptr, recvHeader2);
  148. UdpPacketHeader recvHeaderTmp(recv, TestPacketId, TestReliableSequenceId);
  149. send.ProcessReceived(nullptr, recvHeaderTmp);
  150. {
  151. BitsetChunk sendChunk;
  152. BitsetChunk recvChunk;
  153. send.GetAcknowledgedWindow().GetMostRecentAckState(sendChunk);
  154. recv.GetReceivedWindow().GetMostRecentAckState(recvChunk);
  155. BitsetChunk testResult = 0;
  156. for (uint32_t bit = 0; bit < UdpPacketIdWindow::PacketAckContainer::NumBitsetChunkedBits; ++bit)
  157. {
  158. if (send.GetAcknowledgedWindow().GetPacketAckContainer().GetBit(bit))
  159. {
  160. SetBitHelper(testResult, bit, true);
  161. }
  162. }
  163. EXPECT_EQ(sendChunk, recvChunk); // PacketTracker: Replication of acked bits
  164. EXPECT_EQ(sendChunk, testResult); // Optimized ack window generation failed brute force check
  165. }
  166. UdpPacketHeader sendHeaderTmp(send, TestPacketId, TestReliableSequenceId);
  167. recv.ProcessReceived(nullptr, sendHeaderTmp);
  168. {
  169. BitsetChunk sendChunk;
  170. BitsetChunk recvChunk;
  171. recv.GetAcknowledgedWindow().GetMostRecentAckState(sendChunk);
  172. send.GetReceivedWindow().GetMostRecentAckState(recvChunk);
  173. BitsetChunk testResult = 0;
  174. for (uint32_t bit = 0; bit < UdpPacketIdWindow::PacketAckContainer::NumBitsetChunkedBits; ++bit)
  175. {
  176. if (recv.GetAcknowledgedWindow().GetPacketAckContainer().GetBit(bit))
  177. {
  178. SetBitHelper(testResult, bit, true);
  179. }
  180. }
  181. EXPECT_EQ(sendChunk, recvChunk); // PacketTracker: Replication of acked bits
  182. EXPECT_EQ(sendChunk, testResult); // Optimized ack window generation failed brute force check
  183. }
  184. }
  185. }
  186. TEST_F(UdpTransportTests, PacketIdWindow)
  187. {
  188. const PacketType TestPacketType{ 12212 };
  189. UdpPacketIdWindow packetWindow;
  190. UdpPacketHeader header1(TestPacketType, InvalidSequenceId, SequenceId{ 985 }, InvalidSequenceId, 0xF8000FFF, SequenceRolloverCount{ 0 });
  191. packetWindow.UpdateForRemoteAckStatus(nullptr, header1);
  192. UdpPacketHeader header2(TestPacketType, InvalidSequenceId, SequenceId{ 995 }, InvalidSequenceId, 0x3FFFFF, SequenceRolloverCount{ 0 });
  193. packetWindow.UpdateForRemoteAckStatus(nullptr, header2);
  194. UdpPacketHeader header3(TestPacketType, InvalidSequenceId, SequenceId{ 999 }, InvalidSequenceId, 0x3FFFFFF, SequenceRolloverCount{ 0 });
  195. packetWindow.UpdateForRemoteAckStatus(nullptr, header3);
  196. UdpPacketHeader header4(TestPacketType, InvalidSequenceId, SequenceId{ 1080 }, InvalidSequenceId, 0x3FF, SequenceRolloverCount{ 0 });
  197. packetWindow.UpdateForRemoteAckStatus(nullptr, header4);
  198. UdpPacketHeader header5(TestPacketType, InvalidSequenceId, SequenceId{ 1090 }, InvalidSequenceId, 0xFFFFF, SequenceRolloverCount{ 0 });
  199. packetWindow.UpdateForRemoteAckStatus(nullptr, header5);
  200. UdpPacketHeader header6(TestPacketType, InvalidSequenceId, SequenceId{ 1100 }, InvalidSequenceId, 0x3FFFFFFF, SequenceRolloverCount{ 0 });
  201. packetWindow.UpdateForRemoteAckStatus(nullptr, header6);
  202. UdpPacketHeader header7(TestPacketType, InvalidSequenceId, SequenceId{ 1102 }, InvalidSequenceId, 0xFFFFFFFF, SequenceRolloverCount{ 0 });
  203. packetWindow.UpdateForRemoteAckStatus(nullptr, header7);
  204. UdpPacketHeader header8(TestPacketType, InvalidSequenceId, SequenceId{ 1134 }, InvalidSequenceId, 0x1, SequenceRolloverCount{ 0 });
  205. packetWindow.UpdateForRemoteAckStatus(nullptr, header8);
  206. PacketAckState ackState = packetWindow.GetPacketAckStatus(PacketId(1007));
  207. EXPECT_EQ(ackState, PacketAckState::Nacked); // Testing that PacketId is not flagged as acked
  208. }
  209. TEST_F(UdpTransportTests, TestSingleClient)
  210. {
  211. TestUdpServer testServer;
  212. TestUdpClient testClient;
  213. constexpr AZ::TimeMs TotalIterationTimeMs = AZ::TimeMs{ 5000 };
  214. const AZ::TimeMs startTimeMs = AZ::GetElapsedTimeMs();
  215. for (;;)
  216. {
  217. AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(25));
  218. m_networkingSystemComponent->OnSystemTick();
  219. bool timeExpired = (AZ::GetElapsedTimeMs() - startTimeMs > TotalIterationTimeMs);
  220. bool canTerminate = (testServer.m_serverNetworkInterface->GetConnectionSet().GetConnectionCount() == 1)
  221. && (testClient.m_clientNetworkInterface->GetConnectionSet().GetConnectionCount() == 1);
  222. if (canTerminate || timeExpired)
  223. {
  224. break;
  225. }
  226. }
  227. EXPECT_EQ(testServer.m_serverNetworkInterface->GetConnectionSet().GetConnectionCount(), 1);
  228. EXPECT_EQ(testClient.m_clientNetworkInterface->GetConnectionSet().GetConnectionCount(), 1);
  229. const AZ::TimeMs timeoutMs = AZ::TimeMs{ 100 };
  230. testClient.m_clientNetworkInterface->SetTimeoutMs(timeoutMs);
  231. EXPECT_EQ(testClient.m_clientNetworkInterface->GetTimeoutMs(), timeoutMs);
  232. EXPECT_FALSE(dynamic_cast<UdpNetworkInterface*>(testClient.m_clientNetworkInterface)->IsEncrypted());
  233. EXPECT_TRUE(testServer.m_serverNetworkInterface->StopListening());
  234. EXPECT_FALSE(testServer.m_serverNetworkInterface->StopListening());
  235. EXPECT_FALSE(dynamic_cast<UdpNetworkInterface*>(testServer.m_serverNetworkInterface)->IsOpen());
  236. }
  237. TEST_F(UdpTransportTests, TestMultipleClients)
  238. {
  239. constexpr uint32_t NumTestClients = 50;
  240. TestUdpServer testServer;
  241. TestUdpClient testClient[NumTestClients];
  242. constexpr AZ::TimeMs TotalIterationTimeMs = AZ::TimeMs{ 5000 };
  243. const AZ::TimeMs startTimeMs = AZ::GetElapsedTimeMs();
  244. for (;;)
  245. {
  246. AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(25));
  247. m_networkingSystemComponent->OnSystemTick();
  248. bool timeExpired = (AZ::GetElapsedTimeMs() - startTimeMs > TotalIterationTimeMs);
  249. bool canTerminate = testServer.m_serverNetworkInterface->GetConnectionSet().GetConnectionCount() == NumTestClients;
  250. for (uint32_t i = 0; i < NumTestClients; ++i)
  251. {
  252. canTerminate &= testClient[i].m_clientNetworkInterface->GetConnectionSet().GetConnectionCount() == 1;
  253. }
  254. if (canTerminate || timeExpired)
  255. {
  256. break;
  257. }
  258. }
  259. EXPECT_EQ(testServer.m_serverNetworkInterface->GetConnectionSet().GetConnectionCount(), NumTestClients);
  260. for (uint32_t i = 0; i < NumTestClients; ++i)
  261. {
  262. EXPECT_EQ(testClient[i].m_clientNetworkInterface->GetConnectionSet().GetConnectionCount(), 1);
  263. }
  264. }
  265. }