X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fgnunet-service-transport.c;h=cd9bb5c65e2018cd2f21c8d7badba5ff8ba69fae;hb=107a20218f88dcd4f41869c233d89835fb9c1ac5;hp=2a97f8155a2745f5af5eabeea5bbbbe847ec0755;hpb=09261c0fea3f9db420f42d87964ba90153b2ede0;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index 2a97f8155..cd9bb5c65 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -19,12 +19,13 @@ */ /** - * @file transport/gnunet-service-transport-new.c + * @file transport/gnunet-service-transport.c * @brief * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" +#include "gnunet_hello_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_peerinfo_service.h" @@ -83,17 +84,13 @@ struct GNUNET_ATS_SchedulingHandle *GST_ats; * @param target a connected neighbour * @param ats performance information (unused) * @param ats_count number of records in ats (unused) - * @param transport plugin - * @param addr address - * @param addrlen address length + * @param address the address */ static void transmit_our_hello (void *cls, const struct GNUNET_PeerIdentity *target, const struct GNUNET_ATS_Information *ats, uint32_t ats_count, - const char * transport, - const void * addr, - size_t addrlen) + const struct GNUNET_HELLO_Address *address) { const struct GNUNET_MessageHeader *hello = cls; @@ -116,86 +113,70 @@ process_hello_update (void *cls, const struct GNUNET_MessageHeader *hello) } -/** - * Try to initiate a connection to the given peer if the blacklist - * allowed it. - * - * @param cls closure (unused, NULL) - * @param peer identity of peer that was tested - * @param result GNUNET_OK if the connection is allowed, - * GNUNET_NO if not - */ -static void -try_connect_if_allowed (void *cls, const struct GNUNET_PeerIdentity *peer, - int result) -{ - if (GNUNET_OK != result) - return; /* not allowed */ - GST_neighbours_try_connect (peer); -} - /** - * We received some payload. Prepare to pass it on to our clients. + * We received some payload. Prepare to pass it on to our clients. * * @param peer (claimed) identity of the other peer - * @param message the message, NULL if we only care about - * learning about the delay until we should receive again -- FIXME! + * @param address the address + * @param session session used + * @param message the message to process * @param ats performance information * @param ats_count number of records in ats * @return how long the plugin should wait until receiving more data */ static struct GNUNET_TIME_Relative process_payload (const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *ats, - uint32_t ats_count) + const struct GNUNET_HELLO_Address *address, + struct Session *session, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct GNUNET_TIME_Relative ret; int do_forward; struct InboundMessage *im; - size_t size = sizeof (struct InboundMessage) + ntohs (message->size); + size_t msg_size = ntohs (message->size); + size_t size = + sizeof (struct InboundMessage) + msg_size + + sizeof (struct GNUNET_ATS_Information) * (ats_count + 1); char buf[size]; - + struct GNUNET_ATS_Information *ap; + ret = GNUNET_TIME_UNIT_ZERO; do_forward = GNUNET_SYSERR; - ret = - GST_neighbours_calculate_receive_delay (peer, - (message == - NULL) ? 0 : - ntohs (message->size), - &do_forward); - im = (struct InboundMessage*) buf; + ret = GST_neighbours_calculate_receive_delay (peer, msg_size, &do_forward); + + if (!GST_neighbours_test_connected (peer)) + { + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Discarded %u bytes type %u payload from peer `%s'\n", msg_size, + ntohs (message->type), GNUNET_i2s (peer)); + + GNUNET_STATISTICS_update (GST_stats, + gettext_noop + ("# bytes payload discarded due to not connected peer "), + msg_size, GNUNET_NO); + return ret; + } + + if (do_forward != GNUNET_YES) + return ret; + im = (struct InboundMessage *) buf; im->header.size = htons (size); im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV); - im->ats_count = htonl (0); - memcpy (&(im->peer), peer, sizeof (struct GNUNET_PeerIdentity)); - memcpy (&im[1], message, ntohs (message->size)); + im->ats_count = htonl (ats_count + 1); + im->peer = *peer; + ap = (struct GNUNET_ATS_Information *) &im[1]; + memcpy (ap, ats, ats_count * sizeof (struct GNUNET_ATS_Information)); + ap[ats_count].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); + ap[ats_count].value = + htonl ((uint32_t) GST_neighbour_get_latency (peer).rel_value); + memcpy (&ap[ats_count + 1], message, ntohs (message->size)); + + GNUNET_ATS_address_update (GST_ats, address, session, ap, ats_count + 1); + GST_clients_broadcast (&im->header, GNUNET_YES); - switch (do_forward) - { - case GNUNET_YES: - GST_clients_broadcast (&im->header, GNUNET_YES); - break; - case GNUNET_NO: - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Discarded %u bytes of type %u from %s: quota violated!\n"), - ntohs (message->size), - ntohs (message->type), - GNUNET_i2s (peer)); - break; - case GNUNET_SYSERR: - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Discarded %u bytes of type %u from %s: connection is down!\n"), - ntohs (message->size), - ntohs (message->type), - GNUNET_i2s (peer)); - /* FIXME: store until connection is up? This is virtually always a SETKEY and a PING... */ - break; - default: - GNUNET_break (0); - break; - } return ret; } @@ -233,12 +214,22 @@ plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer, { const char *plugin_name = cls; struct GNUNET_TIME_Relative ret; + struct GNUNET_HELLO_Address address; uint16_t type; - + + address.peer = *peer; + address.address = sender_address; + address.address_length = sender_address_len; + address.transport_name = plugin_name; ret = GNUNET_TIME_UNIT_ZERO; if (NULL == message) goto end; type = ntohs (message->type); +#if DEBUG_TRANSPORT + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received Message with type %u\n", type); +#endif + switch (type) { case GNUNET_MESSAGE_TYPE_HELLO: @@ -247,67 +238,57 @@ plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer, case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, - "Processing `%s' from `%s'\n", "PING", - (sender_address != NULL) ? GST_plugins_a2s (plugin_name, - sender_address, - sender_address_len) - : ""); + "Processing `%s' from `%s'\n", "PING", + (sender_address != + NULL) ? GST_plugins_a2s (&address) : ""); #endif - GST_validation_handle_ping (peer, message, plugin_name, session, - sender_address, sender_address_len); + GST_validation_handle_ping (peer, message, &address, session); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, - "Processing `%s' from `%s'\n", "PONG", - (sender_address != NULL) ? GST_plugins_a2s (plugin_name, - sender_address, - sender_address_len) - : ""); + "Processing `%s' from `%s'\n", "PONG", + (sender_address != + NULL) ? GST_plugins_a2s (&address) : ""); #endif GST_validation_handle_pong (peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT: - GST_neighbours_handle_connect (message, - peer, - plugin_name, sender_address, sender_address_len, - session, ats, ats_count); - (void) GST_blacklist_test_allowed (peer, NULL, &try_connect_if_allowed, - NULL); + GST_neighbours_handle_connect (message, peer, &address, session, ats, + ats_count); + break; + case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK: + GST_neighbours_handle_connect_ack (message, peer, &address, session, ats, + ats_count); + break; + case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK: + GST_neighbours_handle_ack (message, peer, &address, session, ats, + ats_count); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT: - /* FIXME: do some validation to prevent an attacker from sending - * a fake disconnect message... */ - GST_neighbours_force_disconnect (peer); + GST_neighbours_handle_disconnect_message (peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE: GST_neighbours_keepalive (peer); break; + case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE: + GST_neighbours_keepalive_response (peer, ats, ats_count); + break; default: /* should be payload */ - process_payload (peer, - message, - ats, ats_count); + ret = process_payload (peer, &address, session, message, ats, ats_count); break; } - end: +end: #if 1 /* FIXME: this should not be needed, and not sure it's good to have it, but without - this connections seem to go extra-slow */ - if ((ats_count > 0) && (ats != NULL)) - { - if (NULL != session) - GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, - "transport-ats", - "Giving ATS session %p of plugin %s for peer %s\n", - session, - plugin_name, - GNUNET_i2s (peer)); - GNUNET_ATS_address_update (GST_ats, peer, - plugin_name, sender_address, sender_address_len, - session, - ats, ats_count); - } + * this connections seem to go extra-slow */ + GNUNET_ATS_address_update (GST_ats, &address, session, ats, ats_count); +#endif +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Allowing receive from peer %s to continue in %llu ms\n", + GNUNET_i2s (peer), (unsigned long long) ret.rel_value); #endif return ret; } @@ -329,8 +310,13 @@ plugin_env_address_change_notification (void *cls, int add_remove, const void *addr, size_t addrlen) { const char *plugin_name = cls; + struct GNUNET_HELLO_Address address; - GST_hello_modify_addresses (add_remove, plugin_name, addr, addrlen); + address.peer = GST_my_identity; + address.transport_name = plugin_name; + address.address = addr; + address.address_length = addrlen; + GST_hello_modify_addresses (add_remove, &address); } @@ -351,19 +337,61 @@ static void plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { + const char *transport_name = cls; + struct GNUNET_HELLO_Address address; + + GNUNET_assert (strlen (transport_name) > 0); #if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Session %X to peer `%s' ended \n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %X to peer `%s' ended \n", session, GNUNET_i2s (peer)); #endif if (NULL != session) - GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, - "transport-ats", - "Telling ATS to destroy session %p from peer %s\n", - session, - GNUNET_i2s (peer)); - GNUNET_ATS_address_destroyed(GST_ats, peer, NULL, NULL, 0, session); + GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, + "transport-ats", + "Telling ATS to destroy session %p from peer %s\n", + session, GNUNET_i2s (peer)); + address.peer = *peer; + address.address = NULL; + address.address_length = 0; + address.transport_name = transport_name; GST_neighbours_session_terminated (peer, session); + GNUNET_ATS_address_destroyed (GST_ats, &address, session); +} + + +/** + * Function that will be called to figure if an address is an loopback, + * LAN, WAN etc. address + * + * @param cls closure + * @param addr binary address + * @param addrlen length of the address + * @return ATS Information containing the network type + */ +static const struct GNUNET_ATS_Information +plugin_env_address_to_type (void *cls, + const struct sockaddr *addr, + size_t addrlen) +{ + struct GNUNET_ATS_Information ats; + ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); + ats.value = htonl (GNUNET_ATS_NET_UNSPECIFIED); + if (GST_ats == NULL) + { + GNUNET_break (0); + return ats; + } + if (((addr->sa_family != AF_INET) && (addrlen != sizeof (struct sockaddr_in))) && + ((addr->sa_family != AF_INET6) && (addrlen != sizeof (struct sockaddr_in6))) && + (addr->sa_family != AF_UNIX)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed address with length %u `%s'\n", + addrlen, + GNUNET_a2s(addr, addrlen)); + GNUNET_break (0); + return (const struct GNUNET_ATS_Information) ats; + } + return GNUNET_ATS_address_get_type(GST_ats, addr, addrlen); } @@ -375,55 +403,40 @@ plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer, * actually happened. * * @param cls closure - * @param peer identity of the peer - * @param plugin_name name of the transport plugin, NULL to disconnect + * @param address address to use (for peer given in address) * @param session session to use (if available) - * @param plugin_addr address to use (if available) - * @param plugin_addr_len number of bytes in addr * @param bandwidth_out assigned outbound bandwidth for the connection, 0 to disconnect from peer * @param bandwidth_in assigned inbound bandwidth for the connection, 0 to disconnect from peer + * @param ats ATS information + * @param ats_count number of ATS elements */ static void -ats_request_address_change (void *cls, const struct GNUNET_PeerIdentity *peer, - const char *plugin_name, - const void *plugin_addr, size_t plugin_addr_len, +ats_request_address_change (void *cls, + const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, - const struct GNUNET_ATS_Information * ats, + const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { uint32_t bw_in = ntohl (bandwidth_in.value__); uint32_t bw_out = ntohl (bandwidth_out.value__); - /* ATS tells me to disconnect from peer*/ + /* ATS tells me to disconnect from peer */ if ((bw_in == 0) && (bw_out == 0)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS tells me to disconnect from peer `%s'\n", - GNUNET_i2s (peer)); - GST_neighbours_force_disconnect(peer); - return; - } - - GST_neighbours_switch_to_address (peer, plugin_name, plugin_addr, - plugin_addr_len, session, ats, ats_count); - #if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending outbound quota of %u Bps for peer `%s' to all clients\n", - ntohl (bandwidth_out.value__), GNUNET_i2s (peer)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "ATS tells me to disconnect from peer `%s'\n", + GNUNET_i2s (&address->peer)); #endif - struct QuotaSetMessage msg; - msg.header.size = htons (sizeof (struct QuotaSetMessage)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); - msg.quota = bandwidth_out; - msg.peer = (*peer); - GST_clients_broadcast ((struct GNUNET_MessageHeader *) &msg, GNUNET_NO); - -#if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting inbound quota of %u for peer `%s' to \n", - ntohl (bandwidth_in.value__), GNUNET_i2s (peer)); -#endif - GST_neighbours_set_incoming_quota (peer, bandwidth_in); + GST_neighbours_force_disconnect (&address->peer); + return; + } + /* will never return GNUNET_YES since connection is to be established */ + GST_neighbours_switch_to_address (&address->peer, address, session, ats, + ats_count, bandwidth_in, + bandwidth_out); } @@ -439,19 +452,22 @@ ats_request_address_change (void *cls, const struct GNUNET_PeerIdentity *peer, static void neighbours_connect_notification (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information - *ats, uint32_t ats_count) + const struct GNUNET_ATS_Information *ats, + uint32_t ats_count) { - char buf[sizeof (struct ConnectInfoMessage) + - ats_count * sizeof (struct GNUNET_ATS_Information)]; + size_t len = + sizeof (struct ConnectInfoMessage) + + ats_count * sizeof (struct GNUNET_ATS_Information); + char buf[len]; struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf; + struct GNUNET_ATS_Information *ap; connect_msg->header.size = htons (sizeof (buf)); connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); connect_msg->ats_count = htonl (ats_count); connect_msg->id = *peer; - memcpy (&connect_msg->ats, &connect_msg->ats, - ats_count * sizeof (struct GNUNET_ATS_Information)); + ap = (struct GNUNET_ATS_Information *) &connect_msg[1]; + memcpy (ap, ats, ats_count * sizeof (struct GNUNET_ATS_Information)); GST_clients_broadcast (&connect_msg->header, GNUNET_NO); } @@ -477,6 +493,23 @@ neighbours_disconnect_notification (void *cls, } +/** + * Function called to notify transport users that a neighbour peer changed its + * active address. + * + * @param cls closure + * @param peer peer this update is about (never NULL) + * @param address address, NULL on disconnect + */ +static void +neighbours_address_notification (void *cls, + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_HELLO_Address *address) +{ + GST_clients_broadcast_address_notification (peer, address); +} + + /** * Function called when the service shuts down. Unloads our plugins * and cancels pending validations. @@ -487,9 +520,10 @@ neighbours_disconnect_notification (void *cls, static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + GST_neighbours_stop (); GST_validation_stop (); GST_plugins_unload (); - GST_neighbours_stop (); + GNUNET_ATS_scheduling_done (GST_ats); GST_ats = NULL; GST_clients_stop (); @@ -566,12 +600,16 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, /* start subsystems */ GST_hello_start (&process_hello_update, NULL); GST_blacklist_start (server); + GST_ats = + GNUNET_ATS_scheduling_init (GST_cfg, &ats_request_address_change, NULL); GST_plugins_load (&plugin_env_receive_callback, &plugin_env_address_change_notification, - &plugin_env_session_end); - GST_ats = GNUNET_ATS_scheduling_init (GST_cfg, &ats_request_address_change, NULL); - GST_neighbours_start (NULL, &neighbours_connect_notification, - &neighbours_disconnect_notification); + &plugin_env_session_end, + &plugin_env_address_to_type); + GST_neighbours_start (NULL, + &neighbours_connect_notification, + &neighbours_disconnect_notification, + &neighbours_address_notification); GST_clients_start (server); GST_validation_start (); }