From 5cc2c89cdcb6d8fb2b848f61e3caf001dfd40fb4 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Mon, 30 Jan 2012 12:27:14 +0000 Subject: [PATCH] - changes --- src/transport/plugin_transport_udp_new.c | 231 +++++++++++++++++- src/transport/plugin_transport_udp_new.h | 7 +- .../plugin_transport_udp_new_broadcasting.c | 25 +- 3 files changed, 246 insertions(+), 17 deletions(-) diff --git a/src/transport/plugin_transport_udp_new.c b/src/transport/plugin_transport_udp_new.c index fb8c6cf36..057364829 100644 --- a/src/transport/plugin_transport_udp_new.c +++ b/src/transport/plugin_transport_udp_new.c @@ -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); diff --git a/src/transport/plugin_transport_udp_new.h b/src/transport/plugin_transport_udp_new.h index c98553062..062849e9d 100644 --- a/src/transport/plugin_transport_udp_new.h +++ b/src/transport/plugin_transport_udp_new.h @@ -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. */ diff --git a/src/transport/plugin_transport_udp_new_broadcasting.c b/src/transport/plugin_transport_udp_new_broadcasting.c index 849cdd15f..3c2d82675 100644 --- a/src/transport/plugin_transport_udp_new_broadcasting.c +++ b/src/transport/plugin_transport_udp_new_broadcasting.c @@ -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) -- 2.25.1