stuff
[oweals/gnunet.git] / src / transport / plugin_transport_http.c
index a7e5a338caa3cbfe8dd984a9dd66ebaad54af4d0..e63549784728e1842e1920f04f4d1feff41e9cd8 100644 (file)
  */
 #define HTTP_CONNECT_TIMEOUT 30
 
-
 /**
  * Network format for IPv4 addresses.
  */
 struct IPv4HttpAddress
 {
-  /**
-   * Linked list next
-   */
-  struct IPv4HttpAddress * next;
-
-  /**
-   * Linked list previous
-   */
-  struct IPv4HttpAddress * prev;
-
   /**
    * IPv4 address, in network byte order.
    */
@@ -114,26 +103,32 @@ struct IPv4HttpAddress
   /**
    * Port number, in network byte order.
    */
-  uint16_t u_port GNUNET_PACKED;
-
+  uint16_t port GNUNET_PACKED;
 };
 
-
 /**
- * Network format for IPv6 addresses.
+ * Wrapper to manage IPv4 addresses
  */
-struct IPv6HttpAddress
+struct IPv4HttpAddressWrapper
 {
   /**
    * Linked list next
    */
-  struct IPv6HttpAddress * next;
+  struct IPv4HttpAddressWrapper * next;
 
   /**
    * Linked list previous
    */
-  struct IPv6HttpAddress * prev;
+  struct IPv4HttpAddressWrapper * prev;
+
+  struct IPv4HttpAddress * addr;
+};
 
+/**
+ * Network format for IPv6 addresses.
+ */
+struct IPv6HttpAddress
+{
   /**
    * IPv6 address.
    */
@@ -142,10 +137,27 @@ struct IPv6HttpAddress
   /**
    * Port number, in network byte order.
    */
-  uint16_t u6_port GNUNET_PACKED;
+  uint16_t port GNUNET_PACKED;
 
 };
 
+/**
+ * Wrapper for IPv4 addresses.
+ */
+struct IPv6HttpAddressWrapper
+{
+  /**
+   * Linked list next
+   */
+  struct IPv6HttpAddressWrapper * next;
+
+  /**
+   * Linked list previous
+   */
+  struct IPv6HttpAddressWrapper * prev;
+
+  struct IPv6HttpAddress * addr;
+};
 
 /**
  *  Message to send using http
@@ -421,22 +433,22 @@ struct Plugin
   /**
    * ipv4 DLL head
    */
-  struct IPv4HttpAddress * ipv4_addr_head;
+  struct IPv4HttpAddressWrapper * ipv4_addr_head;
 
   /**
    * ipv4 DLL tail
    */
-  struct IPv4HttpAddress * ipv4_addr_tail;
+  struct IPv4HttpAddressWrapper * ipv4_addr_tail;
 
   /**
    * ipv6 DLL head
    */
-  struct IPv6HttpAddress * ipv6_addr_head;
+  struct IPv6HttpAddressWrapper * ipv6_addr_head;
 
   /**
    * ipv6 DLL tail
    */
-  struct IPv6HttpAddress * ipv6_addr_tail;
+  struct IPv6HttpAddressWrapper * ipv6_addr_tail;
 
   /**
    * Our ASCII encoded, hashed peer identity
@@ -502,6 +514,27 @@ struct Plugin
 #endif
 };
 
+/**
+ * Context for address to string conversion.
+ */
+struct PrettyPrinterContext
+{
+  /**
+   * Function to call with the result.
+   */
+  GNUNET_TRANSPORT_AddressStringCallback asc;
+
+  /**
+   * Clsoure for 'asc'.
+   */
+  void *asc_cls;
+
+  /**
+   * Port to add after the IP address.
+   */
+  uint16_t port;
+};
+
 
 /**
  * Function called for a quick conversion of the binary address to
@@ -631,7 +664,10 @@ remove_peer_context_Iterator (void *cls,
              "Freeing context for peer `%s'\n",
              GNUNET_i2s(&pc->identity));
 #endif
-  GNUNET_CONTAINER_multihashmap_remove (plugin->peers, &pc->identity.hashPubKey, pc);
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_remove (plugin->peers, 
+                                                      &pc->identity.hashPubKey, 
+                                                      pc));
   while (ps!=NULL)
     {
       plugin->env->session_end(plugin, &pc->identity, ps);
@@ -746,6 +782,8 @@ remove_session (struct HTTP_PeerContext * pc,
   return GNUNET_OK;
 }
 
+
+#if 0
 static int check_localaddress (const struct sockaddr *addr, socklen_t addrlen)
 {
        uint32_t res = 0;
@@ -785,6 +823,7 @@ static int check_localaddress (const struct sockaddr *addr, socklen_t addrlen)
        return local;
 }
 
+
 /**
  * Add the IP of our network interface to the list of
  * our external IP addresses.
@@ -834,7 +873,7 @@ process_interfaces (void *cls,
 
 
       t4->ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
-      t4->u_port = htons (plugin->port_inbound);
+      t4->port = htons (plugin->port_inbound);
       if (plugin->bind4_address != NULL) {
        if (0 == memcmp(&plugin->bind4_address->sin_addr, &bnd_cmp, sizeof (struct in_addr)))
          {
@@ -875,7 +914,7 @@ process_interfaces (void *cls,
              memcpy (&t6->ipv6_addr,
                      &((struct sockaddr_in6 *) addr)->sin6_addr,
                      sizeof (struct in6_addr));
-             t6->u6_port = htons (plugin->port_inbound);
+             t6->port = htons (plugin->port_inbound);
              plugin->env->notify_address(plugin->env->cls,
                                          GNUNET_YES,
                                          t6, sizeof (struct IPv6HttpAddress));
@@ -890,7 +929,7 @@ process_interfaces (void *cls,
       memcpy (&t6->ipv6_addr,
                  &((struct sockaddr_in6 *) addr)->sin6_addr,
                  sizeof (struct in6_addr));
-      t6->u6_port = htons (plugin->port_inbound);
+      t6->port = htons (plugin->port_inbound);
       GNUNET_CONTAINER_DLL_insert(plugin->ipv6_addr_head,plugin->ipv6_addr_tail,t6);
 
       plugin->env->notify_address(plugin->env->cls,
@@ -899,7 +938,7 @@ process_interfaces (void *cls,
   }
   return GNUNET_OK;
 }
-
+#endif
 
 /**
  * External logging function for MHD
@@ -986,10 +1025,11 @@ mhd_write_mst_cb (void *cls,
                  const struct GNUNET_MessageHeader *message)
 {
   struct Session *ps  = cls; 
-  struct HTTP_PeerContext *pc = ps->peercontext;
+  struct HTTP_PeerContext *pc;
   struct GNUNET_TIME_Relative delay;
 
   GNUNET_assert(ps != NULL);
+  pc = ps->peercontext;
   GNUNET_assert(pc != NULL);
 #if DEBUG_HTTP
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1230,7 +1270,7 @@ mhd_access_cb (void *cls,
          addrin = (const struct sockaddr_in*) client_addr;
          inet_ntop(addrin->sin_family, &(addrin->sin_addr),address,INET_ADDRSTRLEN);
          memcpy(&ipv4addr.ipv4_addr,&(addrin->sin_addr),sizeof(struct in_addr));
-         ipv4addr.u_port = addrin->sin_port;
+         ipv4addr.port = addrin->sin_port;
          addr = &ipv4addr;
          addr_len = sizeof(struct IPv4HttpAddress);
        }
@@ -1240,7 +1280,7 @@ mhd_access_cb (void *cls,
          addrin6 = (const struct sockaddr_in6 *) client_addr;
          inet_ntop(addrin6->sin6_family, &(addrin6->sin6_addr),address,INET6_ADDRSTRLEN);
          memcpy(&ipv6addr.ipv6_addr,&(addrin6->sin6_addr),sizeof(struct in6_addr));
-         ipv6addr.u6_port = addrin6->sin6_port;
+         ipv6addr.port = addrin6->sin6_port;
          addr = &ipv6addr;
          addr_len = sizeof(struct IPv6HttpAddress);
        }
@@ -2573,7 +2613,7 @@ http_plugin_send (void *cls,
          ps->send_force_disconnect = GNUNET_NO;
          ps->pending_msgs_head = NULL;
          ps->pending_msgs_tail = NULL;
-         ps->peercontext=pc;
+         ps->peercontext = pc;
          ps->session_id = pc->session_id_counter;
          ps->queue_length_cur = 0;
          ps->queue_length_max = GNUNET_SERVER_MAX_MESSAGE_SIZE;
@@ -2686,6 +2726,32 @@ http_plugin_disconnect (void *cls,
 }
 
 
+/**
+ * Append our port and forward the result.
+ *
+ * @param cls the 'struct PrettyPrinterContext*'
+ * @param hostname hostname part of the address
+ */
+static void
+append_port (void *cls, const char *hostname)
+{
+  struct PrettyPrinterContext *ppc = cls;
+  char *ret;
+
+  if (hostname == NULL)
+    {
+      ppc->asc (ppc->asc_cls, NULL);
+      GNUNET_free (ppc);
+      return;
+    }
+  GNUNET_asprintf (&ret, "%s://%s:%d", PROTOCOL_PREFIX, hostname, ppc->port);
+
+  ppc->asc (ppc->asc_cls, ret);
+  GNUNET_free (ret);
+}
+
+
+
 /**
  * Convert the transports address to a nice, human-readable
  * format.
@@ -2710,31 +2776,38 @@ http_plugin_address_pretty_printer (void *cls,
                                         GNUNET_TRANSPORT_AddressStringCallback
                                         asc, void *asc_cls)
 {
+  struct PrettyPrinterContext *ppc;
+  const void *sb;
+  size_t sbs;
+  struct sockaddr_in  a4;
+  struct sockaddr_in6 a6;
   const struct IPv4HttpAddress *t4;
   const struct IPv6HttpAddress *t6;
-  struct sockaddr_in a4;
-  struct sockaddr_in6 a6;
-  char * address;
-  char * ret;
-  unsigned int port;
-  unsigned int res;
+  uint16_t port;
 
-  GNUNET_assert(cls !=NULL);
   if (addrlen == sizeof (struct IPv6HttpAddress))
     {
-      address = GNUNET_malloc (INET6_ADDRSTRLEN);
       t6 = addr;
-      a6.sin6_addr = t6->ipv6_addr;
-      inet_ntop(AF_INET6, &(a6.sin6_addr),address,INET6_ADDRSTRLEN);
-      port = ntohs(t6->u6_port);
+      memset (&a6, 0, sizeof (a6));
+      a6.sin6_family = AF_INET6;
+      a6.sin6_port = t6->port;
+      memcpy (&a6.sin6_addr,
+              &t6->ipv6_addr,
+              sizeof (struct in6_addr));
+      port = ntohs (t6->port);
+      sb = &a6;
+      sbs = sizeof (a6);
     }
   else if (addrlen == sizeof (struct IPv4HttpAddress))
     {
-      address = GNUNET_malloc (INET_ADDRSTRLEN);
       t4 = addr;
-      a4.sin_addr.s_addr =  t4->ipv4_addr;
-      inet_ntop(AF_INET, &(a4.sin_addr),address,INET_ADDRSTRLEN);
-      port = ntohs(t4->u_port);
+      memset (&a4, 0, sizeof (a4));
+      a4.sin_family = AF_INET;
+      a4.sin_port = t4->port;
+      a4.sin_addr.s_addr = t4->ipv4_addr;
+      port = ntohs (t4->ipv4_addr);
+      sb = &a4;
+      sbs = sizeof (a4);
     }
   else
     {
@@ -2743,11 +2816,13 @@ http_plugin_address_pretty_printer (void *cls,
       asc (asc_cls, NULL);
       return;
     }
-  res = GNUNET_asprintf(&ret,"%s://%s:%u/", PROTOCOL_PREFIX, address, port);
-  GNUNET_free (address);
-  GNUNET_assert(res != 0);
-  asc (asc_cls, ret);
-  GNUNET_free_non_null (ret);
+  ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
+  ppc->asc = asc;
+  ppc->asc_cls = asc_cls;
+  ppc->port = port;
+  GNUNET_RESOLVER_hostname_get (sb,
+                                sbs,
+                                !numeric, timeout, &append_port, ppc);
 }
 
 
@@ -2771,8 +2846,8 @@ http_plugin_address_suggested (void *cls,
   struct Plugin *plugin = cls;
   struct IPv4HttpAddress *v4;
   struct IPv6HttpAddress *v6;
-  struct IPv4HttpAddress *tv4 = plugin->ipv4_addr_head;
-  struct IPv6HttpAddress *tv6 = plugin->ipv6_addr_head;
+  struct IPv4HttpAddressWrapper *w_tv4 = plugin->ipv4_addr_head;
+  struct IPv6HttpAddressWrapper *w_tv6 = plugin->ipv6_addr_head;
 
   GNUNET_assert(cls !=NULL);
   if ((addrlen != sizeof (struct IPv4HttpAddress)) &&
@@ -2788,13 +2863,13 @@ http_plugin_address_suggested (void *cls,
          else
            return GNUNET_SYSERR;
        }
-      while (tv4!=NULL)
+      while (w_tv4!=NULL)
        {
-         if (0==memcmp (&tv4->ipv4_addr, &v4->ipv4_addr, sizeof(uint32_t)))
+         if (0==memcmp (&w_tv4->addr->ipv4_addr, &v4->ipv4_addr, sizeof(uint32_t)))
            break;
-         tv4 = tv4->next;
+         w_tv4 = w_tv4->next;
        }
-      if (tv4 != NULL)
+      if (w_tv4 != NULL)
         return GNUNET_OK;
       else
        return GNUNET_SYSERR;
@@ -2809,13 +2884,13 @@ http_plugin_address_suggested (void *cls,
          else
            return GNUNET_SYSERR;
        }
-      while (tv6!=NULL)
+      while (w_tv6!=NULL)
        {
-         if (0 == memcmp (&tv6->ipv6_addr, &v6->ipv6_addr, sizeof(struct in6_addr)))
+         if (0 == memcmp (&w_tv6->addr->ipv6_addr, &v6->ipv6_addr, sizeof(struct in6_addr)))
            break;
-         tv6 = tv6->next;
+         w_tv6 = w_tv6->next;
        }
-      if (tv6 !=NULL)
+      if (w_tv6 !=NULL)
         return GNUNET_OK;
       else
        return GNUNET_SYSERR;
@@ -2855,7 +2930,7 @@ http_plugin_address_to_string (void *cls,
       t6 = addr;
       a6.sin6_addr = t6->ipv6_addr;
       inet_ntop(AF_INET6, &(a6.sin6_addr),address,INET6_ADDRSTRLEN);
-      port = ntohs(t6->u6_port);
+      port = ntohs(t6->port);
     }
   else if (addrlen == sizeof (struct IPv4HttpAddress))
     {
@@ -2863,7 +2938,7 @@ http_plugin_address_to_string (void *cls,
       t4 = addr;
       a4.sin_addr.s_addr =  t4->ipv4_addr;
       inet_ntop(AF_INET, &(a4.sin_addr),address,INET_ADDRSTRLEN);
-      port = ntohs(t4->u_port);
+      port = ntohs(t4->port);
     }
   else
     {
@@ -2899,131 +2974,184 @@ try_connection_reversal (void *cls,
 
 }
 
-/**
- * Our external IP address/port mapping has changed.
- *
- * @param cls closure, the 'struct LocalAddrList'
- * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
- *     the previous (now invalid) one
- * @param addr either the previous or the new public IP address
- * @param addrlen actual lenght of the address
- */
 static void
-tcp_nat_port_map_callback (void *cls,
-                           int add_remove,
-                           const struct sockaddr *addr,
-                           socklen_t addrlen)
+tcp_nat_cb_add_addr (void *cls,
+                         int add_remove,
+                         const struct sockaddr *addr,
+                         socklen_t addrlen)
 {
   struct Plugin *plugin = cls;
-  struct IPv4HttpAddress *t4;
-  struct IPv6HttpAddress *t6;
-  void *arg;
-  size_t args;
+  struct IPv4HttpAddress * t4 = NULL;
+  struct IPv4HttpAddressWrapper * w_t4 = NULL;
+  struct IPv6HttpAddress * t6 = NULL;
+  struct IPv6HttpAddressWrapper * w_t6 = NULL;
   int af;
 
+  af = addr->sa_family;
+  switch (af)
+  {
+  case AF_INET:
+    w_t4 = plugin->ipv4_addr_head;
+    while (w_t4 != NULL)
+    {
+      int res = memcmp(&w_t4->addr->ipv4_addr,
+                       &((struct sockaddr_in *) addr)->sin_addr,
+                       sizeof (struct in_addr));
+      if (0 == res)
+        break;
+      w_t4 = w_t4->next;
+    }
+    if (w_t4 == NULL)
+    {
+      w_t4 = GNUNET_malloc(sizeof(struct IPv4HttpAddressWrapper));
+      t4 = GNUNET_malloc(sizeof(struct IPv4HttpAddress));
+      memcpy (&t4->ipv4_addr,
+            &((struct sockaddr_in *) addr)->sin_addr,
+            sizeof (struct in_addr));
+      t4->port = htons (plugin->port_inbound);
 
-  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
-                   "tcp",
-                   "NPMC called with %d for address `%s'\n",
-                   add_remove,
-                   GNUNET_a2s (addr, addrlen));
-  /* convert 'addr' to our internal format */
+      w_t4->addr = t4;
 
-  GNUNET_assert(cls !=NULL);
-  af = addr->sa_family;
-  if ((af == AF_INET) &&
-      (plugin->use_ipv4 == GNUNET_YES) &&
-      (plugin->bind6_address == NULL) ) {
+      GNUNET_CONTAINER_DLL_insert(plugin->ipv4_addr_head,
+                                  plugin->ipv4_addr_tail,w_t4);
+    }
+    plugin->env->notify_address(plugin->env->cls,
+                                add_remove,
+                                w_t4->addr, sizeof (struct IPv4HttpAddress));
 
-          struct in_addr bnd_cmp = ((struct sockaddr_in *) addr)->sin_addr;
-      t4 = GNUNET_malloc(sizeof(struct IPv4HttpAddress));
-     // Not skipping loopback addresses
+    break;
+  case AF_INET6:
+    w_t6 = plugin->ipv6_addr_head;
+    while (w_t6)
+    {
+      int res = memcmp(&w_t6->addr->ipv6_addr,
+                       &((struct sockaddr_in6 *) addr)->sin6_addr,
+                       sizeof (struct in6_addr));
+      if (0 == res)
+        break;
+      w_t6 = w_t6->next;
+    }
+    if (w_t6 == NULL)
+    {
+    w_t6 = GNUNET_malloc(sizeof(struct IPv6HttpAddressWrapper));
+    t6 = GNUNET_malloc(sizeof(struct IPv6HttpAddress));
 
+    memcpy (&t6->ipv6_addr,
+            &((struct sockaddr_in6 *) addr)->sin6_addr,
+            sizeof (struct in6_addr));
+    t6->port = htons (plugin->port_inbound);
 
-      t4->ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
-      t4->u_port = htons (plugin->port_inbound);
-      if (plugin->bind4_address != NULL) {
-        if (0 == memcmp(&plugin->bind4_address->sin_addr, &bnd_cmp, sizeof (struct in_addr)))
-          {
-            GNUNET_CONTAINER_DLL_insert(plugin->ipv4_addr_head,
-                                        plugin->ipv4_addr_tail,t4);
-                  plugin->env->notify_address(plugin->env->cls,
-                                              GNUNET_YES,
-                                              t4, sizeof (struct IPv4HttpAddress));
-            return;
-          }
-        GNUNET_free (t4);
-        return;
-      }
-      else
-          {
-          GNUNET_CONTAINER_DLL_insert (plugin->ipv4_addr_head,
-                                       plugin->ipv4_addr_tail,
-                                       t4);
-          plugin->env->notify_address(plugin->env->cls,
-                                      GNUNET_YES,
-                                      t4, sizeof (struct IPv4HttpAddress));
-          return;
-          }
-   }
-   if ((af == AF_INET6) &&
-            (plugin->use_ipv6 == GNUNET_YES) &&
-            (plugin->bind4_address == NULL) ) {
+    w_t6->addr = t6;
 
-          struct in6_addr bnd_cmp6 = ((struct sockaddr_in6 *) addr)->sin6_addr;
+    GNUNET_CONTAINER_DLL_insert(plugin->ipv6_addr_head,
+                                plugin->ipv6_addr_tail,w_t6);
+    }
+    plugin->env->notify_address(plugin->env->cls,
+                                add_remove,
+                                w_t6->addr, sizeof (struct IPv6HttpAddress));
+    break;
+  default:
+    return;
+  }
 
-      t6 = GNUNET_malloc(sizeof(struct IPv6HttpAddress));
-      GNUNET_assert(t6 != NULL);
+}
 
-      if (plugin->bind6_address != NULL) {
-          if (0 == memcmp(&plugin->bind6_address->sin6_addr,
-                                                  &bnd_cmp6,
-                                                 sizeof (struct in6_addr))) {
-              memcpy (&t6->ipv6_addr,
-                      &((struct sockaddr_in6 *) addr)->sin6_addr,
-                      sizeof (struct in6_addr));
-              t6->u6_port = htons (plugin->port_inbound);
-              plugin->env->notify_address(plugin->env->cls,
-                                          GNUNET_YES,
-                                          t6, sizeof (struct IPv6HttpAddress));
-              GNUNET_CONTAINER_DLL_insert(plugin->ipv6_addr_head,
-                                          plugin->ipv6_addr_tail,
-                                          t6);
-              return;
-              }
-          GNUNET_free (t6);
-          return;
-          }
-      memcpy (&t6->ipv6_addr,
-                  &((struct sockaddr_in6 *) addr)->sin6_addr,
-                  sizeof (struct in6_addr));
-      t6->u6_port = htons (plugin->port_inbound);
-      GNUNET_CONTAINER_DLL_insert(plugin->ipv6_addr_head,plugin->ipv6_addr_tail,t6);
+static void
+tcp_nat_cb_remove_addr (void *cls,
+                         int add_remove,
+                         const struct sockaddr *addr,
+                         socklen_t addrlen)
+{
+  struct Plugin *plugin = cls;
+  struct IPv4HttpAddressWrapper * w_t4 = NULL;
+  struct IPv6HttpAddressWrapper * w_t6 = NULL;
+  int af;
 
+  af = addr->sa_family;
+  switch (af)
+  {
+  case AF_INET:
+    w_t4 = plugin->ipv4_addr_head;
+      while (w_t4 != NULL)
+      {
+        int res = memcmp(&w_t4->addr->ipv4_addr,
+                         &((struct sockaddr_in *) addr)->sin_addr,
+                         sizeof (struct in_addr));
+        if (0 == res)
+          break;
+        w_t4 = w_t4->next;
+      }
+      if (w_t4 == NULL)
+        return;
       plugin->env->notify_address(plugin->env->cls,
-                                  GNUNET_YES,
-                                  t6, sizeof (struct IPv6HttpAddress));
-   }
+                                add_remove,
+                                w_t4->addr, sizeof (struct IPv4HttpAddress));
+
+      GNUNET_CONTAINER_DLL_remove(plugin->ipv4_addr_head,
+                                  plugin->ipv4_addr_tail,w_t4);
+      GNUNET_free (w_t4->addr);
+      GNUNET_free (w_t4);
+    break;
+  case AF_INET6:
+    w_t6 = plugin->ipv6_addr_head;
+    while (w_t6 != NULL)
+    {
+      int res = memcmp(&w_t6->addr->ipv6_addr,
+                       &((struct sockaddr_in6 *) addr)->sin6_addr,
+                       sizeof (struct in6_addr));
+      if (0 == res)
+        break;
+      w_t6 = w_t6->next;
+    }
+    if (w_t6 == NULL)
+      return;
+    plugin->env->notify_address(plugin->env->cls,
+                              add_remove,
+                              w_t6->addr, sizeof (struct IPv6HttpAddress));
+
+    GNUNET_CONTAINER_DLL_remove(plugin->ipv6_addr_head,
+                                plugin->ipv6_addr_tail,w_t6);
+    GNUNET_free (w_t6->addr);
+    GNUNET_free (w_t6);
+    break;
+  default:
+    return;
+  }
 
-  /* modify our published address list */
-  plugin->env->notify_address (plugin->env->cls,
-                               add_remove,
-                               arg, args);
 }
 
 /**
- * Notify transport service about address
+ * Our external IP address/port mapping has changed.
  *
- * @param cls the plugin
- * @param tc unused
+ * @param cls closure, the 'struct LocalAddrList'
+ * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
+ *     the previous (now invalid) one
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual lenght of the address
  */
 static void
-address_notification (void *cls,
-                    const struct GNUNET_SCHEDULER_TaskContext *tc)
+tcp_nat_port_map_callback (void *cls,
+                           int add_remove,
+                           const struct sockaddr *addr,
+                           socklen_t addrlen)
 {
-  struct Plugin *plugin = cls;
-
-  GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
+  GNUNET_assert(cls !=NULL );
+#if DEBUG_HTTP
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                   "NPMC called to %s address `%s'\n",
+                   (add_remove == GNUNET_YES) ? "remove" : "add",
+                   GNUNET_a2s (addr, addrlen));
+#endif
+  /* convert 'addr' to our internal format */
+  switch (add_remove)
+  {
+  case GNUNET_YES:
+    tcp_nat_cb_add_addr (cls, add_remove, addr, addrlen);
+    break;
+  case GNUNET_NO:
+    tcp_nat_cb_remove_addr (cls, add_remove, addr, addrlen);
+    break;
+  }
 }
 
 /**
@@ -3035,10 +3163,13 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
   CURLMcode mret;
-  struct IPv4HttpAddress * ipv4addr;
-  struct IPv6HttpAddress * ipv6addr;
+  struct IPv4HttpAddressWrapper * w_t4;
+  struct IPv6HttpAddressWrapper * w_t6;
   GNUNET_assert(cls !=NULL);
 
+  if (plugin->nat != NULL)
+    GNUNET_NAT_unregister (plugin->nat);
+
   if (plugin->http_server_daemon_v4 != NULL)
     {
       MHD_stop_daemon (plugin->http_server_daemon_v4);
@@ -3059,19 +3190,21 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
       GNUNET_SCHEDULER_cancel(plugin->http_server_task_v6);
       plugin->http_server_task_v6 = GNUNET_SCHEDULER_NO_TASK;
     }
-  
+
   while (plugin->ipv4_addr_head!=NULL)
     {
-      ipv4addr = plugin->ipv4_addr_head;
-      GNUNET_CONTAINER_DLL_remove(plugin->ipv4_addr_head,plugin->ipv4_addr_tail,ipv4addr);
-      GNUNET_free(ipv4addr);
+      w_t4 = plugin->ipv4_addr_head;
+      GNUNET_CONTAINER_DLL_remove(plugin->ipv4_addr_head,plugin->ipv4_addr_tail,w_t4);
+      GNUNET_free(w_t4->addr);
+      GNUNET_free(w_t4);
     }
   
   while (plugin->ipv6_addr_head!=NULL)
     {
-      ipv6addr = plugin->ipv6_addr_head;
-      GNUNET_CONTAINER_DLL_remove(plugin->ipv6_addr_head,plugin->ipv6_addr_tail,ipv6addr);
-      GNUNET_free(ipv6addr);
+      w_t6 = plugin->ipv6_addr_head;
+      GNUNET_CONTAINER_DLL_remove(plugin->ipv6_addr_head,plugin->ipv6_addr_tail,w_t6);
+      GNUNET_free(w_t6->addr);
+      GNUNET_free(w_t6);
     }
   
   /* free all peer information */
@@ -3098,12 +3231,10 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
       plugin->http_curl_task = GNUNET_SCHEDULER_NO_TASK;
     }
   
-  if (plugin->nat != NULL)
-    GNUNET_NAT_unregister (plugin->nat);
 
   GNUNET_free_non_null (plugin->bind4_address);
   GNUNET_free_non_null (plugin->bind6_address);
-  GNUNET_free_non_null(plugin->bind_hostname);
+  GNUNET_free_non_null (plugin->bind_hostname);
 #if BUILD_HTTPS
   GNUNET_free_non_null (plugin->crypto_init);
   GNUNET_free_non_null (plugin->cert);
@@ -3127,8 +3258,8 @@ load_certificate( const char * file )
   struct stat fstat;
   char * text = NULL;
 
-  if (0!=STAT(file, &fstat))
-         return NULL;
+  if (0 != STAT(file, &fstat))
+    return NULL;
   text = GNUNET_malloc (fstat.st_size+1);
   gn_file = GNUNET_DISK_file_open(file, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ);
   if (gn_file==NULL)
@@ -3136,14 +3267,14 @@ load_certificate( const char * file )
       GNUNET_free(text);
       return NULL;
     }
-  if (GNUNET_SYSERR == GNUNET_DISK_file_read(gn_file, text, fstat.st_size))
+  if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fstat.st_size))
     {
-      GNUNET_free(text);
-      GNUNET_DISK_file_close(gn_file);
+      GNUNET_free (text);
+      GNUNET_DISK_file_close (gn_file);
       return NULL;
     }
   text[fstat.st_size] = '\0';
-  GNUNET_DISK_file_close(gn_file);
+  GNUNET_DISK_file_close (gn_file);
   return text;
 }
 #endif
@@ -3161,7 +3292,9 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
   struct GNUNET_TIME_Relative gn_timeout;
   long long unsigned int port;
   unsigned long long tneigh;
-  int addr_count = 0;
+  struct sockaddr **addrs;
+  socklen_t *addrlens;
+  int ret;
   char * component_name;
 #if BUILD_HTTPS
   char * key_file = NULL;
@@ -3201,17 +3334,12 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
                             &plugin->my_ascii_hash_ident);
 
 
-  if (GNUNET_CONFIGURATION_have_value (env->cfg, "TRANSPORT", "NEIGHBOUR_LIMIT"))
-  {
-    GNUNET_CONFIGURATION_get_value_number (env->cfg,
-                                         "TRANSPORT",
-                                         "NEIGHBOUR_LIMIT",
-                                         &tneigh);
-  }
-  else
-  {
-    tneigh = -1;
-  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (env->cfg,
+                                            component_name,
+                                            "MAX_CONNECTIONS",
+                                            &tneigh))
+    tneigh = 128;
   plugin->max_connect_per_transport = tneigh;
 
 
@@ -3316,96 +3444,94 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
   
 #if BUILD_HTTPS
   /* Reading HTTPS crypto related configuration */
-  /* Get crypto init string from config */
-  if (GNUNET_CONFIGURATION_have_value (env->cfg,
-                                      "transport-https", "CRYPTO_INIT"))
-    {
-      GNUNET_CONFIGURATION_get_value_string (env->cfg,
-                                            "transport-https",
-                                            "CRYPTO_INIT",
-                                            &plugin->crypto_init);
-    }
-  else
-    {
-      GNUNET_asprintf(&plugin->crypto_init,"NORMAL");
-    }
-  
-  /* Get private key file from config */
-  if (GNUNET_CONFIGURATION_have_value (env->cfg,
-                                      "transport-https", "KEY_FILE"))
-    {
-    GNUNET_CONFIGURATION_get_value_filename (env->cfg,
-                                            "transport-https",
-                                            "KEY_FILE",
-                                            &key_file);
-    }
-  if (key_file==NULL)
-    GNUNET_asprintf(&key_file,"https.key");
-  
-  /* Get private key file from config */
-  if (GNUNET_CONFIGURATION_have_value (env->cfg,"transport-https", "CERT_FILE"))
+  /* Get crypto init string from config */  
+  if ( (GNUNET_OK !=
+       GNUNET_CONFIGURATION_get_value_string (env->cfg,
+                                              "transport-https",
+                                              "CRYPTO_INIT",
+                                              &plugin->crypto_init)) ||
+       (GNUNET_OK !=
+       GNUNET_CONFIGURATION_get_value_filename (env->cfg,
+                                                "transport-https",
+                                                "KEY_FILE",
+                                                &key_file)) ||
+       (GNUNET_OK !=
+       GNUNET_CONFIGURATION_get_value_filename (env->cfg,
+                                                "transport-https",
+                                                "CERT_FILE",
+                                                &cert_file)) )
     {
-    GNUNET_CONFIGURATION_get_value_filename (env->cfg,
-                                            "transport-https",
-                                            "CERT_FILE",
-                                            &cert_file);
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+                      "https",
+                      _("Required configuration options missing in section `%s'\n"),
+                      "transport-https");
+      GNUNET_free (component_name);
+      GNUNET_free_non_null (key_file);
+      GNUNET_free_non_null (cert_file);
+      LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
+      return NULL;   
     }
-  if (cert_file==NULL)
-    GNUNET_asprintf(&cert_file,"https.cert");
-  
   /* read key & certificates from file */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
              "Loading TLS certificate `%s' `%s'\n", 
              key_file, cert_file);
 
-  plugin->key = load_certificate( key_file );
-  plugin->cert = load_certificate( cert_file );
+  plugin->key = load_certificate (key_file);
+  plugin->cert = load_certificate (cert_file);
 
-  if ((plugin->key==NULL) || (plugin->cert==NULL))
+  if ( (plugin->key==NULL) || (plugin->cert==NULL) )
     {
-      char * cmd;
-      int ret = 0;
-      GNUNET_asprintf(&cmd,
-                     "gnunet-transport-certificate-creation %s %s", 
-                     key_file, cert_file);
+      struct GNUNET_OS_Process *certcreation;
+
+      GNUNET_free_non_null (plugin->key);
+      plugin->key = NULL;
+      GNUNET_free_non_null (plugin->cert);
+      plugin->cert = NULL;
+#if DEBUG_HTTP
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "No usable TLS certificate found, creating certificate \n");
-      ret = system(cmd);
-      if (ret != 0)
-       {
-         GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
-                          "https",
-                          _("Could not create a new TLS certificate, shell script `%s' failed!\n"),cmd,
-                          "transport-https");
-         GNUNET_free (key_file);
-         GNUNET_free (cert_file);
-         GNUNET_free (component_name);
-         LIBGNUNET_PLUGIN_TRANSPORT_DONE(api);
-         GNUNET_free (cmd);
-         return NULL;
-       }
-      GNUNET_free (cmd);
-      plugin->key = load_certificate( key_file );
-      plugin->cert = load_certificate( cert_file );
-      if ((plugin->key==NULL) || (plugin->cert==NULL))
+                 "No usable TLS certificate found, creating certificate\n");
+#endif
+      errno = 0;
+      certcreation = GNUNET_OS_start_process (NULL, NULL,
+                                             "gnunet-transport-certificate-creation", 
+                                             "gnunet-transport-certificate-creation", 
+                                             key_file, cert_file,
+                                             NULL);
+      if (certcreation == NULL) 
        {
          GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
                           "https",
-                          _("No usable TLS certificate found and creating one failed! \n"),
-                          "transport-https");
+                          _("Could not create a new TLS certificate, program `gnunet-transport-certificate-creation' could not be started!\n"));
          GNUNET_free (key_file);
          GNUNET_free (cert_file);
          GNUNET_free (component_name);
-         
-         LIBGNUNET_PLUGIN_TRANSPORT_DONE(api);
+         LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
          return NULL;
        }
+      GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (certcreation));
+      GNUNET_OS_process_close (certcreation);
+      plugin->key = load_certificate (key_file);
+      plugin->cert = load_certificate (cert_file);
     }
+  if ( (plugin->key==NULL) || (plugin->cert==NULL) )
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+                      "https",
+                      _("No usable TLS certificate found and creating one failed!\n"),
+                      "transport-https");
+      GNUNET_free (key_file);
+      GNUNET_free (cert_file);
+      GNUNET_free (component_name);      
+      LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
+      return NULL;
+    }    
   GNUNET_free (key_file);
   GNUNET_free (cert_file);
-  
-  GNUNET_assert((plugin->key!=NULL) && (plugin->cert!=NULL));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLS certificate loaded\n");
+#if DEBUG_HTTP
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
+             "TLS certificate loaded\n");
+#endif
 #endif
 
   GNUNET_assert ((port > 0) && (port <= 65535));
@@ -3460,6 +3586,7 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
                                                         MHD_OPTION_CONNECTION_LIMIT, (unsigned int) plugin->max_connect_per_transport,
 #if BUILD_HTTPS
                                                        MHD_OPTION_HTTPS_PRIORITIES,  plugin->crypto_init,
+
                                                        MHD_OPTION_HTTPS_MEM_KEY, plugin->key,
                                                        MHD_OPTION_HTTPS_MEM_CERT, plugin->cert,
 #endif
@@ -3537,27 +3664,14 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
       return NULL;
     }
   
-  if (plugin->bind4_address != NULL)
-     addr_count++;
-  if (plugin->bind6_address != NULL)
-     addr_count++;
-
-  struct sockaddr **addrs;
-  socklen_t *addrlens;
-  int ret;
-
-  if   (GNUNET_SYSERR !=
-        (ret = GNUNET_SERVICE_get_server_addresses ("transport-http",
-                                                    env->cfg,
-                                                    &addrs,
-                                                    &addrlens)))
-    {
+  ret = GNUNET_SERVICE_get_server_addresses (component_name,
+                          env->cfg,
+                          &addrs,
+                          &addrlens);
 
-    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
-                     component_name,
-                      "addresses %u\n",ret);
-    /*
-      plugin->nat = GNUNET_NAT_register (env->cfg,
+  if (ret != GNUNET_SYSERR)
+  {
+    plugin->nat = GNUNET_NAT_register (env->cfg,
                                          GNUNET_YES,
                                          port,
                                          (unsigned int) ret,
@@ -3566,7 +3680,6 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
                                          &tcp_nat_port_map_callback,
                                          &try_connection_reversal,
                                          plugin);
-
       while (ret > 0)
       {
         ret--;
@@ -3574,23 +3687,23 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
         GNUNET_free (addrs[ret]);
       }
       GNUNET_free_non_null (addrs);
-      GNUNET_free_non_null (addrlens);*/
-    }
+      GNUNET_free_non_null (addrlens);
+  }
   else
-    {
-      plugin->nat = GNUNET_NAT_register (env->cfg,
-                                         GNUNET_YES,
-                                         0,
-                                         0, NULL, NULL,
-                                         NULL,
-                                         &try_connection_reversal,
-                                         plugin);
-    }
+  {
+    plugin->nat = GNUNET_NAT_register (env->cfg,
+         GNUNET_YES,
+         0,
+         0, NULL, NULL,
+         NULL,
+         &try_connection_reversal,
+         plugin);
+  }
 
   plugin->peers = GNUNET_CONTAINER_multihashmap_create (10);
   
   GNUNET_free(component_name);
-  GNUNET_SCHEDULER_add_now(address_notification, plugin);
+  //GNUNET_SCHEDULER_add_now(address_notification, plugin);
   return api;
 }