From: Christian Grothoff Date: Fri, 1 Jul 2011 21:30:28 +0000 (+0000) Subject: testcase for nat test code X-Git-Tag: initial-import-from-subversion-38251~17989 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=e3f24011c0e95a67d673b43348202b7751574474;p=oweals%2Fgnunet.git testcase for nat test code --- diff --git a/contrib/defaults.conf b/contrib/defaults.conf index f5a0c8c7e..a634988a1 100644 --- a/contrib/defaults.conf +++ b/contrib/defaults.conf @@ -65,6 +65,9 @@ IFC_SCAN_FREQUENCY = 3000000 # for our hostname (to get our own IP), in ms DYNDNS_FREQUENCY = 140000 +[gnunet-nat-server] +HOSTNAME = nat.gnunet.org +PORT = 5724 [transport-tcp] # Use 0 to ONLY advertise as a peer behind NAT (no port binding) diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am index 7b738df4e..5aafdb240 100644 --- a/src/nat/Makefile.am +++ b/src/nat/Makefile.am @@ -54,7 +54,8 @@ libgnunetnat_la_LDFLAGS = \ -version-info 0:0:0 check_PROGRAMS = \ - test-nat + test_nat \ + test_nat_test if ENABLE_TEST_RUN TESTS = $(check_PROGRAMS) @@ -62,11 +63,18 @@ endif test_nat_SOURCES = \ test_nat.c - test_nat_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - @LIBCURL@ + $(top_builddir)/src/util/libgnunetutil.la + + +test_nat_test_SOURCES = \ + test_nat_test.c +test_nat_test_LDADD = \ + $(top_builddir)/src/nat/libgnunetnat.la \ + $(top_builddir)/src/util/libgnunetutil.la + EXTRA_DIST = \ - test_nat_data.conf + test_nat_data.conf \ + test_nat_test_data.conf \ No newline at end of file diff --git a/src/nat/gnunet-nat-server.c b/src/nat/gnunet-nat-server.c index f2508a94a..f8951d4d2 100644 --- a/src/nat/gnunet-nat-server.c +++ b/src/nat/gnunet-nat-server.c @@ -39,6 +39,7 @@ static struct GNUNET_SERVER_Handle *server; */ static const struct GNUNET_CONFIGURATION_Handle *cfg; + /** * Try contacting the peer using autonomous * NAT traveral method. @@ -55,12 +56,17 @@ try_anat (uint32_t dst_ipv4, struct GNUNET_NAT_Handle *h; struct sockaddr_in sa; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Asking for connection reversal with %x and code %u\n", + (unsigned int) dst_ipv4, + (unsigned int) dport); h = GNUNET_NAT_register (cfg, is_tcp, dport, 0, NULL, NULL, NULL, NULL, NULL); memset (&sa, 0, sizeof (sa)); + sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif @@ -105,7 +111,7 @@ tcp_send (void *cls, ctx->s)) ) { if (-1 == GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data))) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send"); GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR); } GNUNET_NETWORK_socket_close (ctx->s); @@ -130,18 +136,22 @@ try_send_tcp (uint32_t dst_ipv4, struct sockaddr_in sa; struct TcpContext *ctx; - s = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); + s = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); if (NULL == s) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket"); return; } memset (&sa, 0, sizeof (sa)); + sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_addr.s_addr = dst_ipv4; sa.sin_port = htons (dport); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending TCP message to `%s'\n", + GNUNET_a2s ((struct sockaddr*) &sa, sizeof (sa))); if ( (GNUNET_OK != GNUNET_NETWORK_socket_connect (s, (const struct sockaddr*) &sa, sizeof (sa))) && @@ -176,19 +186,25 @@ try_send_udp (uint32_t dst_ipv4, struct GNUNET_NETWORK_Handle *s; struct sockaddr_in sa; - s = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0); + s = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0); if (NULL == s) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket"); return; } memset (&sa, 0, sizeof (sa)); + sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_addr.s_addr = dst_ipv4; sa.sin_port = htons (dport); - if (-1 == GNUNET_NETWORK_socket_sendto (s, &data, sizeof(data), (const struct sockaddr*) &sa, sizeof (sa))) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending UDP packet to `%s'\n", + GNUNET_a2s ((struct sockaddr*) &sa, sizeof (sa))); + if (-1 == GNUNET_NETWORK_socket_sendto (s, + &data, sizeof(data), + (const struct sockaddr*) &sa, sizeof (sa))) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto"); GNUNET_NETWORK_socket_close (s); } @@ -210,6 +226,8 @@ test (void *cls, const struct GNUNET_NAT_TestMessage *tm; uint16_t dport; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received test request\n"); tm = (const struct GNUNET_NAT_TestMessage*) msg; dport = ntohs (tm->dport); if (0 == dport) @@ -279,15 +297,18 @@ run (void *cls, if ( (args[0] == NULL) || (1 != SSCANF (args[0], "%u", &port)) || (0 == port) || - (65536 >= port) ) + (65536 <= port) ) { fprintf (stderr, - _("Please pass valid port number as the first argument!\n")); + _("Please pass valid port number as the first argument! (got `%s')\n"), + args[0]); return; } memset (&in4, 0, sizeof (in4)); memset (&in6, 0, sizeof (in6)); + in4.sin_family = AF_INET; in4.sin_port = htons ((uint16_t) port); + in6.sin6_family = AF_INET6; in6.sin6_port = htons ((uint16_t) port); #if HAVE_SOCKADDR_IN_SIN_LEN in4.sin_len = sizeof (in); diff --git a/src/nat/nat.c b/src/nat/nat.c index 4e78c5d24..d62dc0408 100644 --- a/src/nat/nat.c +++ b/src/nat/nat.c @@ -51,9 +51,9 @@ #define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7) /** - * How long until we give up on transmitting the welcome message? + * How long until we give up trying to resolve our own hostname? */ -#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) +#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** diff --git a/src/nat/nat_test.c b/src/nat/nat_test.c index 74b2dddec..9b07b48f9 100644 --- a/src/nat/nat_test.c +++ b/src/nat/nat_test.c @@ -61,6 +61,29 @@ struct NatActivity }; +/** + * Entry we keep for each connection to the gnunet-nat-service. + */ +struct ClientActivity +{ + /** + * This is a doubly-linked list. + */ + struct ClientActivity *next; + + /** + * This is a doubly-linked list. + */ + struct ClientActivity *prev; + + /** + * Socket of the incoming connection. + */ + struct GNUNET_CLIENT_Connection *client; + +}; + + /** * Handle to a NAT test. */ @@ -95,12 +118,22 @@ struct GNUNET_NAT_Test /** * Head of list of nat activities. */ - struct NatActivity *head; + struct NatActivity *na_head; /** * Tail of list of nat activities. */ - struct NatActivity *tail; + struct NatActivity *na_tail; + + /** + * Head of list of client activities. + */ + struct ClientActivity *ca_head; + + /** + * Tail of list of client activities. + */ + struct ClientActivity *ca_tail; /** * Identity of task for the listen socket (if any) @@ -172,8 +205,8 @@ do_read (void *cls, na->rtask = GNUNET_SCHEDULER_NO_TASK; tst = na->h; - GNUNET_CONTAINER_DLL_remove (tst->head, - tst->tail, + GNUNET_CONTAINER_DLL_remove (tst->na_head, + tst->na_tail, na); if ( (NULL != tc->write_ready) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, @@ -234,8 +267,8 @@ do_accept (void *cls, wl->sock, &do_read, wl); - GNUNET_CONTAINER_DLL_insert (tst->head, - tst->tail, + GNUNET_CONTAINER_DLL_insert (tst->na_head, + tst->na_tail, wl); } @@ -256,6 +289,7 @@ addr_cb (void *cls, socklen_t addrlen) { struct GNUNET_NAT_Test *h = cls; + struct ClientActivity *ca; struct GNUNET_CLIENT_Connection *client; struct GNUNET_NAT_TestMessage msg; const struct sockaddr_in *sa; @@ -264,6 +298,9 @@ addr_cb (void *cls, return; if (addrlen != sizeof (struct sockaddr_in)) return; /* ignore IPv6 here */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Asking gnunet-nat-server to connect to `%s'\n", + GNUNET_a2s (addr, addrlen)); sa = (const struct sockaddr_in*) addr; msg.header.size = htons (sizeof(struct GNUNET_NAT_TestMessage)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAT_TEST); @@ -274,13 +311,19 @@ addr_cb (void *cls, client = GNUNET_CLIENT_connect ("gnunet-nat-server", h->cfg); + if (NULL == client) + return; + ca = GNUNET_malloc (sizeof (struct ClientActivity)); + ca->client = client; + GNUNET_CONTAINER_DLL_insert (h->ca_head, + h->ca_tail, + ca); GNUNET_break (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client, &msg.header, GNUNET_TIME_UNIT_SECONDS, GNUNET_YES, NULL, NULL)); - GNUNET_CLIENT_disconnect (client, GNUNET_YES); } @@ -369,11 +412,20 @@ void GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) { struct NatActivity *pos; + struct ClientActivity *cpos; - while (NULL != (pos = tst->head)) + while (NULL != (cpos = tst->ca_head)) + { + GNUNET_CONTAINER_DLL_remove (tst->ca_head, + tst->ca_tail, + cpos); + GNUNET_CLIENT_disconnect (cpos->client, GNUNET_NO); + GNUNET_free (cpos); + } + while (NULL != (pos = tst->na_head)) { - GNUNET_CONTAINER_DLL_remove (tst->head, - tst->tail, + GNUNET_CONTAINER_DLL_remove (tst->na_head, + tst->na_tail, pos); GNUNET_SCHEDULER_cancel (pos->rtask); GNUNET_NETWORK_socket_close (pos->sock); diff --git a/src/nat/test_nat_test.c b/src/nat/test_nat_test.c new file mode 100644 index 000000000..3b20a9abd --- /dev/null +++ b/src/nat/test_nat_test.c @@ -0,0 +1,133 @@ +/* + This file is part of GNUnet. + (C) 2009, 2011 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * Testcase for the NAT testing code. + * + * @file nat/test_nat_test.c + * @brief Testcase for NAT testing functions + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_util_lib.h" +#include "gnunet_nat_lib.h" + + +#define VERBOSE GNUNET_YES + + +/** + * Time to wait before stopping NAT test, in seconds + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) + + +static int ret = 1; + +static struct GNUNET_NAT_Test *tst; + +static GNUNET_SCHEDULER_TaskIdentifier end; + +static void +end_test (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_NAT_test_stop (tst); +} + +static void +report_success (void *cls, + int success) +{ + GNUNET_assert (GNUNET_OK == success); + ret = 0; + GNUNET_SCHEDULER_cancel (end); + end = GNUNET_SCHEDULER_add_now (&end_test, NULL); +} + +/** + * Main function run with scheduler. + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + tst = GNUNET_NAT_test_start (cfg, GNUNET_YES, + 1285, 1285, + &report_success, NULL); + if (NULL == tst) + return; + end = GNUNET_SCHEDULER_add_delayed (TIMEOUT, + &end_test, + NULL); +} + + +int +main (int argc, char *const argv[]) +{ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + struct GNUNET_OS_Process *gns; + char *const argv_prog[] = { + "test-nat-test", + "-c", + "test_nat_test_data.conf", + "-L", +#if VERBOSE + "DEBUG", +#else + "WARNING", +#endif + NULL + }; + + GNUNET_log_setup ("test-nat-test", +#if VERBOSE + "DEBUG", +#else + "WARNING", +#endif + NULL); + gns = GNUNET_OS_start_process (NULL, NULL, + "gnunet-nat-server", + "gnunet-nat-server", +#if VERBOSE + "-L", + "DEBUG", +#endif + "12345", + NULL); + GNUNET_assert (NULL != gns); + GNUNET_PROGRAM_run (5, argv_prog, + "test-nat-test", "nohelp", + options, + &run, NULL); + GNUNET_break (0 == GNUNET_OS_process_kill (gns, SIGTERM)); + GNUNET_break (GNUNET_OK == + GNUNET_OS_process_wait (gns)); + GNUNET_OS_process_close (gns); + return ret; +} + +/* end of test_nat_test.c */ diff --git a/src/nat/test_nat_test_data.conf b/src/nat/test_nat_test_data.conf new file mode 100644 index 000000000..41324bb0a --- /dev/null +++ b/src/nat/test_nat_test_data.conf @@ -0,0 +1,43 @@ +[PATHS] +SERVICEHOME = /tmp/nat-test +# SERVICEHOME = /var/lib/gnunet/ +# DEFAULTCONFIG = /etc/gnunet.conf +# If 'DEFAULTCONFIG' is not defined, the current +# configuration file is assumed to be the default, +# which is what we want by default... + +[gnunet-nat-server] +HOSTNAME = localhost +PORT = 12345 + +[nat] +# Are we behind NAT? +BEHIND_NAT = YES + +# Is the NAT hole-punched? +PUNCHED_NAT = NO + +# Disable UPNP by default until it gets cleaner! +ENABLE_UPNP = YES + +# Use addresses from the local network interfaces (inluding loopback, but also others) +USE_LOCALADDR = YES + +# External IP address of the NAT box (if known); IPv4 dotted-decimal ONLY at this time (should allow DynDNS!) +# normal interface IP address for non-NATed peers; +# possibly auto-detected (using UPnP) if possible if not specified +# EXTERNAL_ADDRESS = + +# Should we use ICMP-based NAT traversal to try connect to NATed peers +# or, if we are behind NAT, to allow connections to us? +ENABLE_ICMP_CLIENT = YES +ENABLE_ICMP_SERVER = YES + +# IP address of the interface connected to the NAT box; IPv4 dotted-decimal ONLY; +# normal interface IP address for non-NATed peers; +# likely auto-detected (via interface list) if not specified (!) +INTERNAL_ADDRESS = 127.0.0.1 + +# Disable IPv6 support +DISABLEV6 = YES +x diff --git a/src/util/client.c b/src/util/client.c index c81c4eef0..b57b7bb4a 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -527,7 +527,8 @@ receive_helper (void *cls, if (remaining.rel_value == 0) { /* signal timeout! */ - conn->receiver_handler (conn->receiver_handler_cls, NULL); + if (NULL != conn->receiver_handler) + conn->receiver_handler (conn->receiver_handler_cls, NULL); return; } /* back to receive -- either for more data or to call callback! */ @@ -593,7 +594,8 @@ GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *sock, { /* already disconnected, fail instantly! */ GNUNET_break (0); /* this should not happen in well-written code! */ - handler (handler_cls, NULL); + if (NULL != handler) + handler (handler_cls, NULL); return; } sock->receiver_handler = handler; @@ -1009,7 +1011,8 @@ transmit_for_response (void *cls, size_t size, void *buf) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Could not submit request, not expecting to receive a response.\n")); #endif - tc->rn (tc->rn_cls, NULL); + if (NULL != tc->rn) + tc->rn (tc->rn_cls, NULL); GNUNET_free (tc); return 0; } diff --git a/src/util/network.c b/src/util/network.c index e51d7fdab..726e29511 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -219,7 +219,10 @@ GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc, ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); ret->fd = accept (desc->fd, address, address_len); - ret->af = address->sa_family; + if (address != NULL) + ret->af = address->sa_family; + else + ret->af = desc->af; if (ret->fd == INVALID_SOCKET) { #ifdef MINGW @@ -256,7 +259,7 @@ GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc, socket_set_nosigpipe (ret); #endif #ifdef AF_UNIX - if (address->sa_family != AF_UNIX) + if (ret->af != AF_UNIX) #endif socket_set_nodelay (ret); return ret; diff --git a/src/util/program.c b/src/util/program.c index 8fd77637f..c5fe0b573 100644 --- a/src/util/program.c +++ b/src/util/program.c @@ -144,6 +144,8 @@ GNUNET_PROGRAM_run (int argc, }; struct GNUNET_GETOPT_CommandLineOption *allopts; const char *gargs; + char *lpfx; + char *spc; logfile = NULL; gargs = getenv ("GNUNET_ARGS"); @@ -206,11 +208,14 @@ GNUNET_PROGRAM_run (int argc, &cmd_sorter); loglev = GNUNET_strdup ("WARNING"); cc.cfgfile = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE); + lpfx = GNUNET_strdup (binaryName); + if (NULL != (spc = strstr (lpfx, " "))) + *spc = '\0'; if ((-1 == (ret = GNUNET_GETOPT_run (binaryName, allopts, (unsigned int) argc, argv))) || ((GNUNET_OK != - GNUNET_log_setup (binaryName, + GNUNET_log_setup (lpfx, loglev, logfile)) || (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cc.cfgfile)))) @@ -219,9 +224,11 @@ GNUNET_PROGRAM_run (int argc, GNUNET_free_non_null (cc.cfgfile); GNUNET_free (loglev); GNUNET_free (allopts); + GNUNET_free (lpfx); return GNUNET_SYSERR; } GNUNET_free (allopts); + GNUNET_free (lpfx); /* run */ cc.args = &argv[ret];