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.
24 #include "util/serialize.h"
25 #include "network/connection.h"
26 #include "network/networkpacket.h"
27 #include "network/socket.h"
29 class TestConnection : public TestBase {
33 if (INTERNET_SIMULATOR == false)
34 TestManager::registerTestModule(this);
37 const char *getName() { return "TestConnection"; }
39 void runTests(IGameDef *gamedef);
42 void testConnectSendReceive();
45 static TestConnection g_test_instance;
47 void TestConnection::runTests(IGameDef *gamedef)
50 TEST(testConnectSendReceive);
53 ////////////////////////////////////////////////////////////////////////////////
55 struct Handler : public con::PeerHandler
57 Handler(const char *a_name) : name(a_name) {}
59 void peerAdded(con::Peer *peer)
61 infostream << "Handler(" << name << ")::peerAdded(): "
62 "id=" << peer->id << std::endl;
67 void deletingPeer(con::Peer *peer, bool timeout)
69 infostream << "Handler(" << name << ")::deletingPeer(): "
70 "id=" << peer->id << ", timeout=" << timeout << std::endl;
80 void TestConnection::testHelpers()
82 // Some constants for testing
83 u32 proto_id = 0x12345678;
86 SharedBuffer<u8> data1(1);
88 Address a(127,0,0,1, 10);
89 const u16 seqnum = 34352;
91 con::BufferedPacket p1 = con::makePacket(a, data1,
92 proto_id, peer_id, channel);
94 We should now have a packet with this data:
97 [4] u16 sender_peer_id
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]);
107 //infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
109 SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
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;*/
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]);
124 void TestConnection::testConnectSendReceive()
126 DSTACK("TestConnection::Run");
129 Test some real connections
131 NOTE: This mostly tests the legacy interface.
134 u32 proto_id = 0xad26846a;
136 Handler hand_server("server");
137 Handler hand_client("client");
139 Address address(0, 0, 0, 0, 30001);
140 Address bind_addr(0, 0, 0, 0, 30001);
142 * Try to use the bind_address for servers with no localhost address
143 * For example: FreeBSD jails
145 std::string bind_str = g_settings->get("bind_address");
147 bind_addr.Resolve(bind_str.c_str());
149 if (!bind_addr.isIPv6()) {
152 } catch (ResolveError &e) {
155 infostream << "** Creating server Connection" << std::endl;
156 con::Connection server(proto_id, 512, 5.0, false, &hand_server);
157 server.Serve(address);
159 infostream << "** Creating client Connection" << std::endl;
160 con::Connection client(proto_id, 512, 5.0, false, &hand_client);
162 UASSERT(hand_server.count == 0);
163 UASSERT(hand_client.count == 0);
167 Address server_address(127, 0, 0, 1, 30001);
168 if (address != Address(0, 0, 0, 0, 30001)) {
169 server_address = bind_addr;
172 infostream << "** running client.Connect()" << std::endl;
173 client.Connect(server_address);
177 // Client should not have added client yet
178 UASSERT(hand_client.count == 0);
182 infostream << "** running client.Receive()" << std::endl;
183 client.Receive(&pkt);
184 infostream << "** Client received: peer_id=" << pkt.getPeerId()
185 << ", size=" << pkt.getSize() << std::endl;
186 } catch (con::NoIncomingDataException &e) {
189 // Client should have added server now
190 UASSERT(hand_client.count == 1);
191 UASSERT(hand_client.last_id == 1);
192 // Server should not have added client yet
193 UASSERT(hand_server.count == 0);
199 infostream << "** running server.Receive()" << std::endl;
200 server.Receive(&pkt);
201 infostream << "** Server received: peer_id=" << pkt.getPeerId()
202 << ", size=" << pkt.getSize()
204 } catch (con::NoIncomingDataException &e) {
205 // No actual data received, but the client has
206 // probably been connected
209 // Client should be the same
210 UASSERT(hand_client.count == 1);
211 UASSERT(hand_client.last_id == 1);
212 // Server should have the client
213 UASSERT(hand_server.count == 1);
214 UASSERT(hand_server.last_id == 2);
218 while (client.Connected() == false) {
221 infostream << "** running client.Receive()" << std::endl;
222 client.Receive(&pkt);
223 infostream << "** Client received: peer_id=" << pkt.getPeerId()
224 << ", size=" << pkt.getSize() << std::endl;
225 } catch (con::NoIncomingDataException &e) {
234 infostream << "** running server.Receive()" << std::endl;
235 server.Receive(&pkt);
236 infostream << "** Server received: peer_id=" << pkt.getPeerId()
237 << ", size=" << pkt.getSize()
239 } catch (con::NoIncomingDataException &e) {
243 Simple send-receive test
247 pkt.putRawPacket((u8*) "Hello World !", 14, 0);
249 SharedBuffer<u8> sentdata = pkt.oldForgePacket();
251 infostream<<"** running client.Send()"<<std::endl;
252 client.Send(PEER_ID_SERVER, 0, &pkt, true);
256 NetworkPacket recvpacket;
257 infostream << "** running server.Receive()" << std::endl;
258 server.Receive(&recvpacket);
259 infostream << "** Server received: peer_id=" << pkt.getPeerId()
260 << ", size=" << pkt.getSize()
261 << ", data=" << (const char*)pkt.getU8Ptr(0)
264 SharedBuffer<u8> recvdata = pkt.oldForgePacket();
266 UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
269 u16 peer_id_client = 2;
274 const int datasize = 30000;
275 NetworkPacket pkt(0, datasize);
276 for (u16 i=0; i<datasize; i++) {
280 infostream << "Sending data (size=" << datasize << "):";
281 for (int i = 0; i < datasize && i < 20; i++) {
285 snprintf(buf, 10, "%.2X",
286 ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff);
291 infostream << std::endl;
293 SharedBuffer<u8> sentdata = pkt.oldForgePacket();
295 server.Send(peer_id_client, 0, &pkt, true);
299 SharedBuffer<u8> recvdata;
300 infostream << "** running client.Receive()" << std::endl;
303 bool received = false;
304 u64 timems0 = porting::getTimeMs();
306 if (porting::getTimeMs() - timems0 > 5000 || received)
310 client.Receive(&pkt);
311 size = pkt.getSize();
312 peer_id = pkt.getPeerId();
313 recvdata = pkt.oldForgePacket();
315 } catch (con::NoIncomingDataException &e) {
320 infostream << "** Client received: peer_id=" << peer_id
321 << ", size=" << size << std::endl;
323 infostream << "Received data (size=" << size << "): ";
324 for (int i = 0; i < size && i < 20; i++) {
328 snprintf(buf, 10, "%.2X", ((int)(recvdata[i])) & 0xff);
333 infostream << std::endl;
335 UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
336 UASSERT(peer_id == PEER_ID_SERVER);
339 // Check peer handlers
340 UASSERT(hand_client.count == 1);
341 UASSERT(hand_client.last_id == 1);
342 UASSERT(hand_server.count == 1);
343 UASSERT(hand_server.last_id == 2);