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