X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fgnunet-service-transport_clients.c;h=7ce455f7d3174af5732f7d148273c0c80036b803;hb=6d754e6c89fda8cb0da00c4152ffc6dcc707e6ce;hp=1ef28ad90b7d3669f69d8976e7464834c25abfe1;hpb=ec057166095a225d45be16e66671e0f7f74cbef2;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-service-transport_clients.c b/src/transport/gnunet-service-transport_clients.c index 1ef28ad90..7ce455f7d 100644 --- a/src/transport/gnunet-service-transport_clients.c +++ b/src/transport/gnunet-service-transport_clients.c @@ -24,10 +24,12 @@ * @author Christian Grothoff */ #include "platform.h" +#include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_clients.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport_plugins.h" +#include "gnunet-service-transport_validation.h" #include "gnunet-service-transport.h" #include "transport.h" @@ -107,6 +109,10 @@ struct TransportClient */ unsigned int message_count; + /** + * Is this client interested in payload messages? + */ + int send_payload; }; @@ -120,7 +126,6 @@ static struct TransportClient *clients_head; */ static struct TransportClient *clients_tail; - /** * Find the internal handle associated with the given client handle * @@ -132,13 +137,13 @@ lookup_client (struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; - tc = clients_head; + tc = clients_head; while (tc != NULL) - { - if (tc->client == client) - return tc; - tc = tc->next; - } + { + if (tc->client == client) + return tc; + tc = tc->next; + } return NULL; } @@ -153,12 +158,14 @@ static struct TransportClient * setup_client (struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; - + + GNUNET_assert (lookup_client (client) == NULL); tc = GNUNET_malloc (sizeof (struct TransportClient)); tc->client = client; - GNUNET_CONTAINER_DLL_insert (clients_head, - clients_tail, - tc); + +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %X connected\n", tc); +#endif return tc; } @@ -174,9 +181,7 @@ setup_client (struct GNUNET_SERVER_Client *client) * @return number of bytes written to buf */ static size_t -transmit_to_client_callback (void *cls, - size_t size, - void *buf) +transmit_to_client_callback (void *cls, size_t size, void *buf) { struct TransportClient *tc = cls; struct ClientMessageQueueEntry *q; @@ -187,46 +192,42 @@ transmit_to_client_callback (void *cls, tc->th = NULL; if (buf == NULL) - { -#if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmission to client failed, closing connection.\n"); + { +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmission to client failed, closing connection.\n"); #endif - return 0; - } + return 0; + } cbuf = buf; tsize = 0; while (NULL != (q = tc->message_queue_head)) - { - msg = (const struct GNUNET_MessageHeader *) &q[1]; - msize = ntohs (msg->size); - if (msize + tsize > size) - break; + { + msg = (const struct GNUNET_MessageHeader *) &q[1]; + msize = ntohs (msg->size); + if (msize + tsize > size) + break; #if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmitting message of type %u to client.\n", - ntohs (msg->type)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmitting message of type %u to client %X.\n", + ntohs (msg->type), tc); #endif - GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, - tc->message_queue_tail, - q); - tc->message_count--; - memcpy (&cbuf[tsize], - msg, - msize); - GNUNET_free (q); - tsize += msize; - } + GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail, + q); + tc->message_count--; + memcpy (&cbuf[tsize], msg, msize); + GNUNET_free (q); + tsize += msize; + } if (NULL != q) - { - GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader)); - tc->th = GNUNET_SERVER_notify_transmit_ready (tc->client, - msize, - GNUNET_TIME_UNIT_FOREVER_REL, - &transmit_to_client_callback, - tc); - GNUNET_assert (tc->th != NULL); - } + { + GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader)); + tc->th = + GNUNET_SERVER_notify_transmit_ready (tc->client, msize, + GNUNET_TIME_UNIT_FOREVER_REL, + &transmit_to_client_callback, tc); + GNUNET_assert (tc->th != NULL); + } return tsize; } @@ -234,49 +235,44 @@ transmit_to_client_callback (void *cls, /** * Queue the given message for transmission to the given client * - * @param client target of the message + * @param tc target of the message * @param msg message to transmit * @param may_drop GNUNET_YES if the message can be dropped */ static void -unicast (struct TransportClient *tc, - const struct GNUNET_MessageHeader *msg, - int may_drop) +unicast (struct TransportClient *tc, const struct GNUNET_MessageHeader *msg, + int may_drop) { struct ClientMessageQueueEntry *q; uint16_t msize; - if ( (tc->message_count >= MAX_PENDING) && - (GNUNET_YES == may_drop) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Dropping message of type %u and size %u, have %u/%u messages pending\n"), - ntohs (msg->type), - ntohs (msg->size), - tc->message_count, - MAX_PENDING); - GNUNET_STATISTICS_update (GST_stats, - gettext_noop ("# messages dropped due to slow client"), - 1, - GNUNET_NO); - return; - } + if ((tc->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _ + ("Dropping message of type %u and size %u, have %u/%u messages pending\n"), + ntohs (msg->type), ntohs (msg->size), tc->message_count, + MAX_PENDING); + GNUNET_STATISTICS_update (GST_stats, + gettext_noop + ("# messages dropped due to slow client"), 1, + GNUNET_NO); + return; + } msize = ntohs (msg->size); GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader)); q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize); memcpy (&q[1], msg, msize); GNUNET_CONTAINER_DLL_insert_tail (tc->message_queue_head, - tc->message_queue_tail, - q); + tc->message_queue_tail, q); tc->message_count++; if (tc->th != NULL) return; - tc->th = GNUNET_SERVER_notify_transmit_ready (tc->client, - msize, - GNUNET_TIME_UNIT_FOREVER_REL, - &transmit_to_client_callback, - tc); - GNUNET_assert (tc->th != NULL); + tc->th = + GNUNET_SERVER_notify_transmit_ready (tc->client, msize, + GNUNET_TIME_UNIT_FOREVER_REL, + &transmit_to_client_callback, tc); + GNUNET_assert (tc->th != NULL); } @@ -288,8 +284,7 @@ unicast (struct TransportClient *tc, * @param client identification of the client */ static void -client_disconnect_notification (void *cls, - struct GNUNET_SERVER_Client *client) +client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; struct ClientMessageQueueEntry *mqe; @@ -301,52 +296,26 @@ client_disconnect_notification (void *cls, return; #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, - "Client disconnected, cleaning up.\n"); + "Client %X disconnected, cleaning up.\n", tc); #endif while (NULL != (mqe = tc->message_queue_head)) - { - GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, - tc->message_queue_tail, - mqe); - tc->message_count--; - GNUNET_free (mqe); - } - GNUNET_CONTAINER_DLL_remove (clients_head, - clients_tail, - tc); + { + GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail, + mqe); + tc->message_count--; + GNUNET_free (mqe); + } + GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc); if (tc->th != NULL) - { - GNUNET_CONNECTION_notify_transmit_ready_cancel (tc->th); - tc->th = NULL; - } + { + GNUNET_CONNECTION_notify_transmit_ready_cancel (tc->th); + tc->th = NULL; + } GNUNET_break (0 == tc->message_count); GNUNET_free (tc); } -/** - * Start handling requests from clients. - * - * @param server server used to accept clients from. - */ -void -GST_clients_start (struct GNUNET_SERVER_Handle *server) -{ - GNUNET_SERVER_disconnect_notify (server, - &client_disconnect_notification, NULL); -} - - -/** - * Stop processing clients. - */ -void -GST_clients_stop () -{ - /* nothing to do */ -} - - /** * Function called for each of our connected neighbours. Notify the * client about the existing neighbour. @@ -355,29 +324,32 @@ GST_clients_stop () * @param peer identity of the neighbour * @param ats performance data * @param ats_count number of entries in ats (excluding 0-termination) + * @param address the address */ static void notify_client_about_neighbour (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TRANSPORT_ATS_Information *ats, - uint32_t ats_count) + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_ATS_Information *ats, + uint32_t ats_count, + const struct GNUNET_HELLO_Address *address) { struct TransportClient *tc = cls; struct ConnectInfoMessage *cim; - size_t size; + struct GNUNET_ATS_Information *ap; + size_t size = + sizeof (struct ConnectInfoMessage) + + ats_count * sizeof (struct GNUNET_ATS_Information); + char buf[size]; - size = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information); GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); - cim = GNUNET_malloc (size); + cim = (struct ConnectInfoMessage *) buf; cim->header.size = htons (size); cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); - cim->ats_count = htonl(ats_count); + cim->ats_count = htonl (ats_count); cim->id = *peer; - memcpy (&cim->ats, - ats, - ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)); + ap = (struct GNUNET_ATS_Information *) &cim[1]; + memcpy (ap, ats, ats_count * sizeof (struct GNUNET_ATS_Information)); unicast (tc, &cim->header, GNUNET_NO); - GNUNET_free (cim); } @@ -390,85 +362,241 @@ notify_client_about_neighbour (void *cls, * @param client the client * @param message the start message that was sent */ -void -GST_clients_handle_start (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +static void +clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { const struct StartMessage *start; struct TransportClient *tc; + uint32_t options; tc = lookup_client (client); + +#if DEBUG_TRANSPORT if (tc != NULL) - { - /* got 'start' twice from the same client, not allowed */ - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - start = (const struct StartMessage*) message; - if ( (GNUNET_NO != ntohl (start->do_check)) && - (0 != memcmp (&start->self, - &GST_my_identity, - sizeof (struct GNUNET_PeerIdentity))) ) - { - /* client thinks this is a different peer, reject */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Rejecting control connection from peer `%s', which is not me!\n"), - GNUNET_i2s (&start->self)); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, + "Client %X sent START\n", tc); + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, + "Client %X sent START\n", tc); +#endif + if (tc != NULL) + { + /* got 'start' twice from the same client, not allowed */ +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, + "TransportClient %X ServerClient %X sent multiple START messages\n", + tc, tc->client); +#endif + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + start = (const struct StartMessage *) message; + options = ntohl (start->options); + if ((0 != (1 & options)) && + (0 != + memcmp (&start->self, &GST_my_identity, + sizeof (struct GNUNET_PeerIdentity)))) + { + /* client thinks this is a different peer, reject */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ + ("Rejecting control connection from peer `%s', which is not me!\n"), + GNUNET_i2s (&start->self)); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } tc = setup_client (client); - unicast (tc, GST_hello_get(), GNUNET_NO); + tc->send_payload = (0 != (2 & options)); + unicast (tc, GST_hello_get (), GNUNET_NO); GST_neighbours_iterate (¬ify_client_about_neighbour, tc); + GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** - * Client asked for transmission to a peer. Process the request. + * Client sent us a HELLO. Process the request. * * @param cls unused * @param client the client - * @param message the send message that was sent + * @param message the HELLO message */ -void -GST_clients_handle_send (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +static void +clients_handle_hello (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { + GST_validation_handle_hello (message); + GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** - * Client asked for a quota change for a particular peer. Process the request. + * Closure for 'handle_send_transmit_continuation' + */ +struct SendTransmitContinuationContext +{ + /** + * Client that made the request. + */ + struct GNUNET_SERVER_Client *client; + + /** + * Peer that was the target. + */ + struct GNUNET_PeerIdentity target; +}; + + +/** + * Function called after the transmission is done. Notify the client that it is + * OK to send the next message. + * + * @param cls closure + * @param success GNUNET_OK on success, GNUNET_NO on failure, GNUNET_SYSERR if we're not connected + */ +static void +handle_send_transmit_continuation (void *cls, int success) +{ + struct SendTransmitContinuationContext *stcc = cls; + struct SendOkMessage send_ok_msg; + + send_ok_msg.header.size = htons (sizeof (send_ok_msg)); + send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); + send_ok_msg.success = htonl (success); + send_ok_msg.latency = + GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_FOREVER_REL); + send_ok_msg.peer = stcc->target; + GST_clients_unicast (stcc->client, &send_ok_msg.header, GNUNET_NO); + GNUNET_SERVER_client_drop (stcc->client); + GNUNET_free (stcc); +} + + +/** + * Client asked for transmission to a peer. Process the request. * * @param cls unused * @param client the client - * @param message the quota changing message + * @param message the send message that was sent */ -void -GST_clients_handle_set_quota (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +static void +clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { - const struct QuotaSetMessage *qsm; + const struct OutboundMessage *obm; + const struct GNUNET_MessageHeader *obmm; + struct SendTransmitContinuationContext *stcc; + uint16_t size; + uint16_t msize; + struct TransportClient *tc; + + tc = lookup_client (client); + if (NULL == tc) + { + /* client asked for transmission before 'START' */ + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } - qsm = (const struct QuotaSetMessage *) message; + size = ntohs (message->size); + if (size < + sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + obm = (const struct OutboundMessage *) message; + obmm = (const struct GNUNET_MessageHeader *) &obm[1]; + msize = size - sizeof (struct OutboundMessage); + if (msize < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } GNUNET_STATISTICS_update (GST_stats, - gettext_noop ("# SET QUOTA messages received"), - 1, - GNUNET_NO); -#if DEBUG_TRANSPORT + gettext_noop + ("# bytes payload received for other peers"), msize, + GNUNET_NO); +#if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received `%s' request (new quota %u) from client for peer `%4s'\n", - "SET_QUOTA", - (unsigned int) ntohl (qsm->quota.value__), - GNUNET_i2s (&qsm->peer)); + "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n", + "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize); +#endif + if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer)) + { + /* not connected, not allowed to send; can happen due to asynchronous operations */ +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Could not send message to peer `%s': not connected\n", + GNUNET_i2s (&obm->peer)); #endif - GST_neighbours_set_incoming_quota (&qsm->peer, - qsm->quota); + GNUNET_STATISTICS_update (GST_stats, + gettext_noop + ("# bytes payload dropped (other peer was not connected)"), + msize, GNUNET_NO); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + GNUNET_SERVER_receive_done (client, GNUNET_OK); + stcc = GNUNET_malloc (sizeof (struct SendTransmitContinuationContext)); + stcc->target = obm->peer; + stcc->client = client; + GNUNET_SERVER_client_keep (client); + GST_neighbours_send (&obm->peer, obmm, msize, + GNUNET_TIME_relative_ntoh (obm->timeout), + &handle_send_transmit_continuation, stcc); +} + + +/** + * 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); +} + + +/** + * Handle request connect message + * + * @param cls closure (always NULL) + * @param client identification of the client + * @param message the actual message + */ +static void +clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + const struct TransportRequestConnectMessage *trcm = + (const struct TransportRequestConnectMessage *) message; + + GNUNET_STATISTICS_update (GST_stats, + gettext_noop + ("# REQUEST CONNECT messages received"), 1, + GNUNET_NO); +#if DEBUG_TRANSPORT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received a request connect message for peer `%s'\n", + GNUNET_i2s (&trcm->peer)); +#endif + (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed, + NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -478,25 +606,22 @@ GST_clients_handle_set_quota (void *cls, * the client. * * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*') - * @param address the resolved name, NULL to indicate the last response + * @param buf text to transmit */ static void -transmit_address_to_client (void *cls, - const char *address) +transmit_address_to_client (void *cls, const char *buf) { struct GNUNET_SERVER_TransmitContext *tc = cls; - if (NULL == address) - { - GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, - GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY); - GNUNET_SERVER_transmit_context_run (tc, - GNUNET_TIME_UNIT_FOREVER_REL); - return; - } - GNUNET_SERVER_transmit_context_append_data (tc, - address, strlen (address) + 1, - GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY); + if (NULL == buf) + { + GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); + GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); + return; + } + GNUNET_SERVER_transmit_context_append_data (tc, buf, strlen (buf) + 1, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); } @@ -507,10 +632,10 @@ transmit_address_to_client (void *cls, * @param client the client * @param message the resolution request */ -void -GST_clients_handle_address_lookup (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +static void +clients_handle_address_to_string (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { const struct AddressLookupMessage *alum; struct GNUNET_TRANSPORT_PluginFunctions *papi; @@ -524,78 +649,195 @@ GST_clients_handle_address_lookup (void *cls, size = ntohs (message->size); if (size < sizeof (struct AddressLookupMessage)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } alum = (const struct AddressLookupMessage *) message; - address_len = ntohl (alum->addrlen); + address_len = ntohs (alum->addrlen); if (size <= sizeof (struct AddressLookupMessage) + address_len) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } address = (const char *) &alum[1]; plugin_name = (const char *) &address[address_len]; - if (plugin_name - [size - sizeof (struct AddressLookupMessage) - address_len - 1] != '\0') - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } + if (plugin_name[size - sizeof (struct AddressLookupMessage) - address_len - 1] + != '\0') + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout); - numeric = ntohl (alum->numeric_only); + numeric = ntohs (alum->numeric_only); tc = GNUNET_SERVER_transmit_context_create (client); papi = GST_plugins_find (plugin_name); if (NULL == papi) - { - GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, - GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY); - GNUNET_SERVER_transmit_context_run (tc, rtimeout); - return; - } + { + GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); + GNUNET_SERVER_transmit_context_run (tc, rtimeout); + return; + } GNUNET_SERVER_disable_receive_done_warning (client); - papi->address_pretty_printer (papi->cls, - plugin_name, - address, address_len, - numeric, - rtimeout, - &transmit_address_to_client, tc); + papi->address_pretty_printer (papi->cls, plugin_name, address, address_len, + numeric, rtimeout, &transmit_address_to_client, + tc); } /** - * Client asked to obtain information about a peer's addresses. - * Process the request. + * Output the active address of connected neighbours to the given client. * - * @param cls unused - * @param client the client - * @param message the peer address information request + * @param cls the 'struct GNUNET_SERVER_TransmitContext' for transmission to the client + * @param peer identity of the neighbour + * @param ats performance data + * @param ats_count number of entries in ats (excluding 0-termination) + * @param address the address */ -void -GST_clients_handle_peer_address_lookup (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +static void +output_address (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_ATS_Information *ats, uint32_t ats_count, + const struct GNUNET_HELLO_Address *address) { + struct GNUNET_SERVER_TransmitContext *tc = cls; + struct AddressIterateResponseMessage *msg; + size_t size; + size_t tlen; + size_t alen; + char *addr; + + tlen = strlen (address->transport_name) + 1; + alen = address->address_length; + size = (sizeof (struct AddressIterateResponseMessage) + alen + tlen); + { + char buf[size]; + + msg = (struct AddressIterateResponseMessage *) buf; + msg->reserved = htonl (0); + msg->peer = *peer; + msg->addrlen = htonl (alen); + msg->pluginlen = htonl (tlen); + addr = (char *) &msg[1]; + memcpy (addr, address->address, alen); + memcpy (&addr[alen], address->transport_name, tlen); + GNUNET_SERVER_transmit_context_append_data (tc, + &buf[sizeof + (struct + GNUNET_MessageHeader)], + size - + sizeof (struct + GNUNET_MessageHeader), + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE); + } } /** - * Client asked to obtain information about all addresses. + * Client asked to obtain information about all actively used addresses + * of connected peers * Process the request. * * @param cls unused * @param client the client * @param message the peer address information request */ +static void +clients_handle_address_iterate (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + static struct GNUNET_PeerIdentity all_zeros; + struct GNUNET_SERVER_TransmitContext *tc; + struct AddressIterateMessage *msg; + struct GNUNET_HELLO_Address *address; + + if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + if (ntohs (message->size) != sizeof (struct AddressIterateMessage)) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + msg = (struct AddressIterateMessage *) message; + if (GNUNET_YES != ntohl (msg->one_shot)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Address monitoring not implemented\n"); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + GNUNET_SERVER_disable_receive_done_warning (client); + tc = GNUNET_SERVER_transmit_context_create (client); + if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) + { + /* iterate over all neighbours */ + GST_neighbours_iterate (&output_address, tc); + } + else + { + /* just return one neighbour */ + address = GST_neighbour_get_current_address (&msg->peer); + if (address != NULL) + output_address (tc, &msg->peer, NULL, 0, address); + } + GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE); + GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); +} + + +/** + * Start handling requests from clients. + * + * @param server server used to accept clients from. + */ void -GST_clients_handle_address_iterate (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +GST_clients_start (struct GNUNET_SERVER_Handle *server) { + static const struct GNUNET_SERVER_MessageHandler handlers[] = { + {&clients_handle_start, NULL, + GNUNET_MESSAGE_TYPE_TRANSPORT_START, sizeof (struct StartMessage)}, + {&clients_handle_hello, NULL, + GNUNET_MESSAGE_TYPE_HELLO, 0}, + {&clients_handle_send, NULL, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0}, + {&clients_handle_request_connect, NULL, + GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT, + sizeof (struct TransportRequestConnectMessage)}, + {&clients_handle_address_to_string, NULL, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING, 0}, + {&clients_handle_address_iterate, NULL, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE, + sizeof (struct AddressIterateMessage)}, + {&GST_blacklist_handle_init, NULL, + GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT, + sizeof (struct GNUNET_MessageHeader)}, + {&GST_blacklist_handle_reply, NULL, + GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY, + sizeof (struct BlacklistMessage)}, + {NULL, NULL, 0, 0} + }; + GNUNET_SERVER_add_handlers (server, handlers); + GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, + NULL); +} + + +/** + * Stop processing clients. + */ +void +GST_clients_stop () +{ + /* nothing to do */ } @@ -603,16 +845,19 @@ GST_clients_handle_address_iterate (void *cls, * Broadcast the given message to all of our clients. * * @param msg message to broadcast - * @param may_drop GNUNET_YES if the message can be dropped + * @param may_drop GNUNET_YES if the message can be dropped / is payload */ void -GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, - int may_drop) +GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop) { struct TransportClient *tc; for (tc = clients_head; tc != NULL; tc = tc->next) + { + if ((GNUNET_YES == may_drop) && (GNUNET_YES != tc->send_payload)) + continue; /* skip, this client does not care about payload */ unicast (tc, msg, may_drop); + } } @@ -625,14 +870,13 @@ GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, */ void GST_clients_unicast (struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg, - int may_drop) + const struct GNUNET_MessageHeader *msg, int may_drop) { struct TransportClient *tc; tc = lookup_client (client); if (NULL == tc) - tc = setup_client (client); + return; /* client got disconnected in the meantime, drop message */ unicast (tc, msg, may_drop); }