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