-doxygen
[oweals/gnunet.git] / src / transport / plugin_transport_udp.c
index 4d74e272e9d2ba3d3cf82dd920cf763925defcc8..7f442cff0cfedb7cf39b365e5bd1db3140fc2622 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+     (C) 2010-2013 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
  */
 #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
 
+/**
+ * Running pretty printers: head
+ */
+static struct PrettyPrinterContext *ppc_dll_head;
+
+/**
+ * Running pretty printers: tail
+ */
+static struct PrettyPrinterContext *ppc_dll_tail;
+
 /**
  * Closure for 'append_port'.
  */
 struct PrettyPrinterContext
 {
+  /**
+   * DLL
+   */
+  struct PrettyPrinterContext *next;
+
+  /**
+   * DLL
+   */
+  struct PrettyPrinterContext *prev;
+
+  /**
+   * Timeout task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+  /**
+   * Resolver handle
+   */
+  struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
+
   /**
    * Function to call with the result.
    */
@@ -162,6 +192,7 @@ struct SessionCompareContext
 {
   struct Session *res;
   const struct GNUNET_HELLO_Address *addr;
+  int inbound;
 };
 
 
@@ -434,22 +465,23 @@ udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
 
 /**
- * Start session timeout
+ * Cancel timeout
  */
 static void
-start_session_timeout (struct Session *s);
+stop_session_timeout (struct Session *s)
+{
+  GNUNET_assert (NULL != s);
 
-/**
- * Increment session timeout due to activity
- */
-static void
-reschedule_session_timeout (struct Session *s);
+  if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (s->timeout_task);
+    s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Timeout stopped for session %p canceled\n",
+                s);
+  }
+}
 
-/**
- * Cancel timeout
- */
-static void
-stop_session_timeout (struct Session *s);
 
 /**
  * (re)schedule select tasks for this plugin.
@@ -470,7 +502,7 @@ schedule_select (struct Plugin *plugin)
     for (udpw = plugin->ipv4_queue_head; NULL != udpw; udpw = udpw->next)
       min_delay = GNUNET_TIME_relative_min (min_delay,
                                            GNUNET_TIME_absolute_get_remaining (udpw->session->flow_delay_from_other_peer));
-    
+
     if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
       GNUNET_SCHEDULER_cancel(plugin->select_task);
 
@@ -479,10 +511,10 @@ schedule_select (struct Plugin *plugin)
      * - timeout minimum delay */
     plugin->select_task =
       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                                  (0 == min_delay.rel_value) ? GNUNET_TIME_UNIT_FOREVER_REL : min_delay,
+                                  (0 == min_delay.rel_value_us) ? GNUNET_TIME_UNIT_FOREVER_REL : min_delay,
                                   plugin->rs_v4,
-                                  (0 == min_delay.rel_value) ? plugin->ws_v4 : NULL,
-                                  &udp_plugin_select, plugin);  
+                                  (0 == min_delay.rel_value_us) ? plugin->ws_v4 : NULL,
+                                  &udp_plugin_select, plugin);
   }
   if ((GNUNET_YES == plugin->enable_ipv6) && (NULL != plugin->sockv6))
   {
@@ -490,14 +522,14 @@ schedule_select (struct Plugin *plugin)
     for (udpw = plugin->ipv6_queue_head; NULL != udpw; udpw = udpw->next)
       min_delay = GNUNET_TIME_relative_min (min_delay,
                                            GNUNET_TIME_absolute_get_remaining (udpw->session->flow_delay_from_other_peer));
-    
+
     if (GNUNET_SCHEDULER_NO_TASK != plugin->select_task_v6)
       GNUNET_SCHEDULER_cancel(plugin->select_task_v6);
     plugin->select_task_v6 =
       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                                  (0 == min_delay.rel_value) ? GNUNET_TIME_UNIT_FOREVER_REL : min_delay,
+                                  (0 == min_delay.rel_value_us) ? GNUNET_TIME_UNIT_FOREVER_REL : min_delay,
                                   plugin->rs_v6,
-                                  (0 == min_delay.rel_value) ? plugin->ws_v6 : NULL,
+                                  (0 == min_delay.rel_value_us) ? plugin->ws_v6 : NULL,
                                   &udp_plugin_select_v6, plugin);
   }
 }
@@ -528,8 +560,7 @@ udp_address_to_string (void *cls, const void *addr, size_t addrlen)
   uint16_t port;
   uint32_t options;
 
-  options = 0;
-  if (addrlen == sizeof (struct IPv6UdpAddress))
+  if ((NULL != addr) && (addrlen == sizeof (struct IPv6UdpAddress)))
   {
     t6 = addr;
     af = AF_INET6;
@@ -538,7 +569,7 @@ udp_address_to_string (void *cls, const void *addr, size_t addrlen)
     memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
     sb = &a6;
   }
-  else if (addrlen == sizeof (struct IPv4UdpAddress))
+  else if ((NULL != addr) && (addrlen == sizeof (struct IPv4UdpAddress)))
   {
     t4 = addr;
     af = AF_INET;
@@ -547,19 +578,14 @@ udp_address_to_string (void *cls, const void *addr, size_t addrlen)
     memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
     sb = &a4;
   }
-  else if (addrlen == 0)
-       {
-               GNUNET_snprintf (rbuf, sizeof (rbuf), "%s", TRANSPORT_SESSION_INBOUND_STRING);
-               return rbuf;
-       }
   else
   {
-    GNUNET_break_op (0);
     return NULL;
   }
   inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
 
-  GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
+  GNUNET_snprintf (rbuf, sizeof (rbuf),
+                  (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
                    PLUGIN_NAME, options, buf, port);
   return rbuf;
 }
@@ -591,7 +617,7 @@ udp_string_to_address (void *cls, const char *addr, uint16_t addrlen,
   address = NULL;
   plugin = NULL;
   optionstr = NULL;
-  options = 0;
+
   if ((NULL == addr) || (addrlen == 0))
   {
     GNUNET_break (0);
@@ -672,6 +698,23 @@ udp_string_to_address (void *cls, const char *addr, uint16_t addrlen,
 }
 
 
+static void
+ppc_cancel_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+       struct PrettyPrinterContext *ppc = cls;
+       /* GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PPC %p was not removed!\n", ppc); */
+       ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+       if (NULL != ppc->resolver_handle)
+       {
+               GNUNET_RESOLVER_request_cancel (ppc->resolver_handle);
+               ppc->resolver_handle = NULL;
+       }
+
+       GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc);
+       GNUNET_free (ppc);
+}
+
+
 /**
  * Append our port and forward the result.
  *
@@ -682,14 +725,31 @@ static void
 append_port (void *cls, const char *hostname)
 {
   struct PrettyPrinterContext *ppc = cls;
+  struct PrettyPrinterContext *cur;
   char *ret;
-
+       /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC callback: %p `%s'\n",ppc, hostname); */
   if (hostname == NULL)
   {
     ppc->asc (ppc->asc_cls, NULL);
+    GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc);
+    GNUNET_SCHEDULER_cancel (ppc->timeout_task);
+    ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    ppc->resolver_handle = NULL;
+       /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was removed!\n", ppc); */
     GNUNET_free (ppc);
     return;
   }
+  for (cur = ppc_dll_head; (NULL != cur); cur = cur->next)
+  {
+       if (cur == ppc)
+               break;
+  }
+  if (NULL == cur)
+  {
+       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid callback for PPC %p \n", ppc);
+       return;
+  }
+
   if (GNUNET_YES == ppc->ipv6)
     GNUNET_asprintf (&ret, "%s.%u.[%s]:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port);
   else
@@ -698,7 +758,6 @@ append_port (void *cls, const char *hostname)
   GNUNET_free (ret);
 }
 
-
 /**
  * Convert the transports address to a nice, human-readable
  * format.
@@ -731,7 +790,6 @@ udp_plugin_address_pretty_printer (void *cls, const char *type,
   uint16_t port;
   uint32_t options;
 
-  options = 0;
   if (addrlen == sizeof (struct IPv6UdpAddress))
   {
     u6 = addr;
@@ -762,12 +820,6 @@ udp_plugin_address_pretty_printer (void *cls, const char *type,
     sb = &a4;
     sbs = sizeof (a4);
   }
-  else if (0 == addrlen)
-  {
-    asc (asc_cls, TRANSPORT_SESSION_INBOUND_STRING);
-    asc (asc_cls, NULL);
-    return;
-  }
   else
   {
     /* invalid address */
@@ -784,7 +836,12 @@ udp_plugin_address_pretty_printer (void *cls, const char *type,
     ppc->ipv6 = GNUNET_YES;
   else
     ppc->ipv6 = GNUNET_NO;
-  GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
+  ppc->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(timeout, 2),
+               &ppc_cancel_task, ppc);
+  GNUNET_CONTAINER_DLL_insert (ppc_dll_head, ppc_dll_tail, ppc);
+       /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was created!\n", ppc); */
+  ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
+
 }
 
 
@@ -1001,7 +1058,6 @@ udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
   if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
       (addrlen != sizeof (struct IPv6UdpAddress)))
   {
-    GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   if (addrlen == sizeof (struct IPv4UdpAddress))
@@ -1074,6 +1130,7 @@ dequeue (struct Plugin *plugin, struct UDP_MessageWrapper * udpw)
                                  plugin->ipv6_queue_tail, udpw);
 }
 
+
 static void
 fragmented_message_done (struct UDP_FragmentationContext *fc, int result)
 {
@@ -1082,8 +1139,11 @@ fragmented_message_done (struct UDP_FragmentationContext *fc, int result)
   struct UDP_MessageWrapper dummy;
   struct Session *s = fc->session;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "%p : Fragmented message removed with result %s\n", fc, (result == GNUNET_SYSERR) ? "FAIL" : "SUCCESS");
-  
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "%p : Fragmented message removed with result %s\n",
+       fc,
+       (result == GNUNET_SYSERR) ? "FAIL" : "SUCCESS");
+
   /* Call continuation for fragmented message */
   memset (&dummy, 0, sizeof (dummy));
   dummy.msg_type = MSG_FRAGMENTED_COMPLETE;
@@ -1184,7 +1244,6 @@ disconnect_session (struct Session *s)
       call_continuation(udpw, GNUNET_SYSERR);
       GNUNET_free (udpw);
     }
-    udpw = next;
   }
   plugin->env->session_end (plugin->env->cls, &s->target, s);
 
@@ -1201,12 +1260,12 @@ disconnect_session (struct Session *s)
   }
 
   GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
-                                                       &s->target.hashPubKey,
+                 GNUNET_CONTAINER_multipeermap_remove (plugin->sessions,
+                                                       &s->target,
                                                        s));
   GNUNET_STATISTICS_set(plugin->env->stats,
                         "# UDP, sessions active",
-                        GNUNET_CONTAINER_multihashmap_size(plugin->sessions),
+                        GNUNET_CONTAINER_multipeermap_size(plugin->sessions),
                         GNUNET_NO);
   if (s->rc > 0)
     s->in_destroy = GNUNET_YES;
@@ -1223,7 +1282,7 @@ disconnect_session (struct Session *s)
  * @return GNUNET_OK (continue to iterate)
  */
 static int
-disconnect_and_free_it (void *cls, const struct GNUNET_HashCode * key, void *value)
+disconnect_and_free_it (void *cls, const struct GNUNET_PeerIdentity * key, void *value)
 {
   disconnect_session(value);
   return GNUNET_OK;
@@ -1247,7 +1306,8 @@ udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Disconnecting from peer `%s'\n", GNUNET_i2s (target));
   /* Clean up sessions */
-  GNUNET_CONTAINER_multihashmap_get_multiple (plugin->sessions, &target->hashPubKey, &disconnect_and_free_it, plugin);
+  GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessions, target,
+                                             &disconnect_and_free_it, plugin);
 }
 
 
@@ -1262,8 +1322,10 @@ session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
   s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Session %p was idle for %llu ms, disconnecting\n",
-              s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+              "Session %p was idle for %s, disconnecting\n",
+              s,
+             GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+                                                     GNUNET_YES));
   /* call session destroy function */
   disconnect_session (s);
 }
@@ -1281,8 +1343,10 @@ start_session_timeout (struct Session *s)
                                                    &session_timeout,
                                                    s);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Timeout for session %p set to %llu ms\n",
-              s,  (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+              "Timeout for session %p set to %s\n",
+              s,
+             GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+                                                     GNUNET_YES));
 }
 
 
@@ -1300,27 +1364,10 @@ reschedule_session_timeout (struct Session *s)
                                                    &session_timeout,
                                                    s);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Timeout rescheduled for session %p set to %llu ms\n",
-              s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
-}
-
-
-/**
- * Cancel timeout
- */
-static void
-stop_session_timeout (struct Session *s)
-{
-  GNUNET_assert (NULL != s);
-
-  if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
-  {
-    GNUNET_SCHEDULER_cancel (s->timeout_task);
-    s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Timeout stopped for session %p canceled\n",
-                s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
-  }
+              "Timeout rescheduled for session %p set to %s\n",
+              s,
+             GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+                                                     GNUNET_YES));
 }
 
 
@@ -1336,6 +1383,12 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
   struct sockaddr_in6 *v6;
   size_t len;
 
+  if (NULL == addr)
+  {
+       GNUNET_break (0);
+       return NULL;
+  }
+
   switch (addrlen)
   {
   case sizeof (struct IPv4UdpAddress):
@@ -1369,8 +1422,7 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
       return NULL;
     }
     t6 = addr;
-    s =
-        GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in6));
+    s = GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in6));
     len = sizeof (struct sockaddr_in6);
     v6 = (struct sockaddr_in6 *) &s[1];
     v6->sin6_family = AF_INET6;
@@ -1383,7 +1435,10 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
     break;
   default:
     /* Must have a valid address to send to */
-    GNUNET_break_op (0);
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              gettext_noop
+                              ("# requests to create session with invalid address"),
+                              1, GNUNET_NO);
     return NULL;
   }
   s->addrlen = len;
@@ -1401,7 +1456,7 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
 
 static int
 session_cmp_it (void *cls,
-               const struct GNUNET_HashCode * key,
+               const struct GNUNET_PeerIdentity * key,
                void *value)
 {
   struct SessionCompareContext * cctx = cls;
@@ -1410,14 +1465,19 @@ session_cmp_it (void *cls,
 
   socklen_t s_addrlen = s->addrlen;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Comparing  address %s <-> %s\n",
-      udp_address_to_string (NULL, (void *) address->address, address->address_length),
-      GNUNET_a2s (s->sock_addr, s->addrlen));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Comparing address %s <-> %s\n",
+       udp_address_to_string (NULL, (void *) address->address,
+                             address->address_length),
+       GNUNET_a2s (s->sock_addr, s->addrlen));
+  if (s->inbound != cctx->inbound)
+    return GNUNET_YES;
   if ((address->address_length == sizeof (struct IPv4UdpAddress)) &&
       (s_addrlen == sizeof (struct sockaddr_in)))
   {
     struct IPv4UdpAddress * u4 = NULL;
     u4 = (struct IPv4UdpAddress *) address->address;
+    GNUNET_assert (NULL != u4);
     const struct sockaddr_in *s4 = (const struct sockaddr_in *) s->sock_addr;
     if ((0 == memcmp ((const void *) &u4->ipv4_addr,(const void *) &s4->sin_addr, sizeof (struct in_addr))) &&
         (u4->u4_port == s4->sin_port))
@@ -1432,6 +1492,7 @@ session_cmp_it (void *cls,
   {
     struct IPv6UdpAddress * u6 = NULL;
     u6 = (struct IPv6UdpAddress *) address->address;
+    GNUNET_assert (NULL != u6);
     const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) s->sock_addr;
     if ((0 == memcmp (&u6->ipv6_addr, &s6->sin6_addr, sizeof (struct in6_addr))) &&
         (u6->u6_port == s6->sin6_port))
@@ -1452,7 +1513,7 @@ session_cmp_it (void *cls,
  * @return the network type in HBO or GNUNET_SYSERR
  */
 static enum GNUNET_ATS_Network_Type
-udp_get_network (void *cls, 
+udp_get_network (void *cls,
                 struct Session *session)
 {
   return ntohl (session->ats.value);
@@ -1465,11 +1526,13 @@ udp_get_network (void *cls,
  *
  * @param cls the plugin
  * @param address the address
+ * @param inbound look for inbound session
  * @return the session or NULL of max connections exceeded
  */
 static struct Session *
 udp_plugin_lookup_session (void *cls,
-                 const struct GNUNET_HELLO_Address *address)
+                          const struct GNUNET_HELLO_Address *address,
+                          int inbound)
 {
   struct Plugin * plugin = cls;
   struct IPv6UdpAddress * udp_a6;
@@ -1513,11 +1576,12 @@ udp_plugin_lookup_session (void *cls,
   struct SessionCompareContext cctx;
   cctx.addr = address;
   cctx.res = NULL;
+  cctx.inbound = inbound;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Looking for existing session for peer `%s' `%s' \n", 
-       GNUNET_i2s (&address->peer), 
+       "Looking for existing session for peer `%s' `%s' \n",
+       GNUNET_i2s (&address->peer),
        udp_address_to_string(NULL, address->address, address->address_length));
-  GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessions, &address->peer.hashPubKey, session_cmp_it, &cctx);
+  GNUNET_CONTAINER_multipeermap_get_multiple(plugin->sessions, &address->peer, session_cmp_it, &cctx);
   if (cctx.res != NULL)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
@@ -1526,39 +1590,41 @@ udp_plugin_lookup_session (void *cls,
   return NULL;
 }
 
+
 static struct Session *
 udp_plugin_create_session (void *cls,
-                  const struct GNUNET_HELLO_Address *address)
+                          const struct GNUNET_HELLO_Address *address,
+                          int inbound)
 {
-  struct Session * s = NULL;
+  struct Session *s;
 
-  /* otherwise create new */
   s = create_session (plugin,
-      &address->peer,
-      address->address,
-      address->address_length,
-      NULL, NULL);
+                     &address->peer,
+                     address->address,
+                     address->address_length,
+                     NULL, NULL);
   if (NULL == s)
-       return NULL; /* protocol not supported or address invalid */
+    return NULL; /* protocol not supported or address invalid */
+  s->inbound = inbound;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Creating new session %p for peer `%s' address `%s'\n",
+       "Creating new %s session %p for peer `%s' address `%s'\n",
+       (GNUNET_YES == s->inbound) ? "inbound" : "outbound",
        s,
        GNUNET_i2s(&address->peer),
        udp_address_to_string(NULL,address->address,address->address_length));
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
-                                                    &s->target.hashPubKey,
+                 GNUNET_CONTAINER_multipeermap_put (plugin->sessions,
+                                                    &s->target,
                                                     s,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
   GNUNET_STATISTICS_set(plugin->env->stats,
                         "# UDP, sessions active",
-                        GNUNET_CONTAINER_multihashmap_size(plugin->sessions),
+                        GNUNET_CONTAINER_multipeermap_size(plugin->sessions),
                         GNUNET_NO);
   return s;
 }
 
 
-
 /**
  * Creates a new outbound session the transport service will use to send data to the
  * peer
@@ -1569,28 +1635,27 @@ udp_plugin_create_session (void *cls,
  */
 static struct Session *
 udp_plugin_get_session (void *cls,
-                  const struct GNUNET_HELLO_Address *address)
+                       const struct GNUNET_HELLO_Address *address)
 {
-  struct Session * s = NULL;
+  struct Session *s;
 
   if (NULL == address)
   {
-       GNUNET_break (0);
-       return NULL;
+    GNUNET_break (0);
+    return NULL;
   }
   if ((address->address_length != sizeof (struct IPv4UdpAddress)) &&
-               (address->address_length != sizeof (struct IPv6UdpAddress)))
-               return NULL;
+      (address->address_length != sizeof (struct IPv6UdpAddress)))
+    return NULL;
 
   /* otherwise create new */
-  if (NULL != (s = udp_plugin_lookup_session(cls, address)))
-       return s;
-  else
-       return udp_plugin_create_session (cls, address);
+  if (NULL != (s = udp_plugin_lookup_session (cls, address, GNUNET_NO)))
+    return s;
+  return udp_plugin_create_session (cls, address, GNUNET_NO);
 }
 
 
-static void 
+static void
 enqueue (struct Plugin *plugin, struct UDP_MessageWrapper * udpw)
 {
   if (plugin->bytes_in_buffer + udpw->msg_size > INT64_MAX)
@@ -1631,7 +1696,8 @@ send_next_fragment (void *cls,
                    int result, size_t payload, size_t physical)
 {
   struct UDP_MessageWrapper *udpw = cls;
-  GNUNET_FRAGMENT_context_transmission_done (udpw->frag_ctx->frag);  
+
+  GNUNET_FRAGMENT_context_transmission_done (udpw->frag_ctx->frag);
 }
 
 
@@ -1651,8 +1717,8 @@ enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
   struct Plugin *plugin = frag_ctx->plugin;
   struct UDP_MessageWrapper * udpw;
   size_t msg_len = ntohs (msg->size);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, 
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Enqueuing fragment with %u bytes\n", msg_len);
   frag_ctx->fragments_used ++;
   udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + msg_len);
@@ -1724,7 +1790,7 @@ udp_plugin_send (void *cls,
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains_value(plugin->sessions, &s->target.hashPubKey, s))
+  if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_contains_value(plugin->sessions, &s->target, s))
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -1785,11 +1851,11 @@ udp_plugin_send (void *cls,
     frag_ctx->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats,
                                                     UDP_MTU,
                                                     &plugin->tracker,
-                                                    s->last_expected_msg_delay, 
-                                                    s->last_expected_ack_delay, 
+                                                    s->last_expected_msg_delay,
+                                                    s->last_expected_ack_delay,
                                                     &udp->header,
                                                     &enqueue_fragment,
-                                                    frag_ctx);    
+                                                    frag_ctx);
     s->frag_ctx = frag_ctx;
     GNUNET_STATISTICS_update (plugin->env->stats,
                               "# UDP, fragmented msgs, messages, pending",
@@ -1839,6 +1905,8 @@ udp_nat_port_map_callback (void *cls, int add_remove,
     u4.options = htonl(myoptions);
     u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
     u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
+    if (0 == ((struct sockaddr_in *) addr)->sin_port)
+       return;
     arg = &u4;
     args = sizeof (struct IPv4UdpAddress);
     break;
@@ -1846,6 +1914,8 @@ udp_nat_port_map_callback (void *cls, int add_remove,
     GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
     memset (&u4, 0, sizeof (u4));
     u6.options = htonl(myoptions);
+    if (0 == ((struct sockaddr_in6 *) addr)->sin6_port)
+       return;
     memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
             sizeof (struct in6_addr));
     u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
@@ -1966,14 +2036,11 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
        GNUNET_a2s (sender_addr, sender_addr_len));
 
   struct GNUNET_HELLO_Address * address = GNUNET_HELLO_address_allocate(&msg->sender, "udp", arg, args);
-  if (NULL == (s = udp_plugin_lookup_session (plugin, address)))
+  if (NULL == (s = udp_plugin_lookup_session (plugin, address, GNUNET_YES)))
   {
-               s = udp_plugin_create_session(plugin, address);
-               s->inbound = GNUNET_YES;
-         plugin->env->session_start (NULL, &address->peer, PLUGIN_NAME,
-                       (GNUNET_YES == s->inbound) ? NULL : address->address,
-                       (GNUNET_YES == s->inbound) ? 0 : address->address_length,
-                 s, NULL, 0);
+    s = udp_plugin_create_session (plugin, address, GNUNET_YES);
+    plugin->env->session_start (NULL, &address->peer, PLUGIN_NAME,
+                  address->address, address->address_length, s, NULL, 0);
   }
   GNUNET_free (address);
 
@@ -2047,25 +2114,39 @@ fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
 
 struct LookupContext
 {
-  const struct sockaddr * addr;
-
   struct Session *res;
 
+  const struct sockaddr * addr;
+
   size_t addrlen;
+
+  int must_have_frag_ctx;
 };
 
 
 static int
-lookup_session_by_addr_it (void *cls, const struct GNUNET_HashCode * key, void *value)
+lookup_session_by_addr_it (void *cls,
+                          const struct GNUNET_PeerIdentity *key,
+                          void *value)
 {
   struct LookupContext *l_ctx = cls;
   struct Session * s = value;
 
+  if ((GNUNET_YES == l_ctx->must_have_frag_ctx) && (NULL == s->frag_ctx))
+    return GNUNET_YES;
+
+  /*
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Comparing session: have %s %s %p<-> want %s\n",
+      GNUNET_a2s(s->sock_addr, s->addrlen),
+      (GNUNET_YES == s->inbound) ? "inbound" : "outbound",
+      s->frag_ctx,
+      GNUNET_a2s(l_ctx->addr, l_ctx->addrlen));
+   */
   if ((s->addrlen == l_ctx->addrlen) &&
       (0 == memcmp (s->sock_addr, l_ctx->addr, s->addrlen)))
   {
     l_ctx->res = s;
-    return GNUNET_NO;
+    return GNUNET_YES;
   }
   return GNUNET_YES;
 }
@@ -2092,7 +2173,8 @@ ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
   l_ctx.addr = rc->src_addr;
   l_ctx.addrlen = rc->addr_len;
   l_ctx.res = NULL;
-  GNUNET_CONTAINER_multihashmap_iterate (rc->plugin->sessions,
+  l_ctx.must_have_frag_ctx = GNUNET_NO;
+  GNUNET_CONTAINER_multipeermap_iterate (rc->plugin->sessions,
       &lookup_session_by_addr_it,
       &l_ctx);
   s = l_ctx.res;
@@ -2100,16 +2182,17 @@ ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
   if (NULL == s)
     return;
 
-  if (s->flow_delay_for_other_peer.rel_value <= UINT32_MAX)
-    delay = s->flow_delay_for_other_peer.rel_value;
+  if (s->flow_delay_for_other_peer.rel_value_us <= UINT32_MAX)
+    delay = s->flow_delay_for_other_peer.rel_value_us;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Sending ACK to `%s' including delay of %u ms\n",
+       "Sending ACK to `%s' including delay of %s\n",
        GNUNET_a2s (rc->src_addr,
                    (rc->src_addr->sa_family ==
                     AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct
                                                                      sockaddr_in6)),
-       delay);
+       GNUNET_STRINGS_relative_time_to_string (s->flow_delay_for_other_peer,
+                                              GNUNET_YES));
   udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + msize);
   udpw->msg_size = msize;
   udpw->payload_size = 0;
@@ -2127,10 +2210,10 @@ ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
 }
 
 
-static void 
+static void
 read_process_msg (struct Plugin *plugin,
                  const struct GNUNET_MessageHeader *msg,
-                 const char *addr,
+                 const struct sockaddr *addr,
                  socklen_t fromlen)
 {
   if (ntohs (msg->size) < sizeof (struct UDPMessage))
@@ -2139,14 +2222,14 @@ read_process_msg (struct Plugin *plugin,
     return;
   }
   process_udp_message (plugin, (const struct UDPMessage *) msg,
-                       (const struct sockaddr *) addr, fromlen);
+                       addr, fromlen);
 }
 
 
-static void 
+static void
 read_process_ack (struct Plugin *plugin,
                  const struct GNUNET_MessageHeader *msg,
-                 char *addr,
+                 const struct sockaddr *addr,
                  socklen_t fromlen)
 {
   const struct GNUNET_MessageHeader *ack;
@@ -2165,20 +2248,22 @@ read_process_ack (struct Plugin *plugin,
   l_ctx.addr = (const struct sockaddr *) addr;
   l_ctx.addrlen = fromlen;
   l_ctx.res = NULL;
-  GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions,
+  l_ctx.must_have_frag_ctx = GNUNET_YES;
+  GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions,
                                         &lookup_session_by_addr_it,
                                         &l_ctx);
   s = l_ctx.res;
-
   if ((NULL == s) || (NULL == s->frag_ctx))
   {
     return;
   }
 
-  flow_delay.rel_value = (uint64_t) ntohl (udp_ack->delay);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, 
-       "We received a sending delay of %llu\n",
-       flow_delay.rel_value);
+
+  flow_delay.rel_value_us = (uint64_t) ntohl (udp_ack->delay);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "We received a sending delay of %s\n",
+       GNUNET_STRINGS_relative_time_to_string (flow_delay,
+                                              GNUNET_YES));
   s->flow_delay_from_other_peer =
       GNUNET_TIME_relative_to_absolute (flow_delay);
 
@@ -2197,7 +2282,7 @@ read_process_ack (struct Plugin *plugin,
     LOG (GNUNET_ERROR_TYPE_DEBUG,
         "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
         (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
-        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
+        GNUNET_a2s (addr, fromlen));
     /* Expect more ACKs to arrive */
     return;
   }
@@ -2205,17 +2290,17 @@ read_process_ack (struct Plugin *plugin,
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Message full ACK'ed\n",
        (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
-       GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
+       GNUNET_a2s (addr, fromlen));
 
   /* Remove fragmented message after successful sending */
   fragmented_message_done (s->frag_ctx, GNUNET_OK);
 }
 
 
-static void 
+static void
 read_process_fragment (struct Plugin *plugin,
                       const struct GNUNET_MessageHeader *msg,
-                      char *addr,
+                      const struct sockaddr *addr,
                       socklen_t fromlen)
 {
   struct DefragContext *d_ctx;
@@ -2223,12 +2308,12 @@ read_process_fragment (struct Plugin *plugin,
   struct FindReceiveContext frc;
 
   frc.rc = NULL;
-  frc.addr = (const struct sockaddr *) addr;
+  frc.addr = addr;
   frc.addr_len = fromlen;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n",
        (unsigned int) ntohs (msg->size),
-       GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
+       GNUNET_a2s (addr, fromlen));
   /* Lookup existing receive context for this address */
   GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs,
                                  &find_receive_context,
@@ -2251,18 +2336,18 @@ read_process_fragment (struct Plugin *plugin,
     d_ctx->hnode =
         GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs, d_ctx,
                                       (GNUNET_CONTAINER_HeapCostType)
-                                      now.abs_value);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, 
+                                      now.abs_value_us);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Created new defragmentation context for %u-byte fragment from `%s'\n",
         (unsigned int) ntohs (msg->size),
-        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
+        GNUNET_a2s (addr, fromlen));
   }
   else
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Found existing defragmentation context for %u-byte fragment from `%s'\n",
         (unsigned int) ntohs (msg->size),
-        GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
+        GNUNET_a2s (addr, fromlen));
   }
 
   if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (d_ctx->defrag, msg))
@@ -2270,7 +2355,7 @@ read_process_fragment (struct Plugin *plugin,
     /* keep this 'rc' from expiring */
     GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs, d_ctx->hnode,
                                        (GNUNET_CONTAINER_HeapCostType)
-                                       now.abs_value);
+                                       now.abs_value_us);
   }
   if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) >
       UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
@@ -2294,7 +2379,7 @@ static void
 udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
 {
   socklen_t fromlen;
-  char addr[32];
+  struct sockaddr_storage addr;
   char buf[65536] GNUNET_ALIGN;
   ssize_t size;
   const struct GNUNET_MessageHeader *msg;
@@ -2302,7 +2387,7 @@ udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
   fromlen = sizeof (addr);
   memset (&addr, 0, sizeof (addr));
   size = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
-                                      (struct sockaddr *) &addr, &fromlen);
+                                         (struct sockaddr *) &addr, &fromlen);
 #if MINGW
   /* On SOCK_DGRAM UDP sockets recvfrom might fail with a
    * WSAECONNRESET error to indicate that previous sendto() (yes, sendto!)
@@ -2337,8 +2422,10 @@ udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
   msg = (const struct GNUNET_MessageHeader *) buf;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "UDP received %u-byte message from `%s' type %i\n", (unsigned int) size,
-       GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs (msg->type));
+       "UDP received %u-byte message from `%s' type %u\n",
+       (unsigned int) size,
+       GNUNET_a2s ((const struct sockaddr *) &addr, fromlen),
+       ntohs (msg->type));
 
   if (size != ntohs (msg->size))
   {
@@ -2353,27 +2440,28 @@ udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
   switch (ntohs (msg->type))
   {
   case GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON:
-    udp_broadcast_receive (plugin, &buf, size, addr, fromlen);
+    udp_broadcast_receive (plugin, buf, size,
+                           (const struct sockaddr *) &addr, fromlen);
     return;
-
   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE:
-    read_process_msg (plugin, msg, addr, fromlen);
+    read_process_msg (plugin, msg,
+                      (const struct sockaddr *) &addr, fromlen);
     return;
-
   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
-    read_process_ack (plugin, msg, addr, fromlen);
+    read_process_ack (plugin, msg,
+                      (const struct sockaddr *) &addr, fromlen);
     return;
-
   case GNUNET_MESSAGE_TYPE_FRAGMENT:
-    read_process_fragment (plugin, msg, addr, fromlen);
+    read_process_fragment (plugin, msg,
+                           (const struct sockaddr *) &addr, fromlen);
     return;
-
   default:
     GNUNET_break_op (0);
     return;
   }
 }
 
+
 static struct UDP_MessageWrapper *
 remove_timeout_messages_and_select (struct UDP_MessageWrapper *head,
                                     struct GNUNET_NETWORK_Handle *sock)
@@ -2386,7 +2474,7 @@ remove_timeout_messages_and_select (struct UDP_MessageWrapper *head,
   {
     /* Find messages with timeout */
     remaining = GNUNET_TIME_absolute_get_remaining (udpw->timeout);
-    if (GNUNET_TIME_UNIT_ZERO.rel_value == remaining.rel_value)
+    if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us)
     {
       /* Message timed out */
       switch (udpw->msg_type) {
@@ -2469,10 +2557,10 @@ remove_timeout_messages_and_select (struct UDP_MessageWrapper *head,
     {
       /* Message did not time out, check flow delay */
       remaining = GNUNET_TIME_absolute_get_remaining (udpw->session->flow_delay_from_other_peer);
-      if (GNUNET_TIME_UNIT_ZERO.rel_value == remaining.rel_value)
+      if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us)
       {
         /* this message is not delayed */
-        LOG (GNUNET_ERROR_TYPE_DEBUG, 
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
              "Message for peer `%s' (%u bytes) is not delayed \n",
              GNUNET_i2s(&udpw->session->target), udpw->payload_size);
         break; /* Found message to send, break */
@@ -2481,8 +2569,10 @@ remove_timeout_messages_and_select (struct UDP_MessageWrapper *head,
       {
         /* Message is delayed, try next */
         LOG (GNUNET_ERROR_TYPE_DEBUG,
-             "Message for peer `%s' (%u bytes) is delayed for %llu \n",
-             GNUNET_i2s(&udpw->session->target), udpw->payload_size, remaining.rel_value);
+             "Message for peer `%s' (%u bytes) is delayed for %s\n",
+             GNUNET_i2s(&udpw->session->target), udpw->payload_size,
+            GNUNET_STRINGS_relative_time_to_string (remaining,
+                                                    GNUNET_YES));
         udpw = udpw->next;
       }
     }
@@ -2525,10 +2615,9 @@ analyze_send_error (struct Plugin *plugin,
       */
 
     LOG (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
-        _("UDP could not transmit message to `%s': "
-          "Please check your network configuration and disable IPv6 if your "
-          "connection does not have a global IPv6 address\n"),
-        GNUNET_a2s (sa, slen));
+        _("UDP could not transmit IPv6 message! "
+        "Please check your network configuration and disable IPv6 if your "
+        "connection does not have a global IPv6 address\n"));
    }
  }
  else
@@ -2539,6 +2628,7 @@ analyze_send_error (struct Plugin *plugin,
  }
 }
 
+
 static size_t
 udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
 {
@@ -2617,10 +2707,10 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
        (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4)) )
     udp_select_read (plugin, plugin->sockv4);
   if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
-       (NULL != plugin->sockv4) && 
+       (NULL != plugin->sockv4) &&
        (NULL != plugin->ipv4_queue_head) &&
        (GNUNET_NETWORK_fdset_isset (tc->write_ready, plugin->sockv4)) )
-    udp_select_send (plugin, plugin->sockv4);   
+    udp_select_send (plugin, plugin->sockv4);
   schedule_select (plugin);
 }
 
@@ -2647,7 +2737,7 @@ udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     udp_select_read (plugin, plugin->sockv6);
   if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
        (NULL != plugin->sockv6) && (plugin->ipv6_queue_head != NULL) &&
-       (GNUNET_NETWORK_fdset_isset (tc->write_ready, plugin->sockv6)) )    
+       (GNUNET_NETWORK_fdset_isset (tc->write_ready, plugin->sockv6)) )
     udp_select_send (plugin, plugin->sockv6);
   schedule_select (plugin);
 }
@@ -2658,15 +2748,15 @@ udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  * @return number of sockets that were successfully bound
  */
 static int
-setup_sockets (struct Plugin *plugin, 
+setup_sockets (struct Plugin *plugin,
               const struct sockaddr_in6 *bind_v6,
               const struct sockaddr_in *bind_v4)
 {
   int tries;
   int sockets_created = 0;
-  struct sockaddr_in6 serverAddrv6;
-  struct sockaddr_in serverAddrv4;
-  struct sockaddr *serverAddr;
+  struct sockaddr_in6 server_addrv6;
+  struct sockaddr_in server_addrv4;
+  struct sockaddr *server_addr;
   struct sockaddr *addrs[2];
   socklen_t addrlens[2];
   socklen_t addrlen;
@@ -2685,31 +2775,31 @@ setup_sockets (struct Plugin *plugin,
     }
     else
     {
-       memset (&serverAddrv6, '\0', sizeof (struct sockaddr_in6));
+       memset (&server_addrv6, '\0', sizeof (struct sockaddr_in6));
 #if HAVE_SOCKADDR_IN_SIN_LEN
-      serverAddrv6.sin6_len = sizeof (struct sockaddr_in6);
+      server_addrv6.sin6_len = sizeof (struct sockaddr_in6);
 #endif
-      serverAddrv6.sin6_family = AF_INET6;
+      server_addrv6.sin6_family = AF_INET6;
       if (NULL != bind_v6)
-       serverAddrv6.sin6_addr = bind_v6->sin6_addr;
+       server_addrv6.sin6_addr = bind_v6->sin6_addr;
       else
-       serverAddrv6.sin6_addr = in6addr_any;
+       server_addrv6.sin6_addr = in6addr_any;
 
       if (0 == plugin->port) /* autodetect */
-               serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
+               server_addrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
       else
-               serverAddrv6.sin6_port = htons (plugin->port);
+               server_addrv6.sin6_port = htons (plugin->port);
       addrlen = sizeof (struct sockaddr_in6);
-      serverAddr = (struct sockaddr *) &serverAddrv6;
+      server_addr = (struct sockaddr *) &server_addrv6;
 
       tries = 0;
       while (tries < 10)
       {
                LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 `%s'\n",
-                                GNUNET_a2s (serverAddr, addrlen));
+                                GNUNET_a2s (server_addr, addrlen));
                /* binding */
                if (GNUNET_OK == GNUNET_NETWORK_socket_bind (plugin->sockv6,
-                                                            serverAddr, addrlen, 0))
+                                                            server_addr, addrlen))
                        break;
                eno = errno;
                if (0 != plugin->port)
@@ -2718,7 +2808,7 @@ setup_sockets (struct Plugin *plugin,
                                break; /* bind failed on specific port */
                }
                /* autodetect */
-               serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
+               server_addrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
                tries ++;
       }
       if (tries >= 10)
@@ -2732,8 +2822,8 @@ setup_sockets (struct Plugin *plugin,
       {
         LOG (GNUNET_ERROR_TYPE_DEBUG,
              "IPv6 socket created on port %s\n",
-             GNUNET_a2s (serverAddr, addrlen));
-        addrs[sockets_created] = (struct sockaddr *) &serverAddrv6;
+             GNUNET_a2s (server_addr, addrlen));
+        addrs[sockets_created] = (struct sockaddr *) &server_addrv6;
         addrlens[sockets_created] = sizeof (struct sockaddr_in6);
         sockets_created++;
       }
@@ -2741,7 +2831,7 @@ setup_sockets (struct Plugin *plugin,
       {
           LOG (GNUNET_ERROR_TYPE_ERROR,
                "Failed to bind UDP socket to %s: %s\n",
-               GNUNET_a2s (serverAddr, addrlen),
+               GNUNET_a2s (server_addr, addrlen),
               STRERROR (eno));
       }
     }
@@ -2758,35 +2848,35 @@ setup_sockets (struct Plugin *plugin,
   }
   else
   {
-    memset (&serverAddrv4, '\0', sizeof (struct sockaddr_in));
+    memset (&server_addrv4, '\0', sizeof (struct sockaddr_in));
 #if HAVE_SOCKADDR_IN_SIN_LEN
-    serverAddrv4.sin_len = sizeof (struct sockaddr_in);
+    server_addrv4.sin_len = sizeof (struct sockaddr_in);
 #endif
-    serverAddrv4.sin_family = AF_INET;
+    server_addrv4.sin_family = AF_INET;
     if (NULL != bind_v4)
-      serverAddrv4.sin_addr = bind_v4->sin_addr;
+      server_addrv4.sin_addr = bind_v4->sin_addr;
     else
-      serverAddrv4.sin_addr.s_addr = INADDR_ANY;
-    
+      server_addrv4.sin_addr.s_addr = INADDR_ANY;
+
     if (0 == plugin->port)
       /* autodetect */
-      serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
+      server_addrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
     else
-      serverAddrv4.sin_port = htons (plugin->port);
-    
-    
+      server_addrv4.sin_port = htons (plugin->port);
+
+
     addrlen = sizeof (struct sockaddr_in);
-    serverAddr = (struct sockaddr *) &serverAddrv4;
-    
+    server_addr = (struct sockaddr *) &server_addrv4;
+
     tries = 0;
     while (tries < 10)
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 `%s'\n",
-                       GNUNET_a2s (serverAddr, addrlen));
-      
+                       GNUNET_a2s (server_addr, addrlen));
+
       /* binding */
       if (GNUNET_OK == GNUNET_NETWORK_socket_bind (plugin->sockv4,
-                                                   serverAddr, addrlen, 0))
+                                                   server_addr, addrlen))
                break;
       eno = errno;
       if (0 != plugin->port)
@@ -2794,35 +2884,35 @@ setup_sockets (struct Plugin *plugin,
                tries = 10; /* fail */
                break; /* bind failed on specific port */
       }
-      
+
       /* autodetect */
-      serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
+      server_addrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);
       tries ++;
     }
-    
+
     if (tries >= 10)
     {
       GNUNET_NETWORK_socket_close (plugin->sockv4);
       plugin->enable_ipv4 = GNUNET_NO;
       plugin->sockv4 = NULL;
     }
-    
+
     if (plugin->sockv4 != NULL)
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG,
-               "IPv4 socket created on port %s\n", GNUNET_a2s (serverAddr, addrlen));
-      addrs[sockets_created] = (struct sockaddr *) &serverAddrv4;
+               "IPv4 socket created on port %s\n", GNUNET_a2s (server_addr, addrlen));
+      addrs[sockets_created] = (struct sockaddr *) &server_addrv4;
       addrlens[sockets_created] = sizeof (struct sockaddr_in);
       sockets_created++;
     }
     else
-    {            
+    {
       LOG (GNUNET_ERROR_TYPE_ERROR,
                "Failed to bind UDP socket to %s: %s\n",
-               GNUNET_a2s (serverAddr, addrlen), STRERROR (eno));
+               GNUNET_a2s (server_addr, addrlen), STRERROR (eno));
     }
   }
-  
+
   if (0 == sockets_created)
   {
                LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
@@ -2889,8 +2979,8 @@ libgnunet_plugin_transport_udp_init (void *cls)
   char * bind6_address;
   char * fancy_interval;
   struct GNUNET_TIME_Relative interval;
-  struct sockaddr_in serverAddrv4;
-  struct sockaddr_in6 serverAddrv6;
+  struct sockaddr_in server_addrv4;
+  struct sockaddr_in6 server_addrv6;
   int res;
   int have_bind4;
   int have_bind6;
@@ -2938,7 +3028,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
 
   /* Addresses */
   have_bind4 = GNUNET_NO;
-  memset (&serverAddrv4, 0, sizeof (serverAddrv4));
+  memset (&server_addrv4, 0, sizeof (server_addrv4));
   if (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
                                              "BINDTO", &bind4_address))
@@ -2946,7 +3036,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Binding udp plugin to specific address: `%s'\n",
          bind4_address);
-    if (1 != inet_pton (AF_INET, bind4_address, &serverAddrv4.sin_addr))
+    if (1 != inet_pton (AF_INET, bind4_address, &server_addrv4.sin_addr))
     {
       GNUNET_free (bind4_address);
       return NULL;
@@ -2955,7 +3045,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
   }
   GNUNET_free_non_null (bind4_address);
   have_bind6 = GNUNET_NO;
-  memset (&serverAddrv6, 0, sizeof (serverAddrv6));
+  memset (&server_addrv6, 0, sizeof (server_addrv6));
   if (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
                                              "BINDTO6", &bind6_address))
@@ -2964,7 +3054,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
          "Binding udp plugin to specific address: `%s'\n",
          bind6_address);
     if (1 !=
-        inet_pton (AF_INET6, bind6_address, &serverAddrv6.sin6_addr))
+        inet_pton (AF_INET6, bind6_address, &server_addrv6.sin6_addr))
     {
       LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"),
            bind6_address);
@@ -3012,21 +3102,21 @@ libgnunet_plugin_transport_udp_init (void *cls)
   p->enable_ipv6 = enable_v6;
   p->enable_ipv4 = GNUNET_YES; /* default */
   p->env = env;
-  p->sessions = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  p->sessions = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
   p->defrag_ctxs = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
   p->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, p);
   GNUNET_BANDWIDTH_tracker_init (&p->tracker,
-                                 GNUNET_BANDWIDTH_value_init ((uint32_t)udp_max_bps), 30);
+      GNUNET_BANDWIDTH_value_init ((uint32_t) udp_max_bps), 30);
   plugin = p;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Setting up sockets\n");
-  res = setup_sockets (p, (GNUNET_YES == have_bind6) ? &serverAddrv6 : NULL,
-                                                                               (GNUNET_YES == have_bind4) ? &serverAddrv4 : NULL);
-  if ((res == 0) || ((p->sockv4 == NULL&& (p->sockv6 == NULL)))
+  LOG(GNUNET_ERROR_TYPE_DEBUG, "Setting up sockets\n");
+  res = setup_sockets (p, (GNUNET_YES == have_bind6) ? &server_addrv6 : NULL,
+      (GNUNET_YES == have_bind4) ? &server_addrv4 : NULL );
+  if ((res == 0) || ((p->sockv4 == NULL )&& (p->sockv6 == NULL)))
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
         _("Failed to create network sockets, plugin failed\n"));
-    GNUNET_CONTAINER_multihashmap_destroy (p->sessions);
+    GNUNET_CONTAINER_multipeermap_destroy (p->sessions);
     GNUNET_CONTAINER_heap_destroy (p->defrag_ctxs);
     GNUNET_SERVER_mst_destroy (p->mst);
     GNUNET_free (p);
@@ -3035,7 +3125,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
   else if (broadcast == GNUNET_YES)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting broadcasting\n");
-    setup_broadcast (p, &serverAddrv6, &serverAddrv4);
+    setup_broadcast (p, &server_addrv6, &server_addrv4);
   }
 
   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
@@ -3083,6 +3173,8 @@ libgnunet_plugin_transport_udp_done (void *cls)
 {
   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
+  struct PrettyPrinterContext *cur;
+  struct PrettyPrinterContext *next;
 
   if (NULL == plugin)
   {
@@ -3166,8 +3258,19 @@ libgnunet_plugin_transport_udp_done (void *cls)
   /* Clean up sessions */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Cleaning up sessions\n");
-  GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &disconnect_and_free_it, plugin);
-  GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
+  GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, &disconnect_and_free_it, plugin);
+  GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions);
+
+  next = ppc_dll_head;
+  for (cur = next; NULL != cur; cur = next)
+  {
+       next = cur->next;
+       GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, cur);
+       GNUNET_RESOLVER_request_cancel (cur->resolver_handle);
+       GNUNET_SCHEDULER_cancel (cur->timeout_task);
+       GNUNET_free (cur);
+       GNUNET_break (0);
+  }
 
   plugin->nat = NULL;
   GNUNET_free (plugin);