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