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
16 net_init();
17 NETADDR BindAddr;
18 mem_zero(block: &BindAddr, size: sizeof(BindAddr));
19 BindAddr.type = NETTYPE_ALL;
20
21 CNetClient NetClient;
22 NetClient.Open(BindAddr);
23
24 if(argc != 2)
25 {
26 log_error("twping", "usage: %s server[:port] (default port: 8303)", argv[0]);
27 return -1;
28 }
29
30 NETADDR Addr;
31 if(net_host_lookup(hostname: argv[1], addr: &Addr, types: NETTYPE_ALL))
32 {
33 log_error("twping", "host lookup failed");
34 return -1;
35 }
36
37 if(Addr.port == 0)
38 Addr.port = 8303;
39
40 const int CurToken = rand() % 256;
41 unsigned char aBuffer[sizeof(SERVERBROWSE_GETINFO) + 1];
42 mem_copy(dest: aBuffer, source: SERVERBROWSE_GETINFO, size: sizeof(SERVERBROWSE_GETINFO));
43 aBuffer[sizeof(SERVERBROWSE_GETINFO)] = CurToken;
44
45 CNetChunk Packet;
46 Packet.m_ClientId = -1;
47 Packet.m_Address = Addr;
48 Packet.m_Flags = NETSENDFLAG_CONNLESS;
49 Packet.m_DataSize = sizeof(aBuffer);
50 Packet.m_pData = aBuffer;
51
52 NetClient.Send(pChunk: &Packet);
53
54 const int64_t StartTime = time_get();
55
56 using namespace std::chrono_literals;
57 const std::chrono::nanoseconds Timeout = std::chrono::nanoseconds(1s);
58 net_socket_read_wait(sock: NetClient.m_Socket, nanoseconds: Timeout);
59
60 NetClient.Update();
61
62 SECURITY_TOKEN ResponseToken;
63 while(NetClient.Recv(pChunk: &Packet, pResponseToken: &ResponseToken, Sixup: false))
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