3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
25 #include "util/serialize.h"
26 #include "network/connection.h"
27 #include "network/networkpacket.h"
28 #include "network/socket.h"
30 class TestConnection : public TestBase {
34 if (INTERNET_SIMULATOR == false)
35 TestManager::registerTestModule(this);
38 const char *getName() { return "TestConnection"; }
40 void runTests(IGameDef *gamedef);
42 void testNetworkPacketSerialize();
44 void testConnectSendReceive();
47 static TestConnection g_test_instance;
49 void TestConnection::runTests(IGameDef *gamedef)
51 TEST(testNetworkPacketSerialize);
53 TEST(testConnectSendReceive);
56 ////////////////////////////////////////////////////////////////////////////////
58 struct Handler : public con::PeerHandler
60 Handler(const char *a_name) : name(a_name) {}
62 void peerAdded(con::Peer *peer)
64 infostream << "Handler(" << name << ")::peerAdded(): "
65 "id=" << peer->id << std::endl;
70 void deletingPeer(con::Peer *peer, bool timeout)
72 infostream << "Handler(" << name << ")::deletingPeer(): "
73 "id=" << peer->id << ", timeout=" << timeout << std::endl;
83 void TestConnection::testNetworkPacketSerialize()
85 const static u8 expected[] = {
87 0x00, 0x02, 0xd8, 0x42, 0xdf, 0x9a
90 if (sizeof(wchar_t) == 2)
91 warningstream << __FUNCTION__ << " may fail on this platform." << std::endl;
94 NetworkPacket pkt(123, 0);
96 // serializing wide strings should do surrogate encoding, we test that here
97 pkt << std::wstring(L"\U00020b9a");
99 auto buf = pkt.oldForgePacket();
100 UASSERTEQ(int, buf.getSize(), sizeof(expected));
101 UASSERT(!memcmp(expected, &buf[0], buf.getSize()));
106 pkt.putRawPacket(expected, sizeof(expected), 0);
112 UASSERT(pkt_s == L"\U00020b9a");
116 void TestConnection::testHelpers()
118 // Some constants for testing
119 u32 proto_id = 0x12345678;
120 session_t peer_id = 123;
122 SharedBuffer<u8> data1(1);
124 Address a(127,0,0,1, 10);
125 const u16 seqnum = 34352;
127 con::BufferedPacketPtr p1 = con::makePacket(a, data1,
128 proto_id, peer_id, channel);
130 We should now have a packet with this data:
133 [4] session_t sender_peer_id
138 UASSERT(readU32(&p1->data[0]) == proto_id);
139 UASSERT(readU16(&p1->data[4]) == peer_id);
140 UASSERT(readU8(&p1->data[6]) == channel);
141 UASSERT(readU8(&p1->data[7]) == data1[0]);
143 //infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
145 SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
147 /*infostream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
148 <<data1.getSize()<<std::endl;
149 infostream<<"readU8(&p2[3])="<<readU8(&p2[3])
150 <<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
151 infostream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
153 UASSERT(p2.getSize() == 3 + data1.getSize());
154 UASSERT(readU8(&p2[0]) == con::PACKET_TYPE_RELIABLE);
155 UASSERT(readU16(&p2[1]) == seqnum);
156 UASSERT(readU8(&p2[3]) == data1[0]);
160 void TestConnection::testConnectSendReceive()
163 Test some real connections
165 NOTE: This mostly tests the legacy interface.
168 u32 proto_id = 0xad26846a;
170 Handler hand_server("server");
171 Handler hand_client("client");
173 Address address(0, 0, 0, 0, 30001);
174 Address bind_addr(0, 0, 0, 0, 30001);
176 * Try to use the bind_address for servers with no localhost address
177 * For example: FreeBSD jails
179 std::string bind_str = g_settings->get("bind_address");
181 bind_addr.Resolve(bind_str.c_str());
183 if (!bind_addr.isIPv6()) {
186 } catch (ResolveError &e) {
189 infostream << "** Creating server Connection" << std::endl;
190 con::Connection server(proto_id, 512, 5.0, false, &hand_server);
191 server.Serve(address);
193 infostream << "** Creating client Connection" << std::endl;
194 con::Connection client(proto_id, 512, 5.0, false, &hand_client);
196 UASSERT(hand_server.count == 0);
197 UASSERT(hand_client.count == 0);
201 Address server_address(127, 0, 0, 1, 30001);
202 if (address != Address(0, 0, 0, 0, 30001)) {
203 server_address = bind_addr;
206 infostream << "** running client.Connect()" << std::endl;
207 client.Connect(server_address);
211 // Client should not have added client yet
212 UASSERT(hand_client.count == 0);
216 infostream << "** running client.Receive()" << std::endl;
217 client.Receive(&pkt);
218 infostream << "** Client received: peer_id=" << pkt.getPeerId()
219 << ", size=" << pkt.getSize() << std::endl;
220 } catch (con::NoIncomingDataException &e) {
223 // Client should have added server now
224 UASSERT(hand_client.count == 1);
225 UASSERT(hand_client.last_id == 1);
226 // Server should not have added client yet
227 UASSERT(hand_server.count == 0);
233 infostream << "** running server.Receive()" << std::endl;
234 server.Receive(&pkt);
235 infostream << "** Server received: peer_id=" << pkt.getPeerId()
236 << ", size=" << pkt.getSize()
238 } catch (con::NoIncomingDataException &e) {
239 // No actual data received, but the client has
240 // probably been connected
243 // Client should be the same
244 UASSERT(hand_client.count == 1);
245 UASSERT(hand_client.last_id == 1);
246 // Server should have the client
247 UASSERT(hand_server.count == 1);
248 UASSERT(hand_server.last_id == 2);
252 while (client.Connected() == false) {
255 infostream << "** running client.Receive()" << std::endl;
256 client.Receive(&pkt);
257 infostream << "** Client received: peer_id=" << pkt.getPeerId()
258 << ", size=" << pkt.getSize() << std::endl;
259 } catch (con::NoIncomingDataException &e) {
268 infostream << "** running server.Receive()" << std::endl;
269 server.Receive(&pkt);
270 infostream << "** Server received: peer_id=" << pkt.getPeerId()
271 << ", size=" << pkt.getSize()
273 } catch (con::NoIncomingDataException &e) {
277 Simple send-receive test
281 pkt.putRawPacket((u8*) "Hello World !", 14, 0);
283 auto sentdata = pkt.oldForgePacket();
285 infostream<<"** running client.Send()"<<std::endl;
286 client.Send(PEER_ID_SERVER, 0, &pkt, true);
290 NetworkPacket recvpacket;
291 infostream << "** running server.Receive()" << std::endl;
292 server.Receive(&recvpacket);
293 infostream << "** Server received: peer_id=" << pkt.getPeerId()
294 << ", size=" << pkt.getSize()
295 << ", data=" << (const char*)pkt.getU8Ptr(0)
298 auto recvdata = pkt.oldForgePacket();
300 UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
303 session_t peer_id_client = 2;
308 const int datasize = 30000;
309 NetworkPacket pkt(0, datasize);
310 for (u16 i=0; i<datasize; i++) {
314 infostream << "Sending data (size=" << datasize << "):";
315 for (int i = 0; i < datasize && i < 20; i++) {
319 porting::mt_snprintf(buf, sizeof(buf), "%.2X",
320 ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff);
325 infostream << std::endl;
327 auto sentdata = pkt.oldForgePacket();
329 server.Send(peer_id_client, 0, &pkt, true);
334 infostream << "** running client.Receive()" << std::endl;
335 session_t peer_id = 132;
337 bool received = false;
338 u64 timems0 = porting::getTimeMs();
340 if (porting::getTimeMs() - timems0 > 5000 || received)
344 client.Receive(&pkt);
345 size = pkt.getSize();
346 peer_id = pkt.getPeerId();
347 recvdata = pkt.oldForgePacket();
349 } catch (con::NoIncomingDataException &e) {
354 infostream << "** Client received: peer_id=" << peer_id
355 << ", size=" << size << std::endl;
357 infostream << "Received data (size=" << size << "): ";
358 for (int i = 0; i < size && i < 20; i++) {
362 porting::mt_snprintf(buf, sizeof(buf), "%.2X", ((int)(recvdata[i])) & 0xff);
367 infostream << std::endl;
369 UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
370 UASSERT(peer_id == PEER_ID_SERVER);
373 // Check peer handlers
374 UASSERT(hand_client.count == 1);
375 UASSERT(hand_client.last_id == 1);
376 UASSERT(hand_server.count == 1);
377 UASSERT(hand_server.last_id == 2);