From 3629ff42683654fe6dcc6463a77faaeb27ae3203 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 1 Feb 2015 18:00:31 +0000 Subject: cleaning up UDP code to use only on address format throughout the code as much as possible --- src/transport/gnunet-service-transport.c | 97 ++- .../gnunet-service-transport_neighbours.c | 8 +- src/transport/gnunet-service-transport_plugins.c | 8 +- .../gnunet-service-transport_validation.c | 4 +- src/transport/plugin_transport_tcp.c | 3 +- src/transport/plugin_transport_udp.c | 732 +++++++++++---------- src/transport/plugin_transport_udp.h | 55 +- src/transport/plugin_transport_udp_broadcasting.c | 199 ++---- 8 files changed, 557 insertions(+), 549 deletions(-) (limited to 'src') diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index b21b0c384..505fed797 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -359,7 +359,9 @@ connect_bl_check_cont (void *cls, /* Blacklist allows to speak to this peer, forward SYN to neighbours */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received SYN message from peer `%s' with `%s' %p\n", - GNUNET_i2s (peer), GST_plugins_a2s (blctx->address), blctx->session); + GNUNET_i2s (peer), + GST_plugins_a2s (blctx->address), + blctx->session); if (GNUNET_OK != GST_neighbours_handle_session_syn (blctx->msg, @@ -416,16 +418,19 @@ GST_receive_callback (void *cls, if (NULL == message) goto end; type = ntohs (message->type); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Received Message with type %u from peer `%s'\n", type, - GNUNET_i2s (&address->peer)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received Message with type %u from peer `%s'\n", + type, + GNUNET_i2s (&address->peer)); - GNUNET_STATISTICS_update (GST_stats, gettext_noop - ("# bytes total received"), + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# bytes total received"), ntohs (message->size), GNUNET_NO); - GST_neighbours_notify_data_recv (&address->peer, address, session, message); - + GST_neighbours_notify_data_recv (&address->peer, + address, + session, + message); switch (type) { case GNUNET_MESSAGE_TYPE_HELLO_LEGACY: @@ -434,8 +439,9 @@ GST_receive_callback (void *cls, case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != GST_validation_handle_hello (message)) { - GNUNET_break_op(0); - cancel_pending_blacklist_checks (address, session); + GNUNET_break_op (0); + cancel_pending_blacklist_checks (address, + session); } return ret; case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: @@ -448,8 +454,10 @@ GST_receive_callback (void *cls, address, session)) { - cancel_pending_blacklist_checks (address, session); - kill_session (plugin_name, session); + cancel_pending_blacklist_checks (address, + session); + kill_session (plugin_name, + session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: @@ -472,22 +480,29 @@ GST_receive_callback (void *cls, memcpy (blctx->msg, message, ntohs(message->size)); GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, blctx); if (NULL != (blc = GST_blacklist_test_allowed (&address->peer, NULL, - &connect_bl_check_cont, blctx))) + &connect_bl_check_cont, + blctx))) { blctx->blc = blc; } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK: - if (GNUNET_OK != GST_neighbours_handle_session_syn_ack (message, - &address->peer, address, session)) + if (GNUNET_OK != + GST_neighbours_handle_session_syn_ack (message, + &address->peer, + address, + session)) { cancel_pending_blacklist_checks (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK: - if (GNUNET_OK - != GST_neighbours_handle_session_ack (message, &address->peer, address, session)) + if (GNUNET_OK != + GST_neighbours_handle_session_ack (message, + &address->peer, + address, + session)) { GNUNET_break_op(0); cancel_pending_blacklist_checks (address, session); @@ -505,16 +520,26 @@ GST_receive_callback (void *cls, break; default: /* should be payload */ - GNUNET_STATISTICS_update (GST_stats, gettext_noop - ("# bytes payload received"), ntohs (message->size), GNUNET_NO); - GST_neighbours_notify_payload_recv (&address->peer, address, session, message); - ret = process_payload (&address->peer, address, session, message); + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# bytes payload received"), + ntohs (message->size), + GNUNET_NO); + GST_neighbours_notify_payload_recv (&address->peer, + address, + session, + message); + ret = process_payload (&address->peer, + address, + session, + message); break; } end: - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Allowing receive from peer %s to continue in %s\n", GNUNET_i2s (&address->peer), - GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Allowing receive from peer %s to continue in %s\n", + GNUNET_i2s (&address->peer), + GNUNET_STRINGS_relative_time_to_string (ret, + GNUNET_YES)); return ret; } @@ -552,9 +577,9 @@ plugin_env_address_change_notification (void *cls, } } - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "Transport now has %u addresses to communicate\n", - addresses); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Transport now has %u addresses to communicate\n", + addresses); GST_hello_modify_addresses (add_remove, address); } @@ -595,7 +620,8 @@ plugin_env_session_end (void *cls, "Notification from plugin `%s' about terminated %s session %p from peer `%s' address `%s'\n", address->transport_name, GNUNET_HELLO_address_check_option (address, - GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "outbound", session, + GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "outbound", + session, GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); @@ -839,10 +865,10 @@ neighbours_connect_notification (void *cls, struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf; connections++; - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "We are now connected to peer `%s' and %u peers in total\n", - GNUNET_i2s (peer), - connections); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "We are now connected to peer `%s' and %u peers in total\n", + GNUNET_i2s (peer), + connections); connect_msg->header.size = htons (sizeof(buf)); connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); connect_msg->id = *peer; @@ -866,9 +892,10 @@ neighbours_disconnect_notification (void *cls, struct DisconnectInfoMessage disconnect_msg; connections--; - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "Peer `%s' disconnected and we are connected to %u peers\n", - GNUNET_i2s (peer), connections); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Peer `%s' disconnected and we are connected to %u peers\n", + GNUNET_i2s (peer), + connections); GST_manipulation_peer_disconnect (peer); disconnect_msg.header.size = htons (sizeof(struct DisconnectInfoMessage)); diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c index e13bca139..48bd8cdf8 100644 --- a/src/transport/gnunet-service-transport_neighbours.c +++ b/src/transport/gnunet-service-transport_neighbours.c @@ -738,10 +738,10 @@ set_timeout (struct NeighbourMapEntry *n, */ static void set_alternative_address (struct NeighbourMapEntry *n, - const struct GNUNET_HELLO_Address *address, - struct Session *session, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) + const struct GNUNET_HELLO_Address *address, + struct Session *session, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { struct GNUNET_TRANSPORT_PluginFunctions *papi; diff --git a/src/transport/gnunet-service-transport_plugins.c b/src/transport/gnunet-service-transport_plugins.c index c029fcbc6..44e6a2a65 100644 --- a/src/transport/gnunet-service-transport_plugins.c +++ b/src/transport/gnunet-service-transport_plugins.c @@ -196,7 +196,7 @@ GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, } if (NULL == plug->api->check_address) { - fail = GNUNET_YES; + fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "check_address", @@ -204,7 +204,7 @@ GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, } if (NULL == plug->api->get_session) { - fail = GNUNET_YES; + fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "get_session", @@ -212,7 +212,7 @@ GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, } if (NULL == plug->api->get_network) { - fail = GNUNET_YES; + fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "get_network", @@ -220,7 +220,7 @@ GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, } if (NULL == plug->api->send) { - fail = GNUNET_YES; + fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "send", diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c index b3fe5c46b..7008d2df5 100644 --- a/src/transport/gnunet-service-transport_validation.c +++ b/src/transport/gnunet-service-transport_validation.c @@ -604,7 +604,6 @@ transmit_ping_if_allowed (void *cls, else { GNUNET_assert (NULL != papi->send); - GNUNET_assert (NULL != papi->get_session); struct Session *session = papi->get_session (papi->cls, ve->address); @@ -612,7 +611,8 @@ transmit_ping_if_allowed (void *cls, { ret = papi->send (papi->cls, session, message_buf, tsize, - PING_PRIORITY, ACCEPTABLE_PING_DELAY, + PING_PRIORITY, + ACCEPTABLE_PING_DELAY, NULL, NULL); network = papi->get_network (papi->cls, session); if (GNUNET_ATS_NET_UNSPECIFIED == network) diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index 89d270cc8..d59850f51 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c @@ -1743,7 +1743,8 @@ tcp_plugin_get_session (void *cls, LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to transmit to `%4s', creating fresh session using address `%s'.\n", - GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs)); + GNUNET_i2s (&address->peer), + GNUNET_a2s (sb, sbs)); session = create_session (plugin, address, diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c index 0589a24bd..dba8de2cb 100644 --- a/src/transport/plugin_transport_udp.c +++ b/src/transport/plugin_transport_udp.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - (C) 2010-2014 Christian Grothoff (and other contributing authors) + (C) 2010-2015 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 @@ -102,10 +102,10 @@ struct PrettyPrinterContext /** * Timeout task */ - struct GNUNET_SCHEDULER_Task * timeout_task; + struct GNUNET_SCHEDULER_Task *timeout_task; /** - * IPv6 address + * Is this an IPv6 address? */ int ipv6; @@ -155,7 +155,7 @@ struct Session /** * Session timeout task */ - struct GNUNET_SCHEDULER_Task * timeout_task; + struct GNUNET_SCHEDULER_Task *timeout_task; /** * When does this session time out? @@ -221,21 +221,11 @@ struct SourceInformation */ struct GNUNET_PeerIdentity sender; - /** - * Source address. - */ - const void *arg; - /** * Associated session. */ struct Session *session; - /** - * Number of bytes in source address. - */ - size_t args; - }; /** @@ -249,19 +239,19 @@ struct FindReceiveContext struct DefragContext *rc; /** - * Address to find. + * Session associated with this context. */ - const struct sockaddr *addr; + struct Session *session; /** - * + * Address to find. */ - struct Session *session; + const union UdpAddress *udp_addr; /** - * Number of bytes in @e addr. + * Number of bytes in @e udp_addr. */ - socklen_t addr_len; + size_t udp_addr_len; }; @@ -277,26 +267,43 @@ struct DefragContext */ struct GNUNET_DEFRAGMENT_Context *defrag; + /** + * Reference to master plugin struct. + */ + struct Plugin *plugin; + + /** + * Node in the defrag heap. + */ + struct GNUNET_CONTAINER_HeapNode *hnode; + + /** + * Who's message(s) are we defragmenting here? + * Only initialized once we succeeded and + * @e have_sender is set. + */ + struct GNUNET_PeerIdentity sender; + /** * Source address this receive context is for (allocated at the * end of the struct). */ - const struct sockaddr *src_addr; + const union UdpAddress *udp_addr; /** - * Reference to master plugin struct. + * Length of @e udp_addr. */ - struct Plugin *plugin; + size_t udp_addr_len; /** - * Node in the defrag heap. + * Network type the address belongs to. */ - struct GNUNET_CONTAINER_HeapNode *hnode; + enum GNUNET_ATS_Network_Type network_type; /** - * Length of @e src_addr. + * Has the @e sender field been initialized yet? */ - size_t addr_len; + int have_sender; }; @@ -464,7 +471,7 @@ struct UDP_MessageWrapper /** - * UDP ACK Message-Packet header (after defragmentation). + * UDP ACK Message-Packet header. */ struct UDP_ACK_Message { @@ -606,8 +613,8 @@ schedule_select (struct Plugin *plugin) * to override the address again. * * @param cls closure - * @param addr binary address - * @param addrlen length of the address + * @param addr binary address (a `union UdpAddress`) + * @param addrlen length of the @a addr * @return string representing the same address */ const char * @@ -651,8 +658,13 @@ udp_address_to_string (void *cls, inet_ntop (af, sb, buf, INET6_ADDRSTRLEN); GNUNET_snprintf (rbuf, sizeof(rbuf), - (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u", PLUGIN_NAME, options, - buf, port); + (af == AF_INET6) + ? "%s.%u.[%s]:%u" + : "%s.%u.%s:%u", + PLUGIN_NAME, + options, + buf, + port); return rbuf; } @@ -661,7 +673,7 @@ udp_address_to_string (void *cls, * Function called to convert a string address to * a binary address. * - * @param cls closure ('struct Plugin*') + * @param cls closure (`struct Plugin *`) * @param addr string address * @param addrlen length of the address * @param buf location to store the buffer @@ -822,7 +834,8 @@ append_port (void *cls, * @param cls closure with the `struct Plugin *` * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address - * the specific address format depends on the transport + * the specific address format depends on the transport; + * a `union UdpAddress` * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? @@ -1095,7 +1108,7 @@ check_port (struct Plugin *plugin, * traffic. * * @param cls closure, should be our handle to the Plugin - * @param addr pointer to the address + * @param addr pointer to a `union UdpAddress` * @param addrlen length of @a addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport, #GNUNET_SYSERR if not @@ -1285,7 +1298,7 @@ fragmented_message_done (struct UDP_FragmentationContext *fc, * * @param cls the `struct FindReceiveContext` * @param node internal node of the heap - * @param element value stored at the node (a 'struct ReceiveContext') + * @param element value stored at the node (a `struct ReceiveContext`) * @param cost cost associated with the node * @return #GNUNET_YES if we should continue to iterate, * #GNUNET_NO if not. @@ -1299,8 +1312,10 @@ find_receive_context (void *cls, struct FindReceiveContext *frc = cls; struct DefragContext *e = element; - if ((frc->addr_len == e->addr_len) - && (0 == memcmp (frc->addr, e->src_addr, frc->addr_len))) + if ( (frc->udp_addr_len == e->udp_addr_len) && + (0 == memcmp (frc->udp_addr, + e->udp_addr, + frc->udp_addr_len)) ) { frc->rc = e; return GNUNET_NO; @@ -1328,12 +1343,12 @@ udp_disconnect_session (void *cls, struct FindReceiveContext frc; GNUNET_assert (GNUNET_YES != s->in_destroy); - LOG(GNUNET_ERROR_TYPE_DEBUG, - "Session %p to peer `%s' address ended\n", s, - GNUNET_i2s (&s->target), - udp_address_to_string (NULL, - s->address->address, - s->address->address_length)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Session %p to peer `%s' address ended\n", s, + GNUNET_i2s (&s->target), + udp_address_to_string (NULL, + s->address->address, + s->address->address_length)); /* stop timeout task */ if (NULL != s->timeout_task) { @@ -1343,12 +1358,13 @@ udp_disconnect_session (void *cls, if (NULL != s->frag_ctx) { /* Remove fragmented message due to disconnect */ - fragmented_message_done (s->frag_ctx, GNUNET_SYSERR); + fragmented_message_done (s->frag_ctx, + GNUNET_SYSERR); } frc.rc = NULL; - frc.addr = s->address->address; - frc.addr_len = s->address->address_length; + frc.udp_addr = s->address->address; + frc.udp_addr_len = s->address->address_length; /* Lookup existing receive context for this address */ if (NULL != plugin->defrag_ctxs) { @@ -1555,8 +1571,8 @@ create_session (struct Plugin *plugin, s->plugin = plugin; s->address = GNUNET_HELLO_address_copy (address); s->target = address->peer; - s->last_expected_ack_delay = GNUNET_TIME_relative_multiply ( - GNUNET_TIME_UNIT_MILLISECONDS, 250); + s->last_expected_ack_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, + 250); s->last_expected_msg_delay = GNUNET_TIME_UNIT_MILLISECONDS; s->flow_delay_from_other_peer = GNUNET_TIME_UNIT_ZERO_ABS; s->flow_delay_for_other_peer = GNUNET_TIME_UNIT_ZERO; @@ -1634,20 +1650,21 @@ session_cmp_it (void *cls, /** - * Creates a new outbound session the transport service will use to - * send data to the peer + * Locate an existing session the transport service is using to + * send data to another peer. Performs some basic sanity checks + * on the address and then tries to locate a matching session. * * @param cls the plugin - * @param address the address - * @return the session or NULL of max connections exceeded + * @param address the address we should locate the session by + * @return the session if it exists, or NULL if it is not found */ static struct Session * udp_plugin_lookup_session (void *cls, const struct GNUNET_HELLO_Address *address) { - struct Plugin * plugin = cls; - struct IPv6UdpAddress *udp_a6; - struct IPv4UdpAddress *udp_a4; + struct Plugin *plugin = cls; + const struct IPv6UdpAddress *udp_a6; + const struct IPv4UdpAddress *udp_a4; struct SessionCompareContext cctx; if ( (NULL == address->address) || @@ -1655,7 +1672,7 @@ udp_plugin_lookup_session (void *cls, (address->address_length != sizeof (struct IPv6UdpAddress)))) { LOG (GNUNET_ERROR_TYPE_WARNING, - _("Trying to create session for address of unexpected length %u (should be %u or %u)\n"), + _("Trying to locate session for address of unexpected length %u (should be %u or %u)\n"), address->address_length, sizeof (struct IPv4UdpAddress), sizeof (struct IPv6UdpAddress)); @@ -1664,19 +1681,19 @@ udp_plugin_lookup_session (void *cls, if (address->address_length == sizeof(struct IPv4UdpAddress)) { - if (plugin->sockv4 == NULL) + if (NULL == plugin->sockv4) return NULL; - udp_a4 = (struct IPv4UdpAddress *) address->address; - if (udp_a4->u4_port == 0) + udp_a4 = (const struct IPv4UdpAddress *) address->address; + if (0 == udp_a4->u4_port) return NULL; } if (address->address_length == sizeof(struct IPv6UdpAddress)) { - if (plugin->sockv6 == NULL) + if (NULL == plugin->sockv6) return NULL; - udp_a6 = (struct IPv6UdpAddress *) address->address; - if (udp_a6->u6_port == 0) + udp_a6 = (const struct IPv6UdpAddress *) address->address; + if (0 == udp_a6->u6_port) return NULL; } @@ -1689,7 +1706,7 @@ udp_plugin_lookup_session (void *cls, udp_address_to_string(NULL, address->address, address->address_length)); GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessions, &address->peer, - session_cmp_it, + &session_cmp_it, &cctx); if (NULL != cctx.res) { @@ -1703,144 +1720,37 @@ udp_plugin_lookup_session (void *cls, /** - * Context to lookup a session based on a IP address - */ -struct LookupContext -{ - /** - * The result - */ - struct Session *res; - - /** - * The socket address - */ - const struct sockaddr *address; - - /** - * The socket address length - */ - size_t addr_len; - - /** - * Is a fragmentation context required for the session - */ - int must_have_frag_ctx; -}; - - -/** - * Find a session with a matching address. - * FIXME: very similar code to #udp_plugin_lookup_session() above. - * Unify? + * Allocate a new session for the given endpoint address. + * Note that this function does not inform the service + * of the new session, this is the responsibility of the + * caller (if needed). * - * @param cls the `struct LookupContext *` - * @param key peer identity (unused) - * @param value the `struct Session *` - * @return #GNUNET_NO if we found the session, #GNUNET_OK if not + * @param cls the `struct Plugin` + * @param address address of the other peer to use + * @param network_type network type the address belongs to + * @return NULL on error, otherwise session handle */ -static int -lookup_session_by_sockaddr_it (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct LookupContext *l_ctx = cls; - struct Session *s = value; - struct IPv4UdpAddress u4; - struct IPv6UdpAddress u6; - void *arg; - size_t args; - - /* convert address */ - switch (l_ctx->address->sa_family) - { - case AF_INET: - GNUNET_assert(l_ctx->addr_len == sizeof(struct sockaddr_in)); - memset (&u4, 0, sizeof(u4)); - u6.options = htonl (0); - u4.ipv4_addr = ((struct sockaddr_in *) l_ctx->address)->sin_addr.s_addr; - u4.u4_port = ((struct sockaddr_in *) l_ctx->address)->sin_port; - arg = &u4; - args = sizeof(u4); - break; - case AF_INET6: - GNUNET_assert(l_ctx->addr_len == sizeof(struct sockaddr_in6)); - memset (&u6, 0, sizeof(u6)); - u6.options = htonl (0); - u6.ipv6_addr = ((struct sockaddr_in6 *) l_ctx->address)->sin6_addr; - u6.u6_port = ((struct sockaddr_in6 *) l_ctx->address)->sin6_port; - arg = &u6; - args = sizeof(u6); - break; - default: - GNUNET_break(0); - return GNUNET_YES; - } - if ( (GNUNET_YES == l_ctx->must_have_frag_ctx) && - (NULL == s->frag_ctx)) - return GNUNET_YES; - - /* Does not compare peer identities but addresses */ - if ((args == s->address->address_length) && - (0 == memcmp (arg, s->address->address, args))) - { - l_ctx->res = s; - return GNUNET_NO; - } - return GNUNET_YES; -} - - static struct Session * udp_plugin_create_session (void *cls, - const struct GNUNET_HELLO_Address *address) + const struct GNUNET_HELLO_Address *address, + enum GNUNET_ATS_Network_Type network_type) { struct Plugin *plugin = cls; struct Session *s; - struct IPv4UdpAddress *udp_v4; - struct IPv6UdpAddress *udp_v6; s = create_session (plugin, address); - if (sizeof (struct IPv4UdpAddress) == address->address_length) - { - struct sockaddr_in v4; - - udp_v4 = (struct IPv4UdpAddress *) address->address; - memset (&v4, '\0', sizeof (v4)); - v4.sin_family = AF_INET; -#if HAVE_SOCKADDR_IN_SIN_LEN - v4.sin_len = sizeof (struct sockaddr_in); -#endif - v4.sin_port = udp_v4->u4_port; - v4.sin_addr.s_addr = udp_v4->ipv4_addr; - s->ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); - s->ats.value = htonl (plugin->env->get_address_type (plugin->env->cls, - (const struct sockaddr *) &v4, - sizeof (v4))); - } - else if (sizeof (struct IPv6UdpAddress) == address->address_length) - { - struct sockaddr_in6 v6; - udp_v6 = (struct IPv6UdpAddress *) address->address; - memset (&v6, '\0', sizeof (v6)); - v6.sin6_family = AF_INET6; -#if HAVE_SOCKADDR_IN_SIN_LEN - v6.sin6_len = sizeof (struct sockaddr_in6); -#endif - v6.sin6_port = udp_v6->u6_port; - v6.sin6_addr = udp_v6->ipv6_addr; - s->ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); - s->ats.value = htonl (plugin->env->get_address_type (plugin->env->cls, - (const struct sockaddr *) &v6, - sizeof (v6))); - } + s->ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); + s->ats.value = htonl (network_type); if (NULL == s) return NULL; /* protocol not supported or address invalid */ - LOG(GNUNET_ERROR_TYPE_DEBUG, - "Creating new session %p for peer `%s' address `%s'\n", - s, GNUNET_i2s (&address->peer), - udp_address_to_string( NULL,address->address,address->address_length)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Creating new session %p for peer `%s' address `%s'\n", + s, + GNUNET_i2s (&address->peer), + udp_address_to_string (plugin, + address->address, + address->address_length)); GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (plugin->sessions, &s->target, @@ -1884,8 +1794,8 @@ udp_plugin_update_session_timeout (void *cls, /** - * Creates a new outbound session the transport service will use to send data to the - * peer + * Creates a new outbound session the transport service will use to + * send data to the peer. * * @param cls the plugin * @param address the address @@ -1895,7 +1805,11 @@ static struct Session * udp_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { + struct Plugin *plugin = cls; struct Session *s; + enum GNUNET_ATS_Network_Type network_type; + struct IPv4UdpAddress *udp_v4; + struct IPv6UdpAddress *udp_v6; if (NULL == address) { @@ -1905,11 +1819,45 @@ udp_plugin_get_session (void *cls, if ( (address->address_length != sizeof(struct IPv4UdpAddress)) && (address->address_length != sizeof(struct IPv6UdpAddress)) ) return NULL; + if (NULL != (s = udp_plugin_lookup_session (cls, + address))) + return s; + + if (sizeof (struct IPv4UdpAddress) == address->address_length) + { + struct sockaddr_in v4; + + udp_v4 = (struct IPv4UdpAddress *) address->address; + memset (&v4, '\0', sizeof (v4)); + v4.sin_family = AF_INET; +#if HAVE_SOCKADDR_IN_SIN_LEN + v4.sin_len = sizeof (struct sockaddr_in); +#endif + v4.sin_port = udp_v4->u4_port; + v4.sin_addr.s_addr = udp_v4->ipv4_addr; + network_type = plugin->env->get_address_type (plugin->env->cls, + (const struct sockaddr *) &v4, + sizeof (v4)); + } + else if (sizeof (struct IPv6UdpAddress) == address->address_length) + { + struct sockaddr_in6 v6; + + udp_v6 = (struct IPv6UdpAddress *) address->address; + memset (&v6, '\0', sizeof (v6)); + v6.sin6_family = AF_INET6; +#if HAVE_SOCKADDR_IN_SIN_LEN + v6.sin6_len = sizeof (struct sockaddr_in6); +#endif + v6.sin6_port = udp_v6->u6_port; + v6.sin6_addr = udp_v6->ipv6_addr; + network_type = plugin->env->get_address_type (plugin->env->cls, + (const struct sockaddr *) &v6, + sizeof (v6)); + } /* otherwise create new */ - if (NULL != (s = udp_plugin_lookup_session (cls, address))) - return s; - return udp_plugin_create_session (cls, address); + return udp_plugin_create_session (cls, address, network_type); } @@ -2258,7 +2206,7 @@ process_inbound_tokenized_messages (void *cls, struct SourceInformation *si = client; struct GNUNET_TIME_Relative delay; - GNUNET_assert(si->session != NULL); + GNUNET_assert (NULL != si->session); if (GNUNET_YES == si->session->in_destroy) return GNUNET_OK; /* setup ATS */ @@ -2282,22 +2230,20 @@ process_inbound_tokenized_messages (void *cls, * * @param plugin plugin context * @param msg the message - * @param sender_addr sender address - * @param sender_addr_len number of bytes in @a sender_addr + * @param udp_addr sender address + * @param udp_addr_len number of bytes in @a udp_addr + * @param network_type network type the address belongs to */ static void process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg, - const struct sockaddr *sender_addr, - socklen_t sender_addr_len) + const union UdpAddress *udp_addr, + size_t udp_addr_len, + enum GNUNET_ATS_Network_Type network_type) { struct SourceInformation si; - struct Session * s; + struct Session *s; struct GNUNET_HELLO_Address *address; - struct IPv4UdpAddress u4; - struct IPv6UdpAddress u6; - const void *arg; - size_t args; if (0 != ntohl (msg->reserved)) { @@ -2311,42 +2257,16 @@ process_udp_message (struct Plugin *plugin, return; } - /* convert address */ - switch (sender_addr->sa_family) - { - case AF_INET: - GNUNET_assert(sender_addr_len == sizeof(struct sockaddr_in)); - memset (&u4, 0, sizeof(u4)); - u6.options = htonl (0); - u4.ipv4_addr = ((struct sockaddr_in *) sender_addr)->sin_addr.s_addr; - u4.u4_port = ((struct sockaddr_in *) sender_addr)->sin_port; - arg = &u4; - args = sizeof(u4); - break; - case AF_INET6: - GNUNET_assert(sender_addr_len == sizeof(struct sockaddr_in6)); - memset (&u6, 0, sizeof(u6)); - u6.options = htonl (0); - u6.ipv6_addr = ((struct sockaddr_in6 *) sender_addr)->sin6_addr; - u6.u6_port = ((struct sockaddr_in6 *) sender_addr)->sin6_port; - arg = &u6; - args = sizeof(u6); - break; - default: - GNUNET_break(0); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received message with %u bytes from peer `%s' at `%s'\n", - (unsigned int ) ntohs (msg->header.size), GNUNET_i2s (&msg->sender), - GNUNET_a2s (sender_addr, sender_addr_len)); - - address = GNUNET_HELLO_address_allocate (&msg->sender, PLUGIN_NAME, - arg, args, + address = GNUNET_HELLO_address_allocate (&msg->sender, + PLUGIN_NAME, + udp_addr, + udp_addr_len, GNUNET_HELLO_ADDRESS_INFO_NONE); if (NULL == (s = udp_plugin_lookup_session (plugin, address))) { - s = udp_plugin_create_session (plugin, address); + s = udp_plugin_create_session (plugin, + address, + network_type); plugin->env->session_start (plugin->env->cls, address, s, NULL, 0); notify_session_monitor (s->plugin, @@ -2361,8 +2281,6 @@ process_udp_message (struct Plugin *plugin, /* iterate over all embedded messages */ si.session = s; si.sender = msg->sender; - si.arg = arg; - si.args = args; s->rc++; GNUNET_SERVER_mst_receive (plugin->mst, &si, @@ -2387,6 +2305,7 @@ fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg) { struct DefragContext *rc = cls; + const struct UDPMessage *um; if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE) { @@ -2398,10 +2317,14 @@ fragment_msg_proc (void *cls, GNUNET_break(0); return; } + um = (const struct UDPMessage *) msg; + rc->sender = um->sender; + rc->have_sender = GNUNET_YES; process_udp_message (rc->plugin, - (const struct UDPMessage *) msg, - rc->src_addr, - rc->addr_len); + um, + rc->udp_addr, + rc->udp_addr_len, + rc->network_type); } @@ -2423,26 +2346,32 @@ ack_proc (void *cls, uint32_t delay = 0; struct UDP_MessageWrapper *udpw; struct Session *s; - struct LookupContext l_ctx; - - l_ctx.address = rc->src_addr; - l_ctx.addr_len = rc->addr_len; - l_ctx.must_have_frag_ctx = GNUNET_NO; - l_ctx.res = NULL; - GNUNET_CONTAINER_multipeermap_iterate (rc->plugin->sessions, - &lookup_session_by_sockaddr_it, - &l_ctx); - s = l_ctx.res; + struct GNUNET_HELLO_Address *address; + + if (GNUNET_NO == rc->have_sender) + { + /* tried to defragment but never succeeded, hence will not ACK */ + GNUNET_break_op (0); + return; + } + address = GNUNET_HELLO_address_allocate (&rc->sender, + PLUGIN_NAME, + rc->udp_addr, + rc->udp_addr_len, + GNUNET_HELLO_ADDRESS_INFO_NONE); + s = udp_plugin_lookup_session (rc->plugin, + address); + GNUNET_HELLO_address_free (address); if (NULL == s) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Trying to transmit ACK to peer `%s' but not session found!\n", - GNUNET_a2s(rc->src_addr, rc->addr_len)); - + "Trying to transmit ACK to peer `%s' but no session found!\n", + udp_address_to_string (rc->plugin, + rc->udp_addr, + rc->udp_addr_len)); GNUNET_CONTAINER_heap_remove_node (rc->hnode); GNUNET_DEFRAGMENT_context_destroy (rc->defrag); GNUNET_free (rc); - return; } if (s->flow_delay_for_other_peer.rel_value_us <= UINT32_MAX) @@ -2450,7 +2379,9 @@ ack_proc (void *cls, LOG (GNUNET_ERROR_TYPE_DEBUG, "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)), + udp_address_to_string (rc->plugin, + rc->udp_addr, + rc->udp_addr_len), GNUNET_STRINGS_relative_time_to_string (s->flow_delay_for_other_peer, GNUNET_YES)); udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + msize); @@ -2475,38 +2406,22 @@ ack_proc (void *cls, /** - * FIXME. - */ -static void -read_process_msg (struct Plugin *plugin, - const struct GNUNET_MessageHeader *msg, - const struct sockaddr *addr, - socklen_t fromlen) -{ - if (ntohs (msg->size) < sizeof(struct UDPMessage)) - { - GNUNET_break_op(0); - return; - } - process_udp_message (plugin, - (const struct UDPMessage *) msg, - addr, - fromlen); -} - - -/** - * FIXME. + * Handle an ACK message. + * + * @param plugin the UDP plugin + * @param msg the (presumed) UDP ACK message + * @param udp_addr sender address + * @param udp_addr_len number of bytes in @a udp_addr */ static void read_process_ack (struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, - const struct sockaddr *addr, - socklen_t fromlen) + const union UdpAddress *udp_addr, + socklen_t udp_addr_len) { const struct GNUNET_MessageHeader *ack; const struct UDP_ACK_Message *udp_ack; - struct LookupContext l_ctx; + struct GNUNET_HELLO_Address *address; struct Session *s; struct GNUNET_TIME_Relative flow_delay; @@ -2517,23 +2432,27 @@ read_process_ack (struct Plugin *plugin, return; } udp_ack = (const struct UDP_ACK_Message *) msg; - - /* Lookup session based on sockaddr */ - l_ctx.address = addr; - l_ctx.addr_len = fromlen; - l_ctx.res = NULL; - l_ctx.must_have_frag_ctx = GNUNET_YES; - GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, - &lookup_session_by_sockaddr_it, &l_ctx); - s = l_ctx.res; - if ((NULL == s) || (NULL == s->frag_ctx)) + address = GNUNET_HELLO_address_allocate (&udp_ack->sender, + PLUGIN_NAME, + udp_addr, + udp_addr_len, + GNUNET_HELLO_ADDRESS_INFO_NONE); + s = udp_plugin_lookup_session (plugin, + address); + GNUNET_HELLO_address_free (address); + if ( (NULL == s) || + (NULL == s->frag_ctx) ) { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "UDP session for ACK not found\n"); return; } 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)); + 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); ack = (const struct GNUNET_MessageHeader *) &udp_ack[1]; @@ -2543,92 +2462,120 @@ read_process_ack (struct Plugin *plugin, return; } - if (0 - != memcmp (&l_ctx.res->target, &udp_ack->sender, - sizeof(struct GNUNET_PeerIdentity))) - GNUNET_break(0); - if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (s->frag_ctx->frag, ack)) + if (GNUNET_OK != + GNUNET_FRAGMENT_process_ack (s->frag_ctx->frag, + ack)) { 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 (addr, fromlen)); + (unsigned int ) ntohs (msg->size), + GNUNET_i2s (&udp_ack->sender), + udp_address_to_string (plugin, + udp_addr, + udp_addr_len)); /* Expect more ACKs to arrive */ return; } - LOG(GNUNET_ERROR_TYPE_DEBUG, "Message full ACK'ed\n", - (unsigned int ) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender), - GNUNET_a2s (addr, fromlen)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Message full ACK'ed\n", + (unsigned int ) ntohs (msg->size), + GNUNET_i2s (&udp_ack->sender), + udp_address_to_string (plugin, + udp_addr, + udp_addr_len)); + /* Remove fragmented message after successful sending */ - fragmented_message_done (s->frag_ctx, GNUNET_OK); + fragmented_message_done (s->frag_ctx, + GNUNET_OK); } /** - * FIXME. + * We received a fragment, process it. + * + * @param plugin our plugin + * @param msg a message of type #GNUNET_MESSAGE_TYPE_FRAGMENT + * @param udp_addr sender address + * @param udp_addr_len number of bytes in @a udp_addr + * @param network_type network type the address belongs to */ static void read_process_fragment (struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, - const struct sockaddr *addr, - socklen_t fromlen) + const union UdpAddress *udp_addr, + size_t udp_addr_len, + enum GNUNET_ATS_Network_Type network_type) { struct DefragContext *d_ctx; struct GNUNET_TIME_Absolute now; struct FindReceiveContext frc; frc.rc = NULL; - frc.addr = addr; - frc.addr_len = fromlen; + frc.udp_addr = udp_addr; + frc.udp_addr_len = udp_addr_len; - LOG(GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n", - (unsigned int ) ntohs (msg->size), GNUNET_a2s (addr, fromlen)); /* Lookup existing receive context for this address */ GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs, - &find_receive_context, &frc); + &find_receive_context, + &frc); now = GNUNET_TIME_absolute_get (); d_ctx = frc.rc; - if (d_ctx == NULL ) + if (NULL == d_ctx) { /* Create a new defragmentation context */ - d_ctx = GNUNET_malloc (sizeof (struct DefragContext) + fromlen); - memcpy (&d_ctx[1], addr, fromlen); - d_ctx->src_addr = (const struct sockaddr *) &d_ctx[1]; - d_ctx->addr_len = fromlen; + d_ctx = GNUNET_malloc (sizeof (struct DefragContext) + udp_addr_len); + memcpy (&d_ctx[1], + udp_addr, + udp_addr_len); + d_ctx->udp_addr = (const union UdpAddress *) &d_ctx[1]; + d_ctx->udp_addr_len = udp_addr_len; + d_ctx->network_type = network_type; d_ctx->plugin = plugin; d_ctx->defrag = GNUNET_DEFRAGMENT_context_create (plugin->env->stats, - UDP_MTU, UDP_MAX_MESSAGES_IN_DEFRAG, d_ctx, &fragment_msg_proc, - &ack_proc); - d_ctx->hnode = GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs, d_ctx, + UDP_MTU, + UDP_MAX_MESSAGES_IN_DEFRAG, + d_ctx, + &fragment_msg_proc, + &ack_proc); + d_ctx->hnode = GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs, + d_ctx, (GNUNET_CONTAINER_HeapCostType) 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 (addr, fromlen)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Created new defragmentation context for %u-byte fragment from `%s'\n", + (unsigned int ) ntohs (msg->size), + udp_address_to_string (plugin, + udp_addr, + udp_addr_len)); } else { - LOG(GNUNET_ERROR_TYPE_DEBUG, - "Found existing defragmentation context for %u-byte fragment from `%s'\n", - (unsigned int ) ntohs (msg->size), GNUNET_a2s (addr, fromlen)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Found existing defragmentation context for %u-byte fragment from `%s'\n", + (unsigned int ) ntohs (msg->size), + udp_address_to_string (plugin, + udp_addr, + udp_addr_len)); } - if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (d_ctx->defrag, msg)) + if (GNUNET_OK == + GNUNET_DEFRAGMENT_process_fragment (d_ctx->defrag, msg)) { /* keep this 'rc' from expiring */ - GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs, d_ctx->hnode, + GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs, + d_ctx->hnode, (GNUNET_CONTAINER_HeapCostType) now.abs_value_us); } if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) > - UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG) + UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG) { /* remove 'rc' that was inactive the longest */ d_ctx = GNUNET_CONTAINER_heap_remove_root (plugin->defrag_ctxs); - GNUNET_assert(NULL != d_ctx); + GNUNET_assert (NULL != d_ctx); GNUNET_DEFRAGMENT_context_destroy (d_ctx->defrag); - GNUNET_free(d_ctx); + GNUNET_free (d_ctx); } } @@ -2648,11 +2595,20 @@ udp_select_read (struct Plugin *plugin, char buf[65536] GNUNET_ALIGN; ssize_t size; const struct GNUNET_MessageHeader *msg; + struct IPv4UdpAddress v4; + struct IPv6UdpAddress v6; + const struct sockaddr *sa; + const struct sockaddr_in *sa4; + const struct sockaddr_in6 *sa6; + const union UdpAddress *int_addr; + size_t int_addr_len; + enum GNUNET_ATS_Network_Type network_type; fromlen = sizeof(addr); memset (&addr, 0, sizeof(addr)); size = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof(buf), (struct sockaddr *) &addr, &fromlen); + sa = (const struct sockaddr *) &addr; #if MINGW /* On SOCK_DGRAM UDP sockets recvfrom might fail with a * WSAECONNRESET error to indicate that previous sendto() (yes, sendto!) @@ -2680,50 +2636,94 @@ udp_select_read (struct Plugin *plugin, LOG (GNUNET_ERROR_TYPE_WARNING, "UDP got %u bytes from %s, which is not enough for a GNUnet message header\n", (unsigned int ) size, - GNUNET_a2s ((const struct sockaddr *) &addr, fromlen)); + GNUNET_a2s (sa, fromlen)); /* _MAY_ be a connection failure (got partial message) */ /* But it _MAY_ also be that the other side uses non-GNUnet protocol. */ GNUNET_break_op(0); return; } msg = (const struct GNUNET_MessageHeader *) buf; - LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP received %u-byte message from `%s' type %u\n", (unsigned int) size, - GNUNET_a2s ((const struct sockaddr *) &addr, fromlen), + GNUNET_a2s (sa, + fromlen), ntohs (msg->type)); - if (size != ntohs (msg->size)) { LOG (GNUNET_ERROR_TYPE_WARNING, "UDP malformed message header from %s\n", - (unsigned int ) size, - GNUNET_a2s ((const struct sockaddr *) &addr, fromlen)); - GNUNET_break_op(0); + (unsigned int) size, + GNUNET_a2s (sa, + fromlen)); + GNUNET_break_op (0); return; } GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes, received", size, GNUNET_NO); + network_type = plugin->env->get_address_type (plugin->env->cls, + sa, + fromlen); + switch (sa->sa_family) + { + case AF_INET: + sa4 = (const struct sockaddr_in *) &addr; + v4.options = 0; + v4.ipv4_addr = sa4->sin_addr.s_addr; + v4.u4_port = sa4->sin_port; + int_addr = (union UdpAddress *) &v4; + int_addr_len = sizeof (v4); + break; + case AF_INET6: + sa6 = (const struct sockaddr_in6 *) &addr; + v6.options = 0; + v6.ipv6_addr = sa6->sin6_addr; + v6.u6_port = sa6->sin6_port; + int_addr = (union UdpAddress *) &v6; + int_addr_len = sizeof (v6); + break; + default: + GNUNET_break (0); + return; + } switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON: if (GNUNET_YES == plugin->enable_broadcasting_receiving) - udp_broadcast_receive (plugin, buf, size, (const struct sockaddr *) &addr, - fromlen); + udp_broadcast_receive (plugin, + buf, + size, + int_addr, + int_addr_len, + network_type); return; case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE: - read_process_msg (plugin, msg, (const struct sockaddr *) &addr, fromlen); + if (ntohs (msg->size) < sizeof(struct UDPMessage)) + { + GNUNET_break_op(0); + return; + } + process_udp_message (plugin, + (const struct UDPMessage *) msg, + int_addr, + int_addr_len, + network_type); return; case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK: - read_process_ack (plugin, msg, (const struct sockaddr *) &addr, fromlen); + read_process_ack (plugin, + msg, + int_addr, + int_addr_len); return; case GNUNET_MESSAGE_TYPE_FRAGMENT: - read_process_fragment (plugin, msg, (const struct sockaddr *) &addr, - fromlen); + read_process_fragment (plugin, + msg, + int_addr, + int_addr_len, + network_type); return; default: GNUNET_break_op(0); @@ -3008,15 +3008,21 @@ udp_select_send (struct Plugin *plugin, else { /* Success */ - LOG(GNUNET_ERROR_TYPE_DEBUG, - "UDP transmitted %u-byte message to `%s' `%s' (%d: %s)\n", - (unsigned int ) (udpw->msg_size), GNUNET_i2s (&udpw->session->target), - GNUNET_a2s (a, slen), (int ) sent, - (sent < 0) ? STRERROR (errno) : "ok"); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "UDP transmitted %u-byte message to `%s' `%s' (%d: %s)\n", + (unsigned int) (udpw->msg_size), + GNUNET_i2s (&udpw->session->target), + GNUNET_a2s (a, slen), + (int ) sent, + (sent < 0) ? STRERROR (errno) : "ok"); GNUNET_STATISTICS_update (plugin->env->stats, - "# UDP, total, bytes, sent, success", sent, GNUNET_NO); + "# UDP, total, bytes, sent, success", + sent, + GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, - "# UDP, total, messages, sent, success", 1, GNUNET_NO); + "# UDP, total, messages, sent, success", + 1, + GNUNET_NO); if (NULL != udpw->frag_ctx) udpw->frag_ctx->on_wire_size += udpw->msg_size; call_continuation (udpw, GNUNET_OK); @@ -3233,8 +3239,10 @@ setup_sockets (struct Plugin *plugin, GNUNET_a2s (server_addr, addrlen)); /* binding */ - if (GNUNET_OK - == GNUNET_NETWORK_socket_bind (plugin->sockv4, server_addr, addrlen)) + if (GNUNET_OK == + GNUNET_NETWORK_socket_bind (plugin->sockv4, + server_addr, + addrlen)) break; eno = errno; if (0 != plugin->port) @@ -3259,8 +3267,9 @@ setup_sockets (struct Plugin *plugin, if (NULL != plugin->sockv4) { - LOG(GNUNET_ERROR_TYPE_DEBUG, "IPv4 socket created on port %s\n", - GNUNET_a2s (server_addr, addrlen)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "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++; @@ -3276,7 +3285,8 @@ setup_sockets (struct Plugin *plugin, if (0 == sockets_created) { - LOG(GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n")); + LOG (GNUNET_ERROR_TYPE_WARNING, + _("Failed to open UDP sockets\n")); return 0; /* No sockets created, return */ } @@ -3425,11 +3435,13 @@ libgnunet_plugin_transport_udp_init (void *cls) /* Get port number: port == 0 : autodetect a port, * > 0 : use this port, not given : 2086 default */ if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", + GNUNET_CONFIGURATION_get_value_number (env->cfg, + "transport-udp", "PORT", &port)) port = 2086; if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", + GNUNET_CONFIGURATION_get_value_number (env->cfg, + "transport-udp", "ADVERTISED_PORT", &aport)) aport = port; if (port > 65535) diff --git a/src/transport/plugin_transport_udp.h b/src/transport/plugin_transport_udp.h index 2e77b9010..88a3a9997 100644 --- a/src/transport/plugin_transport_udp.h +++ b/src/transport/plugin_transport_udp.h @@ -102,6 +102,23 @@ struct IPv6UdpAddress }; GNUNET_NETWORK_STRUCT_END +/** + * Either an IPv4 or IPv6 UDP address. Note that without a "length", + * one cannot tell which one of the two types this address represents. + */ +union UdpAddress +{ + /** + * IPv4 case. + */ + struct IPv4UdpAddress v4; + + /** + * IPv6 case. + */ + struct IPv6UdpAddress v6; +}; + /** * UDP Message-Packet header (after defragmentation). @@ -155,12 +172,12 @@ struct Plugin /** * ID of select task for IPv4 */ - struct GNUNET_SCHEDULER_Task * select_task; + struct GNUNET_SCHEDULER_Task *select_task; /** * ID of select task for IPv6 */ - struct GNUNET_SCHEDULER_Task * select_task_v6; + struct GNUNET_SCHEDULER_Task *select_task_v6; /** * Tokenizer for inbound messages. @@ -218,14 +235,9 @@ struct Plugin struct GNUNET_NETWORK_Handle *sockv6; /** - * Tokenizer for inbound IPv6 messages. - */ - struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv6_mst; - - /** - * Tokenizer for inbound IPv4 messages. + * Tokenizer for inbound messages. */ - struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv4_mst; + struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_mst; /** * Head of DLL of broadcast addresses @@ -336,20 +348,37 @@ struct Plugin const char * -udp_address_to_string (void *cls, const void *addr, size_t addrlen); +udp_address_to_string (void *cls, + const void *addr, + size_t addrlen); + +/** + * We received a broadcast message. Process it and all subsequent + * messages in the same packet. + * + * @param plugin the UDP plugin + * @param buf the buffer with the message(s) + * @param size number of bytes in @a buf + * @param udp_addr address of the sender + * @param udp_addr_len number of bytes in @a udp_addr + * @param network_type network type of the sender's address + */ void udp_broadcast_receive (struct Plugin *plugin, - const char * buf, + const char *buf, ssize_t size, - const struct sockaddr *addr, - size_t addrlen); + const union UdpAddress *udp_addr, + size_t udp_addr_len, + enum GNUNET_ATS_Network_Type network_type); + void setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4); + void stop_broadcast (struct Plugin *plugin); diff --git a/src/transport/plugin_transport_udp_broadcasting.c b/src/transport/plugin_transport_udp_broadcasting.c index 814328f48..767bddff4 100644 --- a/src/transport/plugin_transport_udp_broadcasting.c +++ b/src/transport/plugin_transport_udp_broadcasting.c @@ -88,7 +88,7 @@ struct BroadcastAddress struct Plugin *plugin; - void *addr; + struct sockaddr *addr; socklen_t addrlen; @@ -106,24 +106,16 @@ struct BroadcastAddress }; -struct Mstv4Context +/** + * Client-specific context for #broadcast_mst_cb(). + */ +struct MstContext { struct Plugin *plugin; - struct IPv4UdpAddress addr; - - /** - * ATS network type. - */ - enum GNUNET_ATS_Network_Type ats_address_network_type; -}; - - -struct Mstv6Context -{ - struct Plugin *plugin; + const union UdpAddress *udp_addr; - struct IPv6UdpAddress addr; + size_t udp_addr_len; /** * ATS network type. @@ -132,56 +124,21 @@ struct Mstv6Context }; +/** + * Parse broadcast message received. + * + * @param cls the `struct Plugin` + * @param client the `struct MstContext` with sender address + * @param message the message we received + * @return #GNUNET_OK (always) + */ static int -broadcast_ipv6_mst_cb (void *cls, void *client, - const struct GNUNET_MessageHeader *message) -{ - struct Plugin *plugin = cls; - struct Mstv6Context *mc = client; - struct GNUNET_HELLO_Address *address; - const struct GNUNET_MessageHeader *hello; - const struct UDP_Beacon_Message *msg; - struct GNUNET_ATS_Information atsi; - - msg = (const struct UDP_Beacon_Message *) message; - - if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON != - ntohs (msg->header.type)) - return GNUNET_OK; - 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))); - - /* setup ATS */ - atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); - atsi.value = htonl (mc->ats_address_network_type); - GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); - - hello = (struct GNUNET_MessageHeader *) &msg[1]; - address = GNUNET_HELLO_address_allocate (&msg->sender, PLUGIN_NAME, - (const char *) &mc->addr, - sizeof (mc->addr), - GNUNET_HELLO_ADDRESS_INFO_NONE); - plugin->env->receive (plugin->env->cls, address, NULL, hello); - plugin->env->update_address_metrics (plugin->env->cls, address, - NULL, &atsi, 1); - GNUNET_HELLO_address_free (address); - GNUNET_STATISTICS_update (plugin->env->stats, - _ - ("# IPv6 multicast HELLO beacons received via udp"), - 1, GNUNET_NO); - GNUNET_free (mc); - return GNUNET_OK; -} - - -static int -broadcast_ipv4_mst_cb (void *cls, void *client, - const struct GNUNET_MessageHeader *message) +broadcast_mst_cb (void *cls, + void *client, + const struct GNUNET_MessageHeader *message) { struct Plugin *plugin = cls; - struct Mstv4Context *mc = client; + struct MstContext *mc = client; struct GNUNET_HELLO_Address *address; const struct GNUNET_MessageHeader *hello; const struct UDP_Beacon_Message *msg; @@ -194,87 +151,76 @@ broadcast_ipv4_mst_cb (void *cls, void *client, return GNUNET_OK; 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))); - + ntohs (msg->header.size), + GNUNET_i2s (&msg->sender), + udp_address_to_string (NULL, + mc->udp_addr, + mc->udp_addr_len)); /* setup ATS */ atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); atsi.value = htonl (mc->ats_address_network_type); - GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); + GNUNET_break (ntohl(mc->ats_address_network_type) != + GNUNET_ATS_NET_UNSPECIFIED); hello = (struct GNUNET_MessageHeader *) &msg[1]; address = GNUNET_HELLO_address_allocate (&msg->sender, PLUGIN_NAME, - (const char *) &mc->addr, - sizeof (mc->addr), + mc->udp_addr, + mc->udp_addr_len, GNUNET_HELLO_ADDRESS_INFO_NONE); - plugin->env->receive (plugin->env->cls, address, NULL, hello); - plugin->env->update_address_metrics (plugin->env->cls, address, - NULL, &atsi, 1); + plugin->env->receive (plugin->env->cls, + address, + NULL, + hello); + plugin->env->update_address_metrics (plugin->env->cls, + address, + NULL, + &atsi, + 1); GNUNET_HELLO_address_free (address); - GNUNET_STATISTICS_update (plugin->env->stats, - _("# IPv4 broadcast HELLO beacons received via udp"), + _("# Multicast HELLO beacons received via UDP"), 1, GNUNET_NO); - GNUNET_free (mc); return GNUNET_OK; } +/** + * We received a broadcast message. Process it and all subsequent + * messages in the same packet. + * + * @param plugin the UDP plugin + * @param buf the buffer with the message(s) + * @param size number of bytes in @a buf + * @param udp_addr address of the sender + * @param udp_addr_len number of bytes in @a udp_addr + * @param network_type network type of the sender's address + */ void udp_broadcast_receive (struct Plugin *plugin, const char *buf, ssize_t size, - const struct sockaddr *addr, - size_t addrlen) + const union UdpAddress *udp_addr, + size_t udp_addr_len, + enum GNUNET_ATS_Network_Type network_type) { - if (addrlen == sizeof (struct sockaddr_in)) - { - 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)); - struct Mstv4Context *mc; - - mc = GNUNET_new (struct Mstv4Context); - struct sockaddr_in *av4 = (struct sockaddr_in *) addr; - - mc->addr.ipv4_addr = av4->sin_addr.s_addr; - mc->addr.u4_port = av4->sin_port; - mc->ats_address_network_type = plugin->env->get_address_type (plugin->env->cls, - (const struct sockaddr *) addr, - addrlen); - - GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); - if (GNUNET_OK != - GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, size, - GNUNET_NO, GNUNET_NO)) - GNUNET_free (mc); - } - if (addrlen == sizeof (struct sockaddr_in6)) - { - 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)); - struct Mstv6Context *mc; - - mc = GNUNET_new (struct Mstv6Context); - struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) addr; - - mc->addr.ipv6_addr = av6->sin6_addr; - mc->addr.u6_port = av6->sin6_port; - mc->ats_address_network_type = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen); - GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); - if (GNUNET_OK != - GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, size, - GNUNET_NO, GNUNET_NO)) - GNUNET_free (mc); - } + struct MstContext mc; + + mc.udp_addr = udp_addr; + mc.udp_addr_len = udp_addr_len; + mc.ats_address_network_type = network_type; + GNUNET_SERVER_mst_receive (plugin->broadcast_mst, + &mc, + buf, size, + GNUNET_NO, + GNUNET_NO); } static unsigned int -prepare_beacon (struct Plugin *plugin, struct UDP_Beacon_Message *msg) +prepare_beacon (struct Plugin *plugin, + struct UDP_Beacon_Message *msg) { uint16_t hello_size; uint16_t msg_size; @@ -611,10 +557,8 @@ setup_broadcast (struct Plugin *plugin, } /* always create tokenizers */ - plugin->broadcast_ipv4_mst = - GNUNET_SERVER_mst_create (&broadcast_ipv4_mst_cb, plugin); - plugin->broadcast_ipv6_mst = - GNUNET_SERVER_mst_create (&broadcast_ipv6_mst_cb, plugin); + plugin->broadcast_mst = + GNUNET_SERVER_mst_create (&broadcast_mst_cb, plugin); if (GNUNET_YES != plugin->enable_broadcasting) return; /* We do not send, just receive */ @@ -699,15 +643,10 @@ stop_broadcast (struct Plugin *plugin) } /* Destroy MSTs */ - if (NULL != plugin->broadcast_ipv4_mst) - { - GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst); - plugin->broadcast_ipv4_mst = NULL; - } - if (NULL != plugin->broadcast_ipv6_mst) + if (NULL != plugin->broadcast_mst) { - GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst); - plugin->broadcast_ipv6_mst = NULL; + GNUNET_SERVER_mst_destroy (plugin->broadcast_mst); + plugin->broadcast_mst = NULL; } } -- cgit v1.2.3