-must notify client on timeout
[oweals/gnunet.git] / src / nat / nat.c
index 69c60291c54b01e2c497b1520c1dbf5213cd8d76..85d069e07e51943d0c5a4f461fc6a3447a55f789 100644 (file)
@@ -710,7 +710,7 @@ process_interfaces (void *cls, const char *name, int isDefault,
     {
       return GNUNET_OK;
     }
-    if (GNUNET_YES == h->use_localaddresses)
+    if ((GNUNET_YES == h->use_localaddresses) || (value != 0))
     {
       add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr,
                               sizeof (struct in_addr));
@@ -907,7 +907,7 @@ start_gnunet_nat_server (struct GNUNET_NAT_Handle *h)
     /* Start the server process */
     binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
     h->server_proc =
-        GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout,
+        GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, NULL,
                                  binary,
                                  "gnunet-helper-nat-server",
                                  h->internal_address, NULL);
@@ -1011,39 +1011,64 @@ resolve_dns (void *cls,
  *     the previous (now invalid) one
  * @param addr either the previous or the new public IP address
  * @param addrlen actual lenght of @a addr
+ * @param ret GNUNET_NAT_ERROR_SUCCESS on success, otherwise an error code
  */
 static void
 upnp_add (void *cls,
           int add_remove,
           const struct sockaddr *addr,
-          socklen_t addrlen)
+          socklen_t addrlen,
+          enum GNUNET_NAT_StatusCode ret)
 {
   struct GNUNET_NAT_Handle *h = cls;
   struct LocalAddressList *pos;
   struct LocalAddressList *next;
 
+
+  if (GNUNET_NAT_ERROR_SUCCESS != ret)
+  {
+    /* Error while running upnp client */
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+          _("Error while running upnp client:\n"));
+
+    //FIXME: convert error code to string
+    
+    return;
+  }
+  
   if (GNUNET_YES == add_remove)
   {
     add_to_address_list (h, LAL_UPNP, addr, addrlen);
     return;
   }
-  /* remove address */
-  next = h->lal_head;
-  while (NULL != (pos = next))
+  else if (GNUNET_NO == add_remove)
   {
-    next = pos->next;
-    if ((pos->source != LAL_UPNP) || (pos->addrlen != addrlen) ||
-        (0 != memcmp (&pos[1], addr, addrlen)))
-      continue;
-    GNUNET_CONTAINER_DLL_remove (h->lal_head, h->lal_tail, pos);
-    if (NULL != h->address_callback)
-      h->address_callback (h->callback_cls, GNUNET_NO,
-                           (const struct sockaddr *) &pos[1], pos->addrlen);
-    GNUNET_free (pos);
-    return;                     /* only remove once */
+    /* remove address */
+    next = h->lal_head;
+    while (NULL != (pos = next))
+    {
+      next = pos->next;
+      if ((pos->source != LAL_UPNP) || (pos->addrlen != addrlen) ||
+          (0 != memcmp (&pos[1], addr, addrlen)))
+        continue;
+      GNUNET_CONTAINER_DLL_remove (h->lal_head, h->lal_tail, pos);
+      if (NULL != h->address_callback)
+        h->address_callback (h->callback_cls, GNUNET_NO,
+                             (const struct sockaddr *) &pos[1], pos->addrlen);
+      GNUNET_free (pos);
+      return;                     /* only remove once */
+    }
+    /* asked to remove address that does not exist */
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Asked to remove unkown address `%s'\n",
+         GNUNET_a2s(addr, addrlen));
+    GNUNET_break (0);
+  }
+  else
+  {
+
+    GNUNET_break (0);
   }
-  /* asked to remove address that does not exist */
-  GNUNET_break (0);
 }
 
 
@@ -1066,9 +1091,19 @@ add_minis (struct GNUNET_NAT_Handle *h,
       return;                   /* already got this port */
     ml = ml->next;
   }
+
   ml = GNUNET_new (struct MiniList);
   ml->port = port;
   ml->mini = GNUNET_NAT_mini_map_start (port, h->is_tcp, &upnp_add, h);
+
+  if (NULL == ml->mini)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+        _("Failed to run upnp client for port %u\n"), ml->port);
+    GNUNET_free (ml);
+    return;
+  }
+
   GNUNET_CONTAINER_DLL_insert (h->mini_head, h->mini_tail, ml);
 }
 
@@ -1106,7 +1141,12 @@ add_from_bind (void *cls,
         add_to_address_list (h, LAL_BINDTO_ADDRESS, sa,
                              sizeof (struct sockaddr_in));
       if (h->enable_upnp)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+            "Running upnp client for address `%s'\n",
+            GNUNET_a2s (sa,sizeof (struct sockaddr_in)));
         add_minis (h, ntohs (v4->sin_port));
+      }
       break;
     case AF_INET6:
       if (sizeof (struct sockaddr_in6) != h->local_addrlens[i])
@@ -1248,6 +1288,16 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
   if (NULL == reversal_callback)
     h->enable_nat_server = GNUNET_NO;
 
+  /* Check for UPnP client, disable immediately if not available */
+  if ( (GNUNET_YES == h->enable_upnp) &&
+       (GNUNET_SYSERR ==
+        GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) )
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+        _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP \n"));
+    h->enable_upnp = GNUNET_NO;
+  }
+
   /* Check if NAT was hole-punched */
   if ((NULL != h->address_callback) &&
       (NULL != h->external_address) &&
@@ -1443,7 +1493,7 @@ GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
        (unsigned int) h->adv_port);
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
   proc =
-      GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL,
+      GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL,
                                binary,
                                "gnunet-helper-nat-client",
                                h->internal_address,
@@ -1510,5 +1560,60 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
   return GNUNET_NO;
 }
 
+/**
+ * Converts enum GNUNET_NAT_StatusCode to a string
+ * 
+ * @param err error code to resolve to a string
+ * @return pointer to a static string containing the error code
+ */
+const char *
+GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
+{
+  switch (err)
+  {
+  case GNUNET_NAT_ERROR_SUCCESS:
+    return _ ("Operation Successful");
+  case GNUNET_NAT_ERROR_IPC_FAILURE:
+    return _ ("Internal Failure (IPC, ...)");
+  case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
+    return _ ("Failure in network subsystem, check permissions.");
+  case GNUNET_NAT_ERROR_TIMEOUT:
+    return _ ("Encountered timeout while performing operation");
+  case GNUNET_NAT_ERROR_NOT_ONLINE:
+    return _ ("detected that we are offline");
+  case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
+    return _ ("`upnpc` command not found");
+  case GNUNET_NAT_ERROR_UPNPC_FAILED:
+    return _ ("Failed to run `upnpc` command");
+  case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
+    return _ ("`upnpc' command took too long, process killed");
+  case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
+    return _ ("`upnpc' command failed to establish port mapping");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
+    return _ ("`external-ip' command not found");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
+    return _ ("Failed to run `external-ip` command");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
+    return _ ("`external-ip' command output invalid");
+  case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
+    return _ ("no valid address was returned by `external-ip'");
+  case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
+    return _ ("Could not determine interface with internal/local network address");
+  case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
+    return _ ("No functioning gnunet-helper-nat-server installation found");
+  case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
+    return _ ("NAT test could not be initialized");
+  case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
+    return _ ("NAT test timeout reached");
+  case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
+    return _ ("could not register NAT");
+  case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
+    return _ ("No working gnunet-helper-nat-client installation found");
+/*  case:
+    return _ ("");*/
+  default:
+    return "unknown status code";
+  }
+}
 
 /* end of nat.c */