gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r15890 - gnunet/src/nat


From: gnunet
Subject: [GNUnet-SVN] r15890 - gnunet/src/nat
Date: Fri, 8 Jul 2011 13:30:02 +0200

Author: grothoff
Date: 2011-07-08 13:30:01 +0200 (Fri, 08 Jul 2011)
New Revision: 15890

Modified:
   gnunet/src/nat/nat_mini.c
Log:
mini works

Modified: gnunet/src/nat/nat_mini.c
===================================================================
--- gnunet/src/nat/nat_mini.c   2011-07-08 10:58:56 UTC (rev 15889)
+++ gnunet/src/nat/nat_mini.c   2011-07-08 11:30:01 UTC (rev 15890)
@@ -20,7 +20,7 @@
 
 /**
  * @file nat/nat_mini.c
- * @brief functions for interaction with miniupnp
+ * @brief functions for interaction with miniupnp; tested with miniupnpc 1.5
  * @author Christian Grothoff
  */
 #include "platform.h"
@@ -33,7 +33,6 @@
  */
 #define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
15)
 
-
 /**
  * How long do we give upnpc to remove a mapping?
  */
@@ -42,7 +41,7 @@
 /**
  * How often do we check for changes in the mapping?
  */
-#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 15)
+#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 5)
 
 
 /**
@@ -158,6 +157,11 @@
   int did_map;
 
   /**
+   * Did we find our mapping during refresh scan?
+   */ 
+  int found;
+
+  /**
    * Which port are we mapping?
    */
   uint16_t port;
@@ -177,6 +181,17 @@
 
 
 /**
+ * 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);
+
+
+/**
  * Process the output from 'upnpc -l' to see if our
  * external mapping changed.  If so, do the notifications.
  *
@@ -188,20 +203,105 @@
                        const char *line)
 {
   struct GNUNET_NAT_MiniHandle *mini = cls;
+  char pstr[9];
+  const char *s;
+  unsigned int nport;
+  struct in_addr exip;
 
   if (NULL == line)
     {
       GNUNET_OS_command_stop (mini->refresh_cmd);
       mini->refresh_cmd = NULL;
+      if (mini->found == GNUNET_NO)
+       {
+         /* mapping disappeared, try to re-create */
+         if (mini->did_map)
+           {
+             mini->ac (mini->ac_cls, GNUNET_NO,
+                       (const struct sockaddr*) &mini->current_addr,
+                       sizeof (mini->current_addr));
+             mini->did_map = GNUNET_NO;
+           }
+         GNUNET_snprintf (pstr, sizeof (pstr),
+                          "%u",
+                          (unsigned int) mini->port);
+         mini->map_cmd = GNUNET_OS_command_run (&process_map_output,
+                                                mini,
+                                                MAP_TIMEOUT,
+                                                "upnpc",
+                                                "upnpc",
+                                                "-r", pstr, 
+                                                mini->is_tcp ? "tcp" : "udp",
+                                                NULL);
+         if (NULL != mini->map_cmd)
+           return;
+       }
       mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
                                                         &do_refresh,
                                                         mini);
       return;
     }
-  /* FIXME: parse 'line' */
-  fprintf (stderr,
-          "Refresh output: `%s'\n",
-          line);
+  if (! mini->did_map)
+    return; /* never mapped, won't find our mapping anyway */
+
+  /* we're looking for output of the form:
+     "ExternalIPAddress = 12.134.41.124" */
+
+  s = strstr (line, "ExternalIPAddress = ");
+  if (NULL != s)
+    {
+      s += strlen ("ExternalIPAddress = ");
+      if (1 != inet_pton (AF_INET,
+                         s, &exip))
+       return; /* skip */
+      if (exip.s_addr == mini->current_addr.sin_addr.s_addr)
+       return; /* no change */
+      /* update mapping */
+      mini->ac (mini->ac_cls, GNUNET_NO,
+               (const struct sockaddr*) &mini->current_addr,
+               sizeof (mini->current_addr));
+      mini->current_addr.sin_addr = exip;
+      mini->ac (mini->ac_cls, GNUNET_YES,
+               (const struct sockaddr*) &mini->current_addr,
+               sizeof (mini->current_addr));     
+      return;
+    }
+  /*
+    we're looking for output of the form:
+     
+     "0 TCP  3000->192.168.2.150:3000  'libminiupnpc' ''"
+     "1 UDP  3001->192.168.2.150:3001  'libminiupnpc' ''"
+
+    the pattern we look for is:
+
+     "%s TCP  PORT->STRING:OURPORT *" or
+     "%s UDP  PORT->STRING:OURPORT *"
+  */
+  GNUNET_snprintf (pstr, sizeof (pstr),
+                  ":%u ",
+                  mini->port);
+  if (NULL == (s = strstr (line, "->")))
+    return; /* skip */
+  if (NULL == (s = strstr (s, pstr)))
+    return; /* skip */
+  if (1 != sscanf (line,
+                  (mini->is_tcp) 
+                  ? "%*u TCP  %u->%*s:%*u %*s" 
+                  : "%*u UDP  %u->%*s:%*u %*s",
+                  &nport))
+    return; /* skip */
+  mini->found = GNUNET_YES;
+  if (nport == ntohs (mini->current_addr.sin_port))
+    return; /* no change */    
+
+  /* external port changed, update mapping */
+  mini->ac (mini->ac_cls, GNUNET_NO,
+           (const struct sockaddr*) &mini->current_addr,
+           sizeof (mini->current_addr));
+  mini->current_addr.sin_port = htons ((uint16_t) nport);
+  mini->ac (mini->ac_cls, GNUNET_YES,
+           (const struct sockaddr*) &mini->current_addr,
+           sizeof (mini->current_addr));     
 }
 
 
@@ -218,6 +318,7 @@
   struct GNUNET_NAT_MiniHandle *mini = cls;
 
   mini->refresh_task = GNUNET_SCHEDULER_NO_TASK;
+  mini->found = GNUNET_NO;
   mini->refresh_cmd = GNUNET_OS_command_run (&process_refresh_output,
                                             mini,
                                             MAP_TIMEOUT,
@@ -248,10 +349,9 @@
     {
       GNUNET_OS_command_stop (mini->map_cmd);
       mini->map_cmd = NULL;
-      if (mini->did_map == GNUNET_YES)
-       mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
-                                                          &do_refresh,
-                                                          mini);
+      mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
+                                                        &do_refresh,
+                                                        mini);
       return;
     }
   /*
@@ -263,9 +363,6 @@
        (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);
@@ -275,9 +372,6 @@
                      &mini->current_addr.sin_addr))
     {
       GNUNET_free (ipa);
-      fprintf (stderr,
-              "Skipping output `%s'\n",
-              line);
       return; /* skip line */
     }
   GNUNET_free (ipa);         
@@ -332,7 +426,12 @@
                                        "-r", pstr, 
                                        is_tcp ? "tcp" : "udp",
                                        NULL);
-  
+  if (NULL != ret->map_cmd)
+    return ret;
+  ret->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
+                                                   &do_refresh,
+                                                   ret);
+
   return ret;
 }
 
@@ -396,9 +495,12 @@
   mini->ac (mini->ac_cls, GNUNET_NO,
            (const struct sockaddr*) &mini->current_addr,
            sizeof (mini->current_addr));
+  /* Note: oddly enough, deletion uses the external port whereas
+     addition uses the internal port; this rarely matters since they
+     often are the same, but it might... */
   GNUNET_snprintf (pstr, sizeof (pstr),
                   "%u",
-                  (unsigned int) mini->port);
+                  (unsigned int) mini->current_addr.sin_port);
   mini->unmap_cmd = GNUNET_OS_command_run (&process_unmap_output,
                                           mini,
                                           UNMAP_TIMEOUT,




reply via email to

[Prev in Thread] Current Thread [Next in Thread]