X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Flibswift_udp%2Fnat_test.cpp;fp=src%2Flibswift_udp%2Fnat_test.cpp;h=11d9fef717943054e01ef50628aed0aad24b72a0;hb=46f3ca346fe499ba3e8f595fc5c2aa2b3e3c4d5f;hp=0000000000000000000000000000000000000000;hpb=d8da6fc1273a2acee935a15761b77a73424faef5;p=swifty.git diff --git a/src/libswift_udp/nat_test.cpp b/src/libswift_udp/nat_test.cpp new file mode 100644 index 0000000..11d9fef --- /dev/null +++ b/src/libswift_udp/nat_test.cpp @@ -0,0 +1,159 @@ +/* + * nat_test.cpp + * NAT type testing. + * + * Created by Gertjan Halkes. + * Copyright 2010 Delft University of Technology. All rights reserved. + * + */ + +#include "swift.h" +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#include +#endif + +#define REQUEST_MAGIC 0x5a9e5fa1 +#define REPLY_MAGIC 0xa655c5d5 +#define REPLY_SEC_MAGIC 0x85e4a5ca +#define MAX_TRIES 3 +namespace swift { + +static void on_may_receive(SOCKET sock); +static void on_may_send(SOCKET sock); +static tint test_start; +static int tries; +static int packets_since_last_try; + +static sckrwecb_t callbacks(0, on_may_receive, on_may_send, NULL); +/* Note that we lookup the addresses when we actually send, because Windows requires that + the winsock library is first intialized. If we use Address type variables here, the + lookup would be tried before that initialization, which fails... */ +//FIXME: Change addresses to actual addresses used in test (at least 2 should be provided!) +static const char *servers[] = { "dutigp.st.ewi.tudelft.nl:18375" , + "127.0.0.3:18375" }; + +static void on_may_receive(SOCKET sock) { + Datagram data(sock); + + data.Recv(); + + uint32_t magic = data.Pull32(); + if ((magic != REPLY_MAGIC && magic != REPLY_SEC_MAGIC) || + (magic == REPLY_MAGIC && data.size() != 6) || (magic == REPLY_SEC_MAGIC && data.size() != 0)) + { + dprintf("%s #0 NATTEST weird packet %s \n", tintstr(), data.address().str()); + return; + } + + if (magic == REPLY_MAGIC) { + uint32_t ip = data.Pull32(); + uint16_t port = data.Pull16(); + Address reported(ip, port); + dprintf("%s #0 NATTEST incoming %s %s\n", tintstr(), data.address().str(), reported.str()); + } else { + dprintf("%s #0 NATTEST incoming secondary %s\n", tintstr(), data.address().str()); + } + packets_since_last_try++; +} + +static void on_may_send(SOCKET sock) { + callbacks.may_write = NULL; + Datagram::Listen3rdPartySocket(callbacks); + + for (size_t i = 0; i < (sizeof(servers)/sizeof(servers[0])); i++) { + Datagram request(sock, Address(servers[i])); + + request.Push32(REQUEST_MAGIC); + request.Send(); + } + test_start = NOW; + + struct sockaddr_in name; + socklen_t namelen = sizeof(name); + if (getsockname(sock, (struct sockaddr *) &name, &namelen) < 0) { + dprintf("%s #0 NATTEST could not get local address\n", tintstr()); + } else { + Address local(ntohl(name.sin_addr.s_addr), ntohs(name.sin_port)); + dprintf("%s #0 NATTEST local %s\n", tintstr(), local.str()); + } +} + +static void printAddresses(void) { +#ifdef _WIN32 + IP_ADAPTER_INFO *adapterInfo = NULL; + IP_ADAPTER_INFO *adapter = NULL; + DWORD retval = 0; + UINT i; + ULONG size = 0; + + if ((retval = GetAdaptersInfo(adapterInfo, &size)) != ERROR_BUFFER_OVERFLOW) { + dprintf("ERROR: %d\n", (int) retval); + return; + } + + adapterInfo = (IP_ADAPTER_INFO *) malloc(size); + if (adapterInfo == NULL) { + dprintf("ERROR: out of memory\n"); + return; + } + + if ((retval = GetAdaptersInfo(adapterInfo, &size)) == NO_ERROR) { + adapter = adapterInfo; + while (adapter) { + IP_ADDR_STRING *address; + for (address = &adapter->IpAddressList; address != NULL; address = address->Next) { + if (address->IpAddress.String[0] != 0) + dprintf("ADDRESS: %s\n", address->IpAddress.String); + } + adapter = adapter->Next; + } + } else { + dprintf("ERROR: %d\n", (int) retval); + } + free(adapterInfo); +#else + struct ifaddrs *addrs, *ptr; + if (getifaddrs(&addrs) < 0) { + dprintf("ERROR: %s\n", strerror(errno)); + return; + } + + for (ptr = addrs; ptr != NULL; ptr = ptr->ifa_next) { + if (ptr->ifa_addr->sa_family == AF_INET) { + dprintf("ADDRESS: %s\n", inet_ntoa(((struct sockaddr_in *) ptr->ifa_addr)->sin_addr)); + } + } + freeifaddrs(addrs); +#endif +} + + +void nat_test_update(void) { + static bool initialized; + if (!initialized) { + initialized = true; + printAddresses(); + } + + if (tries < MAX_TRIES && NOW - test_start > 30 * TINT_SEC) { + if (tries == 0) { + Address any; + SOCKET sock = Datagram::Bind(any, callbacks); + callbacks.sock = sock; + } else if (packets_since_last_try == 0) { + // Keep on trying if we didn't receive _any_ packet in response to our last request + tries--; + } + tries++; + callbacks.may_write = on_may_send; + Datagram::Listen3rdPartySocket(callbacks); + } +} + +}