1#include <base/logger.h>
2#include <base/system.h>
3
4#include <engine/shared/masterserver.h>
5#include <engine/shared/network.h>
6#include <engine/shared/packer.h>
7
8#include <chrono>
9
10int main(int argc, const char **argv)
11{
12 CCmdlineFix CmdlineFix(&argc, &argv);
13
14 log_set_global_logger_default();
15 if(secure_random_init() != 0)
16 {
17 log_error("twping", "could not initialize secure RNG");
18 return -1;
19 }
20
21 net_init();
22 NETADDR BindAddr;
23 mem_zero(block: &BindAddr, size: sizeof(BindAddr));
24 BindAddr.type = NETTYPE_ALL;
25
26 CNetClient NetClient;
27 NetClient.Open(BindAddr);
28
29 if(argc != 2)
30 {
31 log_error("twping", "usage: %s server[:port] (default port: 8303)", argv[0]);
32 return -1;
33 }
34
35 NETADDR Addr;
36 if(net_host_lookup(hostname: argv[1], addr: &Addr, types: NETTYPE_ALL))
37 {
38 log_error("twping", "host lookup failed");
39 return -1;
40 }
41
42 if(Addr.port == 0)
43 Addr.port = 8303;
44
45 const int CurToken = rand() % 256;
46 unsigned char aBuffer[sizeof(SERVERBROWSE_GETINFO) + 1];
47 mem_copy(dest: aBuffer, source: SERVERBROWSE_GETINFO, size: sizeof(SERVERBROWSE_GETINFO));
48 aBuffer[sizeof(SERVERBROWSE_GETINFO)] = CurToken;
49
50 CNetChunk Packet;
51 Packet.m_ClientId = -1;
52 Packet.m_Address = Addr;
53 Packet.m_Flags = NETSENDFLAG_CONNLESS;
54 Packet.m_DataSize = sizeof(aBuffer);
55 Packet.m_pData = aBuffer;
56
57 NetClient.Send(pChunk: &Packet);
58
59 const int64_t StartTime = time_get();
60
61 using namespace std::chrono_literals;
62 const std::chrono::nanoseconds Timeout = std::chrono::nanoseconds(1s);
63 net_socket_read_wait(sock: NetClient.m_Socket, nanoseconds: Timeout);
64
65 NetClient.Update();
66
67 while(NetClient.Recv(pChunk: &Packet))
68 {
69 if(Packet.m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && mem_comp(a: Packet.m_pData, b: SERVERBROWSE_INFO, size: sizeof(SERVERBROWSE_INFO)) == 0)
70 {
71 // we got ze info
72 CUnpacker Unpacker;
73 Unpacker.Reset(pData: (unsigned char *)Packet.m_pData + sizeof(SERVERBROWSE_INFO), Size: Packet.m_DataSize - sizeof(SERVERBROWSE_INFO));
74 int Token = str_toint(str: Unpacker.GetString());
75 if(Token != CurToken)
76 continue;
77
78 const int64_t EndTime = time_get();
79 log_info("twping", "%g ms", (double)(EndTime - StartTime) / time_freq() * 1000);
80 return 0;
81 }
82 }
83
84 log_info("twping", "timeout (%" PRId64 " ms)", std::chrono::duration_cast<std::chrono::milliseconds>(Timeout).count());
85 return 1;
86}
87