1#include <base/logger.h>
2#include <base/system.h>
3#include <engine/shared/stun.h>
4
5int main(int argc, const char **argv)
6{
7 CCmdlineFix CmdlineFix(&argc, &argv);
8
9 secure_random_init();
10 log_set_global_logger_default();
11
12 if(argc < 2)
13 {
14 log_info("stun", "usage: %s <STUN ADDRESS>", argc > 0 ? argv[0] : "stun");
15 return 1;
16 }
17 NETADDR Addr;
18 if(net_addr_from_str(addr: &Addr, string: argv[1]))
19 {
20 log_error("stun", "couldn't parse address");
21 return 2;
22 }
23
24 net_init();
25 NETADDR BindAddr;
26 mem_zero(block: &BindAddr, size: sizeof(BindAddr));
27 BindAddr.type = NETTYPE_ALL;
28 NETSOCKET Socket = net_udp_create(bindaddr: BindAddr);
29 if(net_socket_type(sock: Socket) == NETTYPE_INVALID)
30 {
31 log_error("stun", "couldn't open udp socket");
32 return 2;
33 }
34
35 CStunData Stun;
36 unsigned char aRequest[32];
37 int RequestSize = StunMessagePrepare(pBuffer: aRequest, BufferSize: sizeof(aRequest), pData: &Stun);
38 if(net_udp_send(sock: Socket, addr: &Addr, data: aRequest, size: RequestSize) == -1)
39 {
40 log_error("stun", "failed sending stun request");
41 return 2;
42 }
43
44 NETADDR ResponseAddr;
45 unsigned char *pResponse;
46 while(true)
47 {
48 if(!net_socket_read_wait(sock: Socket, time: 1000000))
49 {
50 log_error("stun", "no udp message received from server until timeout");
51 return 3;
52 }
53 int ResponseSize = net_udp_recv(sock: Socket, addr: &ResponseAddr, data: &pResponse);
54 if(ResponseSize == -1)
55 {
56 log_error("stun", "failed receiving udp message");
57 return 2;
58 }
59 else if(ResponseSize == 0)
60 {
61 continue;
62 }
63 if(net_addr_comp(a: &Addr, b: &ResponseAddr) != 0)
64 {
65 char aResponseAddr[NETADDR_MAXSTRSIZE];
66 char aAddr[NETADDR_MAXSTRSIZE];
67 net_addr_str(addr: &ResponseAddr, string: aResponseAddr, max_length: sizeof(aResponseAddr), add_port: true);
68 net_addr_str(addr: &Addr, string: aAddr, max_length: sizeof(aAddr), add_port: true);
69 log_debug("stun", "got message from %s while expecting one from %s", aResponseAddr, aAddr);
70 continue;
71 }
72 bool Success;
73 NETADDR StunAddr;
74 if(StunMessageParse(pMessage: pResponse, MessageSize: ResponseSize, pData: &Stun, pSuccess: &Success, pAddr: &StunAddr))
75 {
76 log_debug("stun", "received message from stun server that was not understood");
77 continue;
78 }
79 if(Success)
80 {
81 char aStunAddr[NETADDR_MAXSTRSIZE];
82 net_addr_str(addr: &StunAddr, string: aStunAddr, max_length: sizeof(aStunAddr), add_port: 1);
83 log_info("stun", "public ip address: %s", aStunAddr);
84 break;
85 }
86 else
87 {
88 log_info("stun", "error response from stun server");
89 break;
90 }
91 }
92}
93