- changes
authorMatthias Wachs <wachs@net.in.tum.de>
Mon, 30 Jan 2012 12:27:14 +0000 (12:27 +0000)
committerMatthias Wachs <wachs@net.in.tum.de>
Mon, 30 Jan 2012 12:27:14 +0000 (12:27 +0000)
src/transport/plugin_transport_udp_new.c
src/transport/plugin_transport_udp_new.h
src/transport/plugin_transport_udp_new_broadcasting.c

index fb8c6cf3651436bd7f793b62ad3af41345859beb..0573648294472dbe2d82aada62e9373e30496572 100644 (file)
@@ -64,6 +64,29 @@ struct PrettyPrinterContext
   uint16_t port;
 };
 
+struct Session
+{
+  /**
+   * Which peer is this session for?
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Address of the other peer
+   */
+  const struct sockaddr *sock_addr;
+
+  size_t addrlen;
+};
+
+
+struct SessionCompareContext
+{
+  struct Session *res;
+  const struct GNUNET_HELLO_Address *addr;
+};
+
+
 
 /**
  * Function called for a quick conversion of the binary address to
@@ -292,6 +315,40 @@ udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
 }
 
 
+/**
+ * Destroy a session, plugin is being unloaded.
+ *
+ * @param cls unused
+ * @param key hash of public key of target peer
+ * @param value a 'struct PeerSession*' to clean up
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+disconnect_and_free_it (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct Plugin *plugin = cls;
+  struct Session *s = value;
+
+#if DEBUG_UDP
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Session %p to peer `%s' address ended \n",
+         s,
+         GNUNET_i2s (&s->target),
+         GNUNET_a2s (s->sock_addr, s->addrlen));
+#endif
+
+  plugin->env->session_end (plugin->env->cls, &s->target, s);
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
+                                                       &s->target.hashPubKey,
+                                                       s));
+
+  GNUNET_free (s);
+  return GNUNET_OK;
+}
+
+
 /**
  * Disconnect from a remote node.  Clean up session if we have one for this peer
  *
@@ -302,9 +359,129 @@ udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
 static void
 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
 {
+  struct Plugin *plugin = cls;
+  GNUNET_assert (plugin != NULL);
+
+  GNUNET_assert (target != NULL);
+#if DEBUG_UDP
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Disconnecting from peer `%s'\n", GNUNET_i2s (target));
+#endif
+  /* Clean up sessions */
+  GNUNET_CONTAINER_multihashmap_get_multiple (plugin->sessions, &target->hashPubKey, &disconnect_and_free_it, plugin);
 
 }
 
+static struct Session *
+create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
+                const void *addr, size_t addrlen,
+                GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
+{
+  struct Session *s;
+  const struct IPv4UdpAddress *t4;
+  const struct IPv6UdpAddress *t6;
+  struct sockaddr_in *v4;
+  struct sockaddr_in6 *v6;
+  size_t len;
+  struct GNUNET_ATS_Information ats;
+
+  switch (addrlen)
+  {
+  case sizeof (struct IPv4UdpAddress):
+    if (NULL == plugin->sockv4)
+    {
+      return NULL;
+    }
+    t4 = addr;
+    s = GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in));
+    len = sizeof (struct sockaddr_in);
+    v4 = (struct sockaddr_in *) &s[1];
+    v4->sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    v4->sin_len = sizeof (struct sockaddr_in);
+#endif
+    v4->sin_port = t4->u4_port;
+    v4->sin_addr.s_addr = t4->ipv4_addr;
+    ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v4, sizeof (struct sockaddr_in));
+    break;
+  case sizeof (struct IPv6UdpAddress):
+    if (NULL == plugin->sockv6)
+    {
+      return NULL;
+    }
+    t6 = addr;
+    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;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    v6->sin6_len = sizeof (struct sockaddr_in6);
+#endif
+    v6->sin6_port = t6->u6_port;
+    v6->sin6_addr = t6->ipv6_addr;
+    ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) v6, sizeof (struct sockaddr_in6));
+    break;
+  default:
+    /* Must have a valid address to send to */
+    GNUNET_break_op (0);
+    return NULL;
+  }
+
+  s->addrlen = len;
+  s->target = *target;
+  s->sock_addr = (const struct sockaddr *) &s[1];
+
+  return s;
+}
+
+static int session_cmp_it (void *cls,
+                           const GNUNET_HashCode * key,
+                           void *value)
+{
+  struct SessionCompareContext * cctx = cls;
+  const struct GNUNET_HELLO_Address *address = cctx->addr;
+  struct Session *s = value;
+  struct Session *r = cctx->res;
+  struct IPv4UdpAddress * u4 = NULL;
+  struct IPv6UdpAddress * u6 = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "AAAAAAAAAAAAAAAAAAa\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for existing session for address %s\n", udp_address_to_string (NULL, (void *) address->address, address->address_length));
+
+  if (s->addrlen == address->address_length)
+  {
+    if (address->address_length == sizeof (struct IPv4UdpAddress))
+    {
+      u4 = (struct IPv4UdpAddress * ) address->address;
+      struct sockaddr_in *sai = (struct sockaddr_in *) s->sock_addr;
+      if ((u4->ipv4_addr == sai->sin_addr.s_addr) &&
+          (u4->u4_port == sai->sin_port))
+      {
+        r = s;
+        return GNUNET_NO;
+      }
+    }
+    else if (address->address_length == sizeof (struct IPv6UdpAddress))
+    {
+      u6 = (struct IPv6UdpAddress * ) address->address;
+      struct sockaddr_in6 *sai = (struct sockaddr_in6 *) s->sock_addr;
+
+      if ((0 == memcmp (&u6->ipv6_addr, &sai->sin6_addr, sizeof (struct in6_addr))) &&
+         (u6->u6_port == sai->sin6_port))
+      {
+        r = s;
+        return GNUNET_NO;
+      }
+    }
+    else
+    {
+      GNUNET_break (0);
+      return GNUNET_YES;
+    }
+  }
+  return GNUNET_YES;
+}
+
 
 /**
  * Creates a new outbound session the transport service will use to send data to the
@@ -314,13 +491,50 @@ udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
  * @param address the address
  * @return the session or NULL of max connections exceeded
  */
-
 static struct Session *
 udp_plugin_get_session (void *cls,
                   const struct GNUNET_HELLO_Address *address)
 {
   struct Session * s = NULL;
-  //struct Plugin * plugin = cls;
+  struct Plugin * plugin = cls;
+
+  GNUNET_assert (plugin != NULL);
+  GNUNET_assert (address != NULL);
+
+  if ((address->address == NULL) ||
+      ((address->address_length != sizeof (struct IPv4UdpAddress)) &&
+      (address->address_length != sizeof (struct IPv6UdpAddress))))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  /* check if session already exists */
+  if (NULL != NULL)
+ {
+  struct SessionCompareContext cctx;
+  cctx.addr = address;
+  cctx.res = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "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);
+  if (cctx.res != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found existing session\n");
+    return cctx.res;
+  }
+ }
+  /* otherwise create new */
+  s = create_session (plugin,
+      &address->peer,
+      address->address,
+      address->address_length,
+      NULL, NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Creating new session %p\n", s);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
+                                                    &s->target.hashPubKey,
+                                                    s,
+                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 
   return s;
 }
@@ -784,6 +998,8 @@ libgnunet_plugin_transport_udp_init (void *cls)
   GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
                                  GNUNET_BANDWIDTH_value_init ((uint32_t)udp_max_bps), 30);
 
+
+  plugin->sessions = GNUNET_CONTAINER_multihashmap_create (10);
   plugin->port = port;
   plugin->aport = aport;
   plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
@@ -819,7 +1035,6 @@ libgnunet_plugin_transport_udp_init (void *cls)
   return api;
 }
 
-
 /**
  * The exported method. Makes the core api available via a global and
  * returns the udp transport API.
@@ -848,8 +1063,16 @@ libgnunet_plugin_transport_udp_done (void *cls)
   }
   GNUNET_NETWORK_fdset_destroy (plugin->rs);
   GNUNET_NETWORK_fdset_destroy (plugin->ws);
-
   GNUNET_NAT_unregister (plugin->nat);
+
+  /* Clean up sessions */
+#if DEBUG_UDP
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Cleaning up sessions\n");
+#endif
+  GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &disconnect_and_free_it, plugin);
+  GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
+
   plugin->nat = NULL;
   GNUNET_free (plugin);
   GNUNET_free (api);
index c9855306291cac8d8a832db9d891f9f904c4e8e5..062849e9dfbb9a7d2984c304bd0d3ff447221472 100644 (file)
@@ -42,6 +42,7 @@
 #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
 
 #define DEBUG_UDP GNUNET_YES
+#define DEBUG_UDP_BROADCASTING GNUNET_NO
 
 /**
  * MTU for fragmentation subsystem.  Should be conservative since
@@ -127,12 +128,6 @@ struct Plugin
    */
   struct GNUNET_CONTAINER_MultiHashMap *sessions;
 
-  /**
-   * Session of peers with whom we are currently connected,
-   * map of peer identity to 'struct PeerSession'.
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *inbound_sessions;
-
   /**
    * Heap with all of our defragmentation activities.
    */
index 849cdd15fd4d531556fa04c9a404cc3e40722da2..3c2d82675e849748249d76544a94a5af39175764 100644 (file)
@@ -105,12 +105,12 @@ broadcast_ipv6_mst_cb (void *cls, void *client,
   if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
       ntohs (msg->header.type))
     return;
-
+#if DEBUG_UDP_BROADCASTING
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received beacon with %u bytes from peer `%s' via address `%s'\n",
        ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
        udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
-
+#endif
   struct GNUNET_ATS_Information atsi[2];
 
   /* setup ATS */
@@ -146,11 +146,12 @@ broadcast_ipv4_mst_cb (void *cls, void *client,
   if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
       ntohs (msg->header.type))
     return;
-
+#if DEBUG_UDP_BROADCASTING
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received beacon with %u bytes from peer `%s' via address `%s'\n",
        ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
        udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
+#endif
 
   struct GNUNET_ATS_Information atsi[2];
 
@@ -180,10 +181,11 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
 
   if (addrlen == sizeof (struct sockaddr_in))
   {
+#if DEBUG_UDP_BROADCASTING
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n",
          size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen));
-
+#endif
     struct Mstv4Context *mc;
 
     mc = GNUNET_malloc (sizeof (struct Mstv4Context));
@@ -200,10 +202,11 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
   }
   else if (addrlen == sizeof (struct sockaddr_in6))
   {
+#if DEBUG_UDP_BROADCASTING
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n",
          size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen));
-
+#endif
     struct Mstv6Context *mc;
 
     mc = GNUNET_malloc (sizeof (struct Mstv6Context));
@@ -267,9 +270,13 @@ udp_ipv4_broadcast_send (void *cls,
     if (sent == GNUNET_SYSERR)
       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
     else
+    {
+#if DEBUG_UDP_BROADCASTING
       LOG (GNUNET_ERROR_TYPE_DEBUG,
            "Sent HELLO beacon broadcast with  %i bytes to address %s\n", sent,
            GNUNET_a2s (baddr->addr, baddr->addrlen));
+#endif
+    }
     baddr = baddr->next;
   }
 
@@ -316,12 +323,15 @@ udp_ipv6_broadcast_send (void *cls,
   if (sent == GNUNET_SYSERR)
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
   else
+  {
+#if DEBUG_UDP_BROADCASTING
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Sending IPv6 HELLO beacon broadcast with  %i bytes to address %s\n",
          sent,
          GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address,
                      sizeof (struct sockaddr_in6)));
-
+#endif
+  }
 
 
   plugin->send_ipv6_broadcast_task =
@@ -339,6 +349,7 @@ iface_proc (void *cls, const char *name, int isDefault,
 
   if (addr != NULL)
   {
+#if DEBUG_UDP_BROADCASTING
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ",
                 GNUNET_a2s (addr, addrlen), name, addr);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -346,7 +357,7 @@ iface_proc (void *cls, const char *name, int isDefault,
                 GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
                 GNUNET_a2s (netmask, addrlen), name, netmask);
-
+#endif
 
     /* Collecting broadcast addresses */
     if (broadcast_addr != NULL)