[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r15888 - in gnunet/src: include nat util
From: |
gnunet |
Subject: |
[GNUnet-SVN] r15888 - in gnunet/src: include nat util |
Date: |
Fri, 8 Jul 2011 12:23:45 +0200 |
Author: grothoff
Date: 2011-07-08 12:23:45 +0200 (Fri, 08 Jul 2011)
New Revision: 15888
Added:
gnunet/src/nat/test_nat_mini.c
Modified:
gnunet/src/include/gnunet_nat_lib.h
gnunet/src/nat/Makefile.am
gnunet/src/nat/nat_mini.c
gnunet/src/util/os_priority.c
Log:
towards UPnP support
Modified: gnunet/src/include/gnunet_nat_lib.h
===================================================================
--- gnunet/src/include/gnunet_nat_lib.h 2011-07-08 08:04:25 UTC (rev 15887)
+++ gnunet/src/include/gnunet_nat_lib.h 2011-07-08 10:23:45 UTC (rev 15888)
@@ -201,6 +201,44 @@
GNUNET_NAT_mini_get_external_ipv4 (struct in_addr *addr);
+/**
+ * Handle to a mapping created with upnpc.
+ */
+struct GNUNET_NAT_MiniHandle;
+
+
+/**
+ * Start mapping the given port using (mini)upnpc. This function
+ * should typically not be used directly (it is used within the
+ * general-purpose 'GNUNET_NAT_register' code). However, it can be
+ * used if specifically UPnP-based NAT traversal is to be used or
+ * tested.
+ *
+ * @param port port to map
+ * @param is_tcp GNUNET_YES to map TCP, GNUNET_NO for UDP
+ * @param ac function to call with mapping result
+ * @param ac_cls closure for 'ac'
+ * @return NULL on error
+ */
+struct GNUNET_NAT_MiniHandle *
+GNUNET_NAT_mini_map_start (uint16_t port,
+ int is_tcp,
+ GNUNET_NAT_AddressCallback ac,
+ void *ac_cls);
+
+
+/**
+ * Remove a mapping created with (mini)upnpc. Calling
+ * this function will give 'upnpc' 1s to remove tha mapping,
+ * so while this function is non-blocking, a task will be
+ * left with the scheduler for up to 1s past this call.
+ *
+ * @param mini the handle
+ */
+void
+GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini);
+
+
#endif
/* end of gnunet_nat_lib.h */
Modified: gnunet/src/nat/Makefile.am
===================================================================
--- gnunet/src/nat/Makefile.am 2011-07-08 08:04:25 UTC (rev 15887)
+++ gnunet/src/nat/Makefile.am 2011-07-08 10:23:45 UTC (rev 15888)
@@ -57,6 +57,7 @@
check_PROGRAMS = \
test_nat \
+ test_nat_mini \
test_nat_test
if ENABLE_TEST_RUN
@@ -69,7 +70,13 @@
$(top_builddir)/src/nat/libgnunetnat.la \
$(top_builddir)/src/util/libgnunetutil.la
+test_nat_mini_SOURCES = \
+ test_nat_mini.c
+test_nat_mini_LDADD = \
+ $(top_builddir)/src/nat/libgnunetnat.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
test_nat_test_SOURCES = \
test_nat_test.c
test_nat_test_LDADD = \
Modified: gnunet/src/nat/nat_mini.c
===================================================================
--- gnunet/src/nat/nat_mini.c 2011-07-08 08:04:25 UTC (rev 15887)
+++ gnunet/src/nat/nat_mini.c 2011-07-08 10:23:45 UTC (rev 15888)
@@ -28,8 +28,24 @@
#include "gnunet_nat_lib.h"
#include "nat.h"
+/**
+ * How long do we give upnpc to create a mapping?
+ */
+#define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
15)
+
/**
+ * How long do we give upnpc to remove a mapping?
+ */
+#define UNMAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1)
+
+/**
+ * How often do we check for changes in the mapping?
+ */
+#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_MINUTES, 15)
+
+
+/**
* Try to get the external IPv4 address of this peer.
* Note: calling this function may block this process
* for a few seconds (!).
@@ -89,5 +105,322 @@
}
+/**
+ * Handle to a mapping created with upnpc.
+ */
+struct GNUNET_NAT_MiniHandle
+{
+ /**
+ * Function to call on mapping changes.
+ */
+ GNUNET_NAT_AddressCallback ac;
+
+ /**
+ * Closure for 'ac'.
+ */
+ void *ac_cls;
+
+ /**
+ * Command used to install the map.
+ */
+ struct GNUNET_OS_CommandHandle *map_cmd;
+
+ /**
+ * Command used to refresh our map information.
+ */
+ struct GNUNET_OS_CommandHandle *refresh_cmd;
+
+ /**
+ * Command used to remove the mapping.
+ */
+ struct GNUNET_OS_CommandHandle *unmap_cmd;
+
+ /**
+ * Our current external mapping (if we have one).
+ */
+ struct sockaddr_in current_addr;
+
+ /**
+ * We check the mapping periodically to see if it
+ * still works. This task triggers the check.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier refresh_task;
+
+ /**
+ * Are we mapping TCP or UDP?
+ */
+ int is_tcp;
+
+ /**
+ * Did we succeed with creating a mapping?
+ */
+ int did_map;
+
+ /**
+ * Which port are we mapping?
+ */
+ uint16_t port;
+
+};
+
+
+/**
+ * Run upnpc -l to find out if our mapping changed.
+ *
+ * @param cls the 'struct GNUNET_NAT_MiniHandle'
+ * @param tc scheduler context
+ */
+static void
+do_refresh (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Process the output from 'upnpc -l' to see if our
+ * external mapping changed. If so, do the notifications.
+ *
+ * @param cls the 'struct GNUNET_NAT_MiniHandle'
+ * @param line line of output, NULL at the end
+ */
+static void
+process_refresh_output (void *cls,
+ const char *line)
+{
+ struct GNUNET_NAT_MiniHandle *mini = cls;
+ enum GNUNET_OS_ProcessStatusType type;
+ unsigned long code;
+
+ if (NULL == line)
+ {
+ GNUNET_OS_command_stop (mini->refresh_cmd,
+ &type, &code);
+ mini->refresh_cmd = NULL;
+ mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
+ &do_refresh,
+ mini);
+ return;
+ }
+ /* FIXME: parse 'line' */
+ fprintf (stderr,
+ "Refresh output: `%s'\n",
+ line);
+}
+
+
+/**
+ * Run upnpc -l to find out if our mapping changed.
+ *
+ * @param cls the 'struct GNUNET_NAT_MiniHandle'
+ * @param tc scheduler context
+ */
+static void
+do_refresh (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_NAT_MiniHandle *mini = cls;
+
+ mini->refresh_task = GNUNET_SCHEDULER_NO_TASK;
+ mini->refresh_cmd = GNUNET_OS_command_run (&process_refresh_output,
+ mini,
+ MAP_TIMEOUT,
+ "upnpc",
+ "upnpc",
+ "-l",
+ NULL);
+}
+
+
+/**
+ * Process the output from the 'upnpc -r' command.
+ *
+ * @param cls the 'struct GNUNET_NAT_MiniHandle'
+ * @param line line of output, NULL at the end
+ */
+static void
+process_map_output (void *cls,
+ const char *line)
+{
+ struct GNUNET_NAT_MiniHandle *mini = cls;
+ enum GNUNET_OS_ProcessStatusType type;
+ unsigned long code;
+ const char *ipaddr;
+ char *ipa;
+ const char *pstr;
+ unsigned int port;
+
+ if (NULL == line)
+ {
+ GNUNET_OS_command_stop (mini->map_cmd,
+ &type, &code);
+ mini->map_cmd = NULL;
+ if (mini->did_map == GNUNET_YES)
+ mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
+ &do_refresh,
+ mini);
+ return;
+ }
+ /*
+ The upnpc output we're after looks like this:
+
+ "external 87.123.42.204:3000 TCP is redirected to internal
192.168.2.150:3000"
+ */
+ if ( (NULL == (ipaddr = strstr (line, " "))) ||
+ (NULL == (pstr = strstr (ipaddr, ":"))) ||
+ (1 != sscanf (pstr + 1, "%u", &port)) )
+ {
+ fprintf (stderr,
+ "Skipping output `%s'\n",
+ line);
+ return; /* skip line */
+ }
+ ipa = GNUNET_strdup (ipaddr + 1);
+ strstr (ipa, ":")[0] = '\0';
+ if (1 != inet_pton (AF_INET,
+ ipa,
+ &mini->current_addr.sin_addr))
+ {
+ GNUNET_free (ipa);
+ fprintf (stderr,
+ "Skipping output `%s'\n",
+ line);
+ return; /* skip line */
+ }
+ GNUNET_free (ipa);
+
+ mini->current_addr.sin_port = htons (port);
+ mini->current_addr.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ mini->current_addr.sin_len = sizeof (struct sockaddr_in);
+#endif
+ mini->did_map = GNUNET_YES;
+ mini->ac (mini->ac_cls, GNUNET_YES,
+ (const struct sockaddr*) &mini->current_addr,
+ sizeof (mini->current_addr));
+}
+
+
+/**
+ * Start mapping the given port using (mini)upnpc. This function
+ * should typically not be used directly (it is used within the
+ * general-purpose 'GNUNET_NAT_register' code). However, it can be
+ * used if specifically UPnP-based NAT traversal is to be used or
+ * tested.
+ *
+ * @param port port to map
+ * @param is_tcp GNUNET_YES to map TCP, GNUNET_NO for UDP
+ * @param ac function to call with mapping result
+ * @param ac_cls closure for 'ac'
+ * @return NULL on error
+ */
+struct GNUNET_NAT_MiniHandle *
+GNUNET_NAT_mini_map_start (uint16_t port,
+ int is_tcp,
+ GNUNET_NAT_AddressCallback ac,
+ void *ac_cls)
+{
+ struct GNUNET_NAT_MiniHandle *ret;
+ char pstr[6];
+
+ ret = GNUNET_malloc (sizeof (struct GNUNET_NAT_MiniHandle));
+ ret->ac = ac;
+ ret->ac_cls = ac_cls;
+ ret->is_tcp = is_tcp;
+ ret->port = port;
+ GNUNET_snprintf (pstr, sizeof (pstr),
+ "%u",
+ (unsigned int) port);
+ ret->map_cmd = GNUNET_OS_command_run (&process_map_output,
+ ret,
+ MAP_TIMEOUT,
+ "upnpc",
+ "upnpc",
+ "-r", pstr,
+ is_tcp ? "tcp" : "udp",
+ NULL);
+
+ return ret;
+}
+
+
+/**
+ * Process output from our 'unmap' command.
+ *
+ * @param cls the 'struct GNUNET_NAT_MiniHandle'
+ * @param line line of output, NULL at the end
+ */
+static void
+process_unmap_output (void *cls,
+ const char *line)
+{
+ struct GNUNET_NAT_MiniHandle *mini = cls;
+ enum GNUNET_OS_ProcessStatusType type;
+ unsigned long code;
+
+ if (NULL == line)
+ {
+ GNUNET_OS_command_stop (mini->unmap_cmd,
+ &type, &code);
+ mini->unmap_cmd = NULL;
+ GNUNET_free (mini);
+ return;
+ }
+ /* we don't really care about the output... */
+}
+
+
+/**
+ * Remove a mapping created with (mini)upnpc. Calling
+ * this function will give 'upnpc' 1s to remove tha mapping,
+ * so while this function is non-blocking, a task will be
+ * left with the scheduler for up to 1s past this call.
+ *
+ * @param mini the handle
+ */
+void
+GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini)
+{
+ char pstr[6];
+ enum GNUNET_OS_ProcessStatusType type;
+ unsigned long code;
+
+ if (! mini->did_map)
+ {
+ if (mini->map_cmd != NULL)
+ {
+ GNUNET_OS_command_stop (mini->map_cmd,
+ &type, &code);
+ mini->map_cmd = NULL;
+ }
+ GNUNET_free (mini);
+ return;
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != mini->refresh_task)
+ {
+ GNUNET_SCHEDULER_cancel (mini->refresh_task);
+ mini->refresh_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (mini->refresh_cmd != NULL)
+ {
+ GNUNET_OS_command_stop (mini->refresh_cmd,
+ &type, &code);
+ mini->refresh_cmd = NULL;
+ }
+ mini->ac (mini->ac_cls, GNUNET_NO,
+ (const struct sockaddr*) &mini->current_addr,
+ sizeof (mini->current_addr));
+ GNUNET_snprintf (pstr, sizeof (pstr),
+ "%u",
+ (unsigned int) mini->port);
+ mini->unmap_cmd = GNUNET_OS_command_run (&process_unmap_output,
+ mini,
+ UNMAP_TIMEOUT,
+ "upnpc",
+ "upnpc",
+ "-d", pstr,
+ mini->is_tcp ? "tcp" : "udp",
+ NULL);
+}
+
+
/* end of nat_mini.c */
Added: gnunet/src/nat/test_nat_mini.c
===================================================================
--- gnunet/src/nat/test_nat_mini.c (rev 0)
+++ gnunet/src/nat/test_nat_mini.c 2011-07-08 10:23:45 UTC (rev 15888)
@@ -0,0 +1,142 @@
+/*
+ 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 port redirection and public IP address retrieval.
+ * This test never fails, because there need to be a NAT box set up for tha *
+ * @file nat/test_nat_mini.c
+ * @brief Testcase for NAT library - mini
+ * @author Christian Grothoff
+ *
+ * TODO: actually use ARM to start resolver service to make DNS work!
+ */
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_scheduler_lib.h"
+#include "gnunet_nat_lib.h"
+
+
+#define VERBOSE GNUNET_YES
+
+
+/* Time to wait before stopping NAT, in seconds */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
+
+
+
+
+
+/**
+ * Function called on each address that the NAT service
+ * believes to be valid for the transport.
+ */
+static void
+addr_callback (void *cls, int add_remove,
+ const struct sockaddr *addr, socklen_t addrlen)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Address changed: %s `%s' (%u bytes)\n",
+ add_remove == GNUNET_YES ? "added" : "removed",
+ GNUNET_a2s (addr, addrlen),
+ (unsigned int) addrlen);
+}
+
+
+/**
+ * Function that terminates the test.
+ */
+static void
+stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_NAT_MiniHandle *mini = cls;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Stopping NAT and quitting...\n");
+ GNUNET_NAT_mini_map_stop (mini);
+}
+
+#define PORT 10000
+
+/**
+ * Main function run with scheduler.
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_NAT_MiniHandle *mini;
+
+ GNUNET_log_setup ("test-nat-mini", "DEBUG", NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Requesting NAT redirection for port %u...\n",
+ PORT);
+ mini = GNUNET_NAT_mini_map_start (PORT,
+ GNUNET_YES /* tcp */,
+ &addr_callback, NULL);
+ if (NULL == mini)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Could not start UPnP interaction\n");
+ return;
+ }
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, mini);
+}
+
+
+int
+main (int argc, char *const argv[])
+{
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ char *const argv_prog[] = {
+ "test-nat-mini",
+ "-c",
+ "test_nat_data.conf",
+ "-L",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL
+ };
+
+ GNUNET_log_setup ("test-nat-mini",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "UPnP test for NAT library, timeout set to %d seconds\n",
TIMEOUT);
+ GNUNET_PROGRAM_run (5, argv_prog, "test-nat-mini",
+ "nohelp", options, &run, NULL);
+ return 0;
+}
+
+/* end of test_nat_mini.c */
Modified: gnunet/src/util/os_priority.c
===================================================================
--- gnunet/src/util/os_priority.c 2011-07-08 08:04:25 UTC (rev 15887)
+++ gnunet/src/util/os_priority.c 2011-07-08 10:23:45 UTC (rev 15888)
@@ -1075,6 +1075,7 @@
#endif
}
+
/**
* Retrieve the status of a process
* @param proc process ID
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r15888 - in gnunet/src: include nat util,
gnunet <=