5 * Created by Gertjan Halkes.
6 * Copyright 2010 Delft University of Technology. All rights reserved.
14 #include <sys/types.h>
15 #include <sys/socket.h>
18 #include <netinet/in.h>
21 #define REQUEST_MAGIC 0x5a9e5fa1
22 #define REPLY_MAGIC 0xa655c5d5
23 #define REPLY_SEC_MAGIC 0x85e4a5ca
27 static void on_may_receive(SOCKET sock);
28 static void on_may_send(SOCKET sock);
29 static tint test_start;
31 static int packets_since_last_try;
33 static sckrwecb_t callbacks(0, on_may_receive, on_may_send, NULL);
34 /* Note that we lookup the addresses when we actually send, because Windows requires that
35 the winsock library is first intialized. If we use Address type variables here, the
36 lookup would be tried before that initialization, which fails... */
37 //FIXME: Change addresses to actual addresses used in test (at least 2 should be provided!)
38 static const char *servers[] = { "dutigp.st.ewi.tudelft.nl:18375" ,
41 static void on_may_receive(SOCKET sock) {
46 uint32_t magic = data.Pull32();
47 if ((magic != REPLY_MAGIC && magic != REPLY_SEC_MAGIC) ||
48 (magic == REPLY_MAGIC && data.size() != 6) || (magic == REPLY_SEC_MAGIC && data.size() != 0))
50 dprintf("%s #0 NATTEST weird packet %s \n", tintstr(), data.address().str());
54 if (magic == REPLY_MAGIC) {
55 uint32_t ip = data.Pull32();
56 uint16_t port = data.Pull16();
57 Address reported(ip, port);
58 dprintf("%s #0 NATTEST incoming %s %s\n", tintstr(), data.address().str(), reported.str());
60 dprintf("%s #0 NATTEST incoming secondary %s\n", tintstr(), data.address().str());
62 packets_since_last_try++;
65 static void on_may_send(SOCKET sock) {
66 callbacks.may_write = NULL;
67 Datagram::Listen3rdPartySocket(callbacks);
69 for (size_t i = 0; i < (sizeof(servers)/sizeof(servers[0])); i++) {
70 Datagram request(sock, Address(servers[i]));
72 request.Push32(REQUEST_MAGIC);
77 struct sockaddr_in name;
78 socklen_t namelen = sizeof(name);
79 if (getsockname(sock, (struct sockaddr *) &name, &namelen) < 0) {
80 dprintf("%s #0 NATTEST could not get local address\n", tintstr());
82 Address local(ntohl(name.sin_addr.s_addr), ntohs(name.sin_port));
83 dprintf("%s #0 NATTEST local %s\n", tintstr(), local.str());
87 static void printAddresses(void) {
89 IP_ADAPTER_INFO *adapterInfo = NULL;
90 IP_ADAPTER_INFO *adapter = NULL;
95 if ((retval = GetAdaptersInfo(adapterInfo, &size)) != ERROR_BUFFER_OVERFLOW) {
96 dprintf("ERROR: %d\n", (int) retval);
100 adapterInfo = (IP_ADAPTER_INFO *) malloc(size);
101 if (adapterInfo == NULL) {
102 dprintf("ERROR: out of memory\n");
106 if ((retval = GetAdaptersInfo(adapterInfo, &size)) == NO_ERROR) {
107 adapter = adapterInfo;
109 IP_ADDR_STRING *address;
110 for (address = &adapter->IpAddressList; address != NULL; address = address->Next) {
111 if (address->IpAddress.String[0] != 0)
112 dprintf("ADDRESS: %s\n", address->IpAddress.String);
114 adapter = adapter->Next;
117 dprintf("ERROR: %d\n", (int) retval);
121 struct ifaddrs *addrs, *ptr;
122 if (getifaddrs(&addrs) < 0) {
123 dprintf("ERROR: %s\n", strerror(errno));
127 for (ptr = addrs; ptr != NULL; ptr = ptr->ifa_next) {
128 if (ptr->ifa_addr->sa_family == AF_INET) {
129 dprintf("ADDRESS: %s\n", inet_ntoa(((struct sockaddr_in *) ptr->ifa_addr)->sin_addr));
137 void nat_test_update(void) {
138 static bool initialized;
144 if (tries < MAX_TRIES && NOW - test_start > 30 * TINT_SEC) {
147 SOCKET sock = Datagram::Bind(any, callbacks);
148 callbacks.sock = sock;
149 } else if (packets_since_last_try == 0) {
150 // Keep on trying if we didn't receive _any_ packet in response to our last request
154 callbacks.may_write = on_may_send;
155 Datagram::Listen3rdPartySocket(callbacks);