X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Flibswift%2Fnat_test_server.c;fp=src%2Flibswift%2Fnat_test_server.c;h=b2558c3dfb819f51e164016bdfdcc84cb63f90b6;hb=45963a7511531cd1656ad5d3847d2dafd015c54d;hp=0000000000000000000000000000000000000000;hpb=d069796805ad79542fd7e4406d1e9c6d2d8c2ef7;p=swifty.git diff --git a/src/libswift/nat_test_server.c b/src/libswift/nat_test_server.c new file mode 100644 index 0000000..b2558c3 --- /dev/null +++ b/src/libswift/nat_test_server.c @@ -0,0 +1,156 @@ +/* + * nat_test_server.c + * NAT type testing (server). + * + * Created by Gertjan Halkes. + * Copyright 2010 Delft University of Technology. All rights reserved. + * + */ + +//FIXME: add timestamp to log output + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REQUEST_MAGIC 0x5a9e5fa1 +#define REPLY_MAGIC 0xa655c5d5 +#define REPLY_SEC_MAGIC 0x85e4a5ca + +static int has_secondary; + +/** Alert the user of a fatal error and quit. + @param fmt The format string for the message. See fprintf(3) for details. + @param ... The arguments for printing. +*/ +void fatal(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + exit(EXIT_FAILURE); +} + +const char *getTimestamp(void) { + static char timeBuffer[1024]; + struct timeval now; + double nowF; + + gettimeofday(&now, NULL); + nowF = (double) now.tv_sec + (double) now.tv_usec / 1000000; + snprintf(timeBuffer, 1024, "%.4f", nowF); + return timeBuffer; +} + +int main(int argc, char *argv[]) { + struct sockaddr_in local, remote, secondary; + uint32_t packet[3]; + int c, sock, sock2, sock3, sock4; + ssize_t result; + + local.sin_addr.s_addr = INADDR_ANY; + + while ((c = getopt(argc, argv, "s:")) > 0) { + switch (c) { + case 's': + has_secondary = 1; + secondary.sin_addr.s_addr = inet_addr(optarg); + break; + default: + fatal("Unknown option %c\n", c); + break; + } + } + + if (argc - optind != 3) + fatal("Usage: nat_test_server [] \n"); + + local.sin_family = AF_INET; + local.sin_addr.s_addr = inet_addr(argv[optind++]); + local.sin_port = htons(atoi(argv[optind++])); + + if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + fatal("Error opening primary socket: %m\n"); + if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) + fatal("Error binding primary socket: %m\n"); + + if (has_secondary) { + secondary.sin_family = AF_INET; + secondary.sin_port = local.sin_port; + + if ((sock3 = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + fatal("Error opening primary socket on secondary address: %m\n"); + if (bind(sock3, (struct sockaddr *) &secondary, sizeof(secondary)) < 0) + fatal("Error binding primary socket on secondary address: %m\n"); + } + + local.sin_port = htons(atoi(argv[optind++])); + + if ((sock2 = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + fatal("Error opening secondary socket: %m\n"); + if (bind(sock2, (struct sockaddr *) &local, sizeof(local)) < 0) + fatal("Error binding secondary socket: %m\n"); + + if (has_secondary) { + secondary.sin_port = local.sin_port; + + if ((sock4 = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + fatal("Error opening secondary socket on secondary address: %m\n"); + if (bind(sock4, (struct sockaddr *) &secondary, sizeof(secondary)) < 0) + fatal("Error binding secondary socket on secondary address: %m\n"); + } + + while (1) { + socklen_t socklen = sizeof(remote); + if ((result = recvfrom(sock, &packet, sizeof(packet), 0, (struct sockaddr *) &remote, &socklen)) < 0) { + if (errno == EAGAIN) + continue; + fatal("%s: Error receiving packet: %m\n", getTimestamp()); + } else if (result != 4 || ntohl(packet[0]) != REQUEST_MAGIC) { + fprintf(stderr, "Strange packet received from %s\n", inet_ntoa(remote.sin_addr)); + } else { + fprintf(stderr, "%s: Received packet from %s:%d\n", getTimestamp(), inet_ntoa(remote.sin_addr), ntohs(remote.sin_port)); + packet[0] = htonl(REPLY_MAGIC); + packet[1] = remote.sin_addr.s_addr; + *(uint16_t *)(packet + 2) = remote.sin_port; + retry: + if (sendto(sock, packet, 10, 0, (const struct sockaddr *) &remote, socklen) < 10) { + if (errno == EAGAIN) + goto retry; + fprintf(stderr, "%s: Error sending packet on primary socket: %m\n", getTimestamp()); + } + retry2: + if (sendto(sock2, packet, 10, 0, (const struct sockaddr *) &remote, socklen) < 10) { + if (errno == EAGAIN) + goto retry2; + fprintf(stderr, "%s: Error sending packet on secondary socket: %m\n", getTimestamp()); + } + + if (has_secondary) { + packet[0] = htonl(REPLY_SEC_MAGIC); + retry3: + if (sendto(sock3, packet, 4, 0, (const struct sockaddr *) &remote, socklen) < 4) { + if (errno == EAGAIN) + goto retry3; + fprintf(stderr, "%s: Error sending packet on primary socket on secondary address: %m\n", getTimestamp()); + } + retry4: + if (sendto(sock4, packet, 4, 0, (const struct sockaddr *) &remote, socklen) < 4) { + if (errno == EAGAIN) + goto retry4; + fprintf(stderr, "%s: Error sending packet on secondary socket on secondary address: %m\n", getTimestamp()); + } + } + + } + } + return 0; +}