test_connection.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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]) == TYPE_RELIABLE);
  97. UASSERT(readU16(&p2[1]) == seqnum);
  98. UASSERT(readU8(&p2[3]) == data1[0]);
  99. }
  100. void TestConnection::testConnectSendReceive()
  101. {
  102. DSTACK("TestConnection::Run");
  103. /*
  104. Test some real connections
  105. NOTE: This mostly tests the legacy interface.
  106. */
  107. u32 proto_id = 0xad26846a;
  108. Handler hand_server("server");
  109. Handler hand_client("client");
  110. Address address(0, 0, 0, 0, 30001);
  111. Address bind_addr(0, 0, 0, 0, 30001);
  112. /*
  113. * Try to use the bind_address for servers with no localhost address
  114. * For example: FreeBSD jails
  115. */
  116. std::string bind_str = g_settings->get("bind_address");
  117. try {
  118. bind_addr.Resolve(bind_str.c_str());
  119. if (!bind_addr.isIPv6()) {
  120. address = bind_addr;
  121. }
  122. } catch (ResolveError &e) {
  123. }
  124. infostream << "** Creating server Connection" << std::endl;
  125. con::Connection server(proto_id, 512, 5.0, false, &hand_server);
  126. server.Serve(address);
  127. infostream << "** Creating client Connection" << std::endl;
  128. con::Connection client(proto_id, 512, 5.0, false, &hand_client);
  129. UASSERT(hand_server.count == 0);
  130. UASSERT(hand_client.count == 0);
  131. sleep_ms(50);
  132. Address server_address(127, 0, 0, 1, 30001);
  133. if (address != Address(0, 0, 0, 0, 30001)) {
  134. server_address = bind_addr;
  135. }
  136. infostream << "** running client.Connect()" << std::endl;
  137. client.Connect(server_address);
  138. sleep_ms(50);
  139. // Client should not have added client yet
  140. UASSERT(hand_client.count == 0);
  141. try {
  142. NetworkPacket pkt;
  143. infostream << "** running client.Receive()" << std::endl;
  144. client.Receive(&pkt);
  145. infostream << "** Client received: peer_id=" << pkt.getPeerId()
  146. << ", size=" << pkt.getSize() << std::endl;
  147. } catch (con::NoIncomingDataException &e) {
  148. }
  149. // Client should have added server now
  150. UASSERT(hand_client.count == 1);
  151. UASSERT(hand_client.last_id == 1);
  152. // Server should not have added client yet
  153. UASSERT(hand_server.count == 0);
  154. sleep_ms(100);
  155. try {
  156. NetworkPacket pkt;
  157. infostream << "** running server.Receive()" << std::endl;
  158. server.Receive(&pkt);
  159. infostream << "** Server received: peer_id=" << pkt.getPeerId()
  160. << ", size=" << pkt.getSize()
  161. << std::endl;
  162. } catch (con::NoIncomingDataException &e) {
  163. // No actual data received, but the client has
  164. // probably been connected
  165. }
  166. // Client should be the same
  167. UASSERT(hand_client.count == 1);
  168. UASSERT(hand_client.last_id == 1);
  169. // Server should have the client
  170. UASSERT(hand_server.count == 1);
  171. UASSERT(hand_server.last_id == 2);
  172. //sleep_ms(50);
  173. while (client.Connected() == false) {
  174. try {
  175. NetworkPacket pkt;
  176. infostream << "** running client.Receive()" << std::endl;
  177. client.Receive(&pkt);
  178. infostream << "** Client received: peer_id=" << pkt.getPeerId()
  179. << ", size=" << pkt.getSize() << std::endl;
  180. } catch (con::NoIncomingDataException &e) {
  181. }
  182. sleep_ms(50);
  183. }
  184. sleep_ms(50);
  185. try {
  186. NetworkPacket pkt;
  187. infostream << "** running server.Receive()" << std::endl;
  188. server.Receive(&pkt);
  189. infostream << "** Server received: peer_id=" << pkt.getPeerId()
  190. << ", size=" << pkt.getSize()
  191. << std::endl;
  192. } catch (con::NoIncomingDataException &e) {
  193. }
  194. /*
  195. Simple send-receive test
  196. */
  197. {
  198. NetworkPacket pkt;
  199. pkt.putRawPacket((u8*) "Hello World !", 14, 0);
  200. Buffer<u8> sentdata = pkt.oldForgePacket();
  201. infostream<<"** running client.Send()"<<std::endl;
  202. client.Send(PEER_ID_SERVER, 0, &pkt, true);
  203. sleep_ms(50);
  204. NetworkPacket recvpacket;
  205. infostream << "** running server.Receive()" << std::endl;
  206. server.Receive(&recvpacket);
  207. infostream << "** Server received: peer_id=" << pkt.getPeerId()
  208. << ", size=" << pkt.getSize()
  209. << ", data=" << (const char*)pkt.getU8Ptr(0)
  210. << std::endl;
  211. Buffer<u8> recvdata = pkt.oldForgePacket();
  212. UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
  213. }
  214. u16 peer_id_client = 2;
  215. /*
  216. Send a large packet
  217. */
  218. {
  219. const int datasize = 30000;
  220. NetworkPacket pkt(0, datasize);
  221. for (u16 i=0; i<datasize; i++) {
  222. pkt << (u8) i/4;
  223. }
  224. infostream << "Sending data (size=" << datasize << "):";
  225. for (int i = 0; i < datasize && i < 20; i++) {
  226. if (i % 2 == 0)
  227. infostream << " ";
  228. char buf[10];
  229. snprintf(buf, 10, "%.2X",
  230. ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff);
  231. infostream<<buf;
  232. }
  233. if (datasize > 20)
  234. infostream << "...";
  235. infostream << std::endl;
  236. Buffer<u8> sentdata = pkt.oldForgePacket();
  237. server.Send(peer_id_client, 0, &pkt, true);
  238. //sleep_ms(3000);
  239. Buffer<u8> recvdata;
  240. infostream << "** running client.Receive()" << std::endl;
  241. u16 peer_id = 132;
  242. u16 size = 0;
  243. bool received = false;
  244. u64 timems0 = porting::getTimeMs();
  245. for (;;) {
  246. if (porting::getTimeMs() - timems0 > 5000 || received)
  247. break;
  248. try {
  249. NetworkPacket pkt;
  250. client.Receive(&pkt);
  251. size = pkt.getSize();
  252. peer_id = pkt.getPeerId();
  253. recvdata = pkt.oldForgePacket();
  254. received = true;
  255. } catch (con::NoIncomingDataException &e) {
  256. }
  257. sleep_ms(10);
  258. }
  259. UASSERT(received);
  260. infostream << "** Client received: peer_id=" << peer_id
  261. << ", size=" << size << std::endl;
  262. infostream << "Received data (size=" << size << "): ";
  263. for (int i = 0; i < size && i < 20; i++) {
  264. if (i % 2 == 0)
  265. infostream << " ";
  266. char buf[10];
  267. snprintf(buf, 10, "%.2X", ((int)(recvdata[i])) & 0xff);
  268. infostream << buf;
  269. }
  270. if (size > 20)
  271. infostream << "...";
  272. infostream << std::endl;
  273. UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
  274. UASSERT(peer_id == PEER_ID_SERVER);
  275. }
  276. // Check peer handlers
  277. UASSERT(hand_client.count == 1);
  278. UASSERT(hand_client.last_id == 1);
  279. UASSERT(hand_server.count == 1);
  280. UASSERT(hand_server.last_id == 2);
  281. }