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