test_connection.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "test.h"
  17. #include "log.h"
  18. #include "settings.h"
  19. #include "util/serialize.h"
  20. #include "network/connection.h"
  21. #include "network/networkpacket.h"
  22. #include "network/socket.h"
  23. class TestConnection : public TestBase {
  24. public:
  25. TestConnection()
  26. {
  27. if (INTERNET_SIMULATOR == false)
  28. TestManager::registerTestModule(this);
  29. }
  30. const char *getName() { return "TestConnection"; }
  31. void runTests(IGameDef *gamedef);
  32. void testHelpers();
  33. void testConnectSendReceive();
  34. };
  35. static TestConnection g_test_instance;
  36. void TestConnection::runTests(IGameDef *gamedef)
  37. {
  38. TEST(testHelpers);
  39. TEST(testConnectSendReceive);
  40. }
  41. ////////////////////////////////////////////////////////////////////////////////
  42. struct Handler : public con::PeerHandler
  43. {
  44. Handler(const char *a_name) : name(a_name) {}
  45. void peerAdded(con::Peer *peer)
  46. {
  47. infostream << "Handler(" << name << ")::peerAdded(): "
  48. "id=" << peer->id << std::endl;
  49. last_id = peer->id;
  50. count++;
  51. }
  52. void deletingPeer(con::Peer *peer, bool timeout)
  53. {
  54. infostream << "Handler(" << name << ")::deletingPeer(): "
  55. "id=" << peer->id << ", timeout=" << timeout << std::endl;
  56. last_id = peer->id;
  57. count--;
  58. }
  59. s32 count = 0;
  60. u16 last_id = 0;
  61. const char *name;
  62. };
  63. void TestConnection::testHelpers()
  64. {
  65. // Some constants for testing
  66. u32 proto_id = 0x12345678;
  67. u16 peer_id = 123;
  68. u8 channel = 2;
  69. SharedBuffer<u8> data1(1);
  70. data1[0] = 100;
  71. Address a(127,0,0,1, 10);
  72. const u16 seqnum = 34352;
  73. con::BufferedPacket p1 = con::makePacket(a, data1,
  74. proto_id, peer_id, channel);
  75. /*
  76. We should now have a packet with this data:
  77. Header:
  78. [0] u32 protocol_id
  79. [4] u16 sender_peer_id
  80. [6] u8 channel
  81. Data:
  82. [7] u8 data1[0]
  83. */
  84. UASSERT(readU32(&p1.data[0]) == proto_id);
  85. UASSERT(readU16(&p1.data[4]) == peer_id);
  86. UASSERT(readU8(&p1.data[6]) == channel);
  87. UASSERT(readU8(&p1.data[7]) == data1[0]);
  88. //infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
  89. SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
  90. /*infostream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
  91. <<data1.getSize()<<std::endl;
  92. infostream<<"readU8(&p2[3])="<<readU8(&p2[3])
  93. <<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
  94. infostream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
  95. UASSERT(p2.getSize() == 3 + data1.getSize());
  96. UASSERT(readU8(&p2[0]) == con::PACKET_TYPE_RELIABLE);
  97. UASSERT(readU16(&p2[1]) == seqnum);
  98. UASSERT(readU8(&p2[3]) == data1[0]);
  99. }
  100. void TestConnection::testConnectSendReceive()
  101. {
  102. /*
  103. Test some real connections
  104. NOTE: This mostly tests the legacy interface.
  105. */
  106. u32 proto_id = 0xad26846a;
  107. Handler hand_server("server");
  108. Handler hand_client("client");
  109. Address address(0, 0, 0, 0, 30001);
  110. Address bind_addr(0, 0, 0, 0, 30001);
  111. /*
  112. * Try to use the bind_address for servers with no localhost address
  113. * For example: FreeBSD jails
  114. */
  115. std::string bind_str = g_settings->get("bind_address");
  116. try {
  117. bind_addr.Resolve(bind_str.c_str());
  118. if (!bind_addr.isIPv6()) {
  119. address = bind_addr;
  120. }
  121. } catch (ResolveError &e) {
  122. }
  123. infostream << "** Creating server Connection" << std::endl;
  124. con::Connection server(proto_id, 512, 5.0, false, &hand_server);
  125. server.Serve(address);
  126. infostream << "** Creating client Connection" << std::endl;
  127. con::Connection client(proto_id, 512, 5.0, false, &hand_client);
  128. UASSERT(hand_server.count == 0);
  129. UASSERT(hand_client.count == 0);
  130. sleep_ms(50);
  131. Address server_address(127, 0, 0, 1, 30001);
  132. if (address != Address(0, 0, 0, 0, 30001)) {
  133. server_address = bind_addr;
  134. }
  135. infostream << "** running client.Connect()" << std::endl;
  136. client.Connect(server_address);
  137. sleep_ms(50);
  138. // Client should not have added client yet
  139. UASSERT(hand_client.count == 0);
  140. try {
  141. NetworkPacket pkt;
  142. infostream << "** running client.Receive()" << std::endl;
  143. client.Receive(&pkt);
  144. infostream << "** Client received: peer_id=" << pkt.getPeerId()
  145. << ", size=" << pkt.getSize() << std::endl;
  146. } catch (con::NoIncomingDataException &e) {
  147. }
  148. // Client should have added server now
  149. UASSERT(hand_client.count == 1);
  150. UASSERT(hand_client.last_id == 1);
  151. // Server should not have added client yet
  152. UASSERT(hand_server.count == 0);
  153. sleep_ms(100);
  154. try {
  155. NetworkPacket pkt;
  156. infostream << "** running server.Receive()" << std::endl;
  157. server.Receive(&pkt);
  158. infostream << "** Server received: peer_id=" << pkt.getPeerId()
  159. << ", size=" << pkt.getSize()
  160. << std::endl;
  161. } catch (con::NoIncomingDataException &e) {
  162. // No actual data received, but the client has
  163. // probably been connected
  164. }
  165. // Client should be the same
  166. UASSERT(hand_client.count == 1);
  167. UASSERT(hand_client.last_id == 1);
  168. // Server should have the client
  169. UASSERT(hand_server.count == 1);
  170. UASSERT(hand_server.last_id == 2);
  171. //sleep_ms(50);
  172. while (client.Connected() == false) {
  173. try {
  174. NetworkPacket pkt;
  175. infostream << "** running client.Receive()" << std::endl;
  176. client.Receive(&pkt);
  177. infostream << "** Client received: peer_id=" << pkt.getPeerId()
  178. << ", size=" << pkt.getSize() << std::endl;
  179. } catch (con::NoIncomingDataException &e) {
  180. }
  181. sleep_ms(50);
  182. }
  183. sleep_ms(50);
  184. try {
  185. NetworkPacket pkt;
  186. infostream << "** running server.Receive()" << std::endl;
  187. server.Receive(&pkt);
  188. infostream << "** Server received: peer_id=" << pkt.getPeerId()
  189. << ", size=" << pkt.getSize()
  190. << std::endl;
  191. } catch (con::NoIncomingDataException &e) {
  192. }
  193. /*
  194. Simple send-receive test
  195. */
  196. {
  197. NetworkPacket pkt;
  198. pkt.putRawPacket((u8*) "Hello World !", 14, 0);
  199. SharedBuffer<u8> sentdata = pkt.oldForgePacket();
  200. infostream<<"** running client.Send()"<<std::endl;
  201. client.Send(PEER_ID_SERVER, 0, &pkt, true);
  202. sleep_ms(50);
  203. NetworkPacket recvpacket;
  204. infostream << "** running server.Receive()" << std::endl;
  205. server.Receive(&recvpacket);
  206. infostream << "** Server received: peer_id=" << pkt.getPeerId()
  207. << ", size=" << pkt.getSize()
  208. << ", data=" << (const char*)pkt.getU8Ptr(0)
  209. << std::endl;
  210. SharedBuffer<u8> recvdata = pkt.oldForgePacket();
  211. UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
  212. }
  213. u16 peer_id_client = 2;
  214. /*
  215. Send a large packet
  216. */
  217. {
  218. const int datasize = 30000;
  219. NetworkPacket pkt(0, datasize);
  220. for (u16 i=0; i<datasize; i++) {
  221. pkt << (u8) i/4;
  222. }
  223. infostream << "Sending data (size=" << datasize << "):";
  224. for (int i = 0; i < datasize && i < 20; i++) {
  225. if (i % 2 == 0)
  226. infostream << " ";
  227. char buf[10];
  228. snprintf(buf, 10, "%.2X",
  229. ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff);
  230. infostream<<buf;
  231. }
  232. if (datasize > 20)
  233. infostream << "...";
  234. infostream << std::endl;
  235. SharedBuffer<u8> sentdata = pkt.oldForgePacket();
  236. server.Send(peer_id_client, 0, &pkt, true);
  237. //sleep_ms(3000);
  238. SharedBuffer<u8> recvdata;
  239. infostream << "** running client.Receive()" << std::endl;
  240. u16 peer_id = 132;
  241. u16 size = 0;
  242. bool received = false;
  243. u64 timems0 = porting::getTimeMs();
  244. for (;;) {
  245. if (porting::getTimeMs() - timems0 > 5000 || received)
  246. break;
  247. try {
  248. NetworkPacket pkt;
  249. client.Receive(&pkt);
  250. size = pkt.getSize();
  251. peer_id = pkt.getPeerId();
  252. recvdata = pkt.oldForgePacket();
  253. received = true;
  254. } catch (con::NoIncomingDataException &e) {
  255. }
  256. sleep_ms(10);
  257. }
  258. UASSERT(received);
  259. infostream << "** Client received: peer_id=" << peer_id
  260. << ", size=" << size << std::endl;
  261. infostream << "Received data (size=" << size << "): ";
  262. for (int i = 0; i < size && i < 20; i++) {
  263. if (i % 2 == 0)
  264. infostream << " ";
  265. char buf[10];
  266. snprintf(buf, 10, "%.2X", ((int)(recvdata[i])) & 0xff);
  267. infostream << buf;
  268. }
  269. if (size > 20)
  270. infostream << "...";
  271. infostream << std::endl;
  272. UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
  273. UASSERT(peer_id == PEER_ID_SERVER);
  274. }
  275. // Check peer handlers
  276. UASSERT(hand_client.count == 1);
  277. UASSERT(hand_client.last_id == 1);
  278. UASSERT(hand_server.count == 1);
  279. UASSERT(hand_server.last_id == 2);
  280. }