X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fgnunet-service-transport_neighbours.c;h=3757c0ee32e2a71bdc9486c8552601f8749d1491;hb=cbd60b5e56aac2d6711e299086383f83357794f8;hp=87dd9c2130b2eb0309644aca3e74d62eadbaf956;hpb=77ea8dbe440a1a9780644876430292f65f5de51c;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c index 87dd9c213..3757c0ee3 100644 --- a/src/transport/gnunet-service-transport_neighbours.c +++ b/src/transport/gnunet-service-transport_neighbours.c @@ -1,21 +1,16 @@ /* This file is part of GNUnet. - Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2010-2015 GNUnet e.V. - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Affero General Public License for more details. */ /** @@ -26,8 +21,6 @@ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet-service-transport_ats.h" -#include "gnunet-service-transport_blacklist.h" -#include "gnunet-service-transport_clients.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport_manipulation.h" #include "gnunet-service-transport_plugins.h" @@ -37,6 +30,11 @@ #include "gnunet_constants.h" #include "transport.h" +/** + * Experimental option to ignore SessionQuotaMessages from + * the other peer. + */ +#define IGNORE_INBOUND_QUOTA GNUNET_YES /** * Size of the neighbour hash map. @@ -143,7 +141,7 @@ struct TransportSynMessage * When the keep alive response with type is received, transport service * will call the respective plugin to update the session timeout */ -struct SessionKeepAliveMessage +struct GNUNET_ATS_SessionKeepAliveMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE or @@ -163,7 +161,7 @@ struct SessionKeepAliveMessage * the other peer should limit transmissions to the indicated * quota. */ -struct SessionQuotaMessage +struct GNUNET_ATS_SessionQuotaMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA. @@ -183,7 +181,7 @@ struct SessionQuotaMessage * notification, peers must not rely on always receiving disconnect * messages. */ -struct SessionDisconnectMessage +struct GNUNET_ATS_SessionDisconnectMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT @@ -279,7 +277,7 @@ struct NeighbourAddress /** * Active session for this address. */ - struct Session *session; + struct GNUNET_ATS_Session *session; /** * Network-level address information. @@ -391,7 +389,7 @@ struct NeighbourMapEntry /** * Time where we should cut the connection (timeout) if we don't * make progress in the state machine (or get a KEEPALIVE_RESPONSE - * if we are in #S_CONNECTED). + * if we are in #GNUNET_TRANSPORT_PS_CONNECTED). */ struct GNUNET_TIME_Absolute timeout; @@ -456,52 +454,11 @@ struct NeighbourMapEntry }; -/** - * Context for blacklist checks and the #try_connect_bl_check_cont() - * function. Stores information about ongoing blacklist checks. - */ -struct BlackListCheckContext -{ - - /** - * We keep blacklist checks in a DLL. - */ - struct BlackListCheckContext *next; - - /** - * We keep blacklist checks in a DLL. - */ - struct BlackListCheckContext *prev; - - /** - * Address that is being checked. - */ - struct NeighbourAddress na; - - /** - * Handle to the ongoing blacklist check. - */ - struct GST_BlacklistCheck *bc; -}; - - /** * Hash map from peer identities to the respective `struct NeighbourMapEntry`. */ static struct GNUNET_CONTAINER_MultiPeerMap *neighbours; -/** - * We keep blacklist checks in a DLL so that we can find - * the 'sessions' in their 'struct NeighbourAddress' if - * a session goes down. - */ -static struct BlackListCheckContext *bc_head; - -/** - * We keep blacklist checks in a DLL. - */ -static struct BlackListCheckContext *bc_tail; - /** * List of pending blacklist checks: head */ @@ -551,31 +508,70 @@ print_ack_state (enum GST_ACK_State s) } +/** + * Send information about a new outbound quota to our clients. + * Note that the outbound quota is enforced client-side (i.e. + * in libgnunettransport). + * + * @param n affected peer + */ +static void +send_outbound_quota_to_clients (struct NeighbourMapEntry *n) +{ + struct QuotaSetMessage q_msg; + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min; + + if (! GNUNET_TRANSPORT_is_connected (n->state)) + return; +#if IGNORE_INBOUND_QUOTA + bandwidth_min = n->primary_address.bandwidth_out; +#else + bandwidth_min = GNUNET_BANDWIDTH_value_min (n->primary_address.bandwidth_out, + n->neighbour_receive_quota); +#endif + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending outbound quota of %u Bps for peer `%s' to all clients\n", + ntohl (bandwidth_min.value__), + GNUNET_i2s (&n->id)); + q_msg.header.size = htons (sizeof (struct QuotaSetMessage)); + q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); + q_msg.quota = bandwidth_min; + q_msg.peer = n->id; + GST_clients_broadcast (&q_msg.header, + GNUNET_NO); +} + + /** * Notify our clients that another peer connected to us. * - * @param peer the peer that connected - * @param bandwidth_in inbound bandwidth in NBO - * @param bandwidth_out outbound bandwidth in NBO + * @param n the peer that connected */ static void -neighbours_connect_notification (const struct GNUNET_PeerIdentity *peer, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) +neighbours_connect_notification (struct NeighbourMapEntry *n) { size_t len = sizeof(struct ConnectInfoMessage); char buf[len] GNUNET_ALIGN; struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf; + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min; +#if IGNORE_INBOUND_QUOTA + bandwidth_min = n->primary_address.bandwidth_out; +#else + bandwidth_min = GNUNET_BANDWIDTH_value_min (n->primary_address.bandwidth_out, + n->neighbour_receive_quota); +#endif GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We are now connected to peer `%s'\n", - GNUNET_i2s (peer)); + GNUNET_i2s (&n->id)); connect_msg->header.size = htons (sizeof(buf)); connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); - connect_msg->id = *peer; - connect_msg->quota_in = bandwidth_in; - connect_msg->quota_out = bandwidth_out; - GST_clients_broadcast (&connect_msg->header, GNUNET_NO); + connect_msg->id = n->id; + connect_msg->quota_in = n->primary_address.bandwidth_in; + connect_msg->quota_out = bandwidth_min; + GST_clients_broadcast (&connect_msg->header, + GNUNET_NO); } @@ -583,23 +579,16 @@ neighbours_connect_notification (const struct GNUNET_PeerIdentity *peer, * Notify our clients (and manipulation) that a peer disconnected from * us. * - * @param peer the peer that disconnected + * @param n the peer that disconnected */ static void -neighbours_disconnect_notification (const struct GNUNET_PeerIdentity *peer) +neighbours_disconnect_notification (struct NeighbourMapEntry *n) { - struct DisconnectInfoMessage disconnect_msg; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer `%s' disconnected\n", - GNUNET_i2s (peer)); - GST_manipulation_peer_disconnect (peer); - disconnect_msg.header.size = htons (sizeof(struct DisconnectInfoMessage)); - disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT); - disconnect_msg.reserved = htonl (0); - disconnect_msg.peer = *peer; - GST_clients_broadcast (&disconnect_msg.header, - GNUNET_NO); + GNUNET_i2s (&n->id)); + GST_manipulation_peer_disconnect (&n->id); + GST_clients_broadcast_disconnect (&n->id); } @@ -622,6 +611,8 @@ neighbours_changed_notification (const struct GNUNET_PeerIdentity *peer, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { + (void) bandwidth_in; + (void) bandwidth_out; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n", GNUNET_i2s (peer), @@ -666,32 +657,6 @@ test_connected (struct NeighbourMapEntry *n) } -/** - * Send information about a new outbound quota to our clients. - * Note that the outbound quota is enforced client-side (i.e. - * in libgnunettransport). - * - * @param target affected peer - * @param quota new quota - */ -static void -send_outbound_quota_to_clients (const struct GNUNET_PeerIdentity *target, - struct GNUNET_BANDWIDTH_Value32NBO quota) -{ - struct QuotaSetMessage q_msg; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending outbound quota of %u Bps for peer `%s' to all clients\n", - ntohl (quota.value__), - GNUNET_i2s (target)); - q_msg.header.size = htons (sizeof (struct QuotaSetMessage)); - q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); - q_msg.quota = quota; - q_msg.peer = (*target); - GST_clients_broadcast (&q_msg.header, GNUNET_NO); -} - - /** * We don't need a given neighbour address any more. * Release its resources and give appropriate notifications @@ -726,11 +691,9 @@ free_address (struct NeighbourAddress *na) * clean up after disconnect). * * @param cls the `struct NeighbourMapEntry` for which we are running - * @param tc scheduler context (unused) */ static void -master_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); +master_task (void *cls); /** @@ -748,9 +711,7 @@ set_state_and_timeout (struct NeighbourMapEntry *n, if (GNUNET_TRANSPORT_is_connected (s) && ! GNUNET_TRANSPORT_is_connected (n->state) ) { - neighbours_connect_notification (&n->id, - n->primary_address.bandwidth_in, - n->primary_address.bandwidth_out); + neighbours_connect_notification (n); GNUNET_STATISTICS_set (GST_stats, gettext_noop ("# peers connected"), ++neighbours_connected, @@ -763,7 +724,7 @@ set_state_and_timeout (struct NeighbourMapEntry *n, gettext_noop ("# peers connected"), --neighbours_connected, GNUNET_NO); - neighbours_disconnect_notification (&n->id); + neighbours_disconnect_notification (n); } n->state = s; if ( (timeout.abs_value_us < n->timeout.abs_value_us) && @@ -771,9 +732,9 @@ set_state_and_timeout (struct NeighbourMapEntry *n, { /* new timeout is earlier, reschedule master task */ GNUNET_SCHEDULER_cancel (n->task); - n->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (timeout), - &master_task, - n); + n->task = GNUNET_SCHEDULER_add_at (timeout, + &master_task, + n); } n->timeout = timeout; GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -804,7 +765,7 @@ set_state_and_timeout (struct NeighbourMapEntry *n, static void set_alternative_address (struct NeighbourMapEntry *n, const struct GNUNET_HELLO_Address *address, - struct Session *session, + struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { @@ -862,87 +823,57 @@ set_alternative_address (struct NeighbourMapEntry *n, /** - * Initialize the primary address of a neighbour + * Transmit a message using the current session of the given + * neighbour. * - * @param n the neighbour - * @param address address of the other peer, NULL if other peer - * connected to us - * @param session session to use (or NULL, in which case an - * address must be setup) - * @param bandwidth_in inbound quota to be used when connection is up - * @param bandwidth_out outbound quota to be used when connection is up + * @param n entry for the recipient + * @param msgbuf buffer to transmit + * @param msgbuf_size number of bytes in @a msgbuf buffer + * @param priority transmission priority + * @param timeout transmission timeout + * @param use_keepalive_timeout #GNUNET_YES to use plugin-specific keep-alive + * timeout (@a timeout is ignored in that case), #GNUNET_NO otherwise + * @param cont continuation to call when finished (can be NULL) + * @param cont_cls closure for @a cont + * @return timeout (copy of @a timeout or a calculated one if + * @a use_keepalive_timeout is #GNUNET_YES. */ -static void -set_primary_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) +static struct GNUNET_TIME_Relative +send_with_session (struct NeighbourMapEntry *n, + const void *msgbuf, + size_t msgbuf_size, + uint32_t priority, + struct GNUNET_TIME_Relative timeout, + unsigned int use_keepalive_timeout, + GNUNET_TRANSPORT_TransmitContinuation cont, + void *cont_cls) { - if (session == n->primary_address.session) - { - GST_validation_set_address_use (n->primary_address.address, - GNUNET_YES); - if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__) - { - n->primary_address.bandwidth_in = bandwidth_in; - GST_neighbours_set_incoming_quota (&address->peer, - bandwidth_in); - } - if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__) - { - n->primary_address.bandwidth_out = bandwidth_out; - send_outbound_quota_to_clients (&address->peer, - bandwidth_out); - } - return; - } - if ( (NULL != n->primary_address.address) && - (0 == GNUNET_HELLO_address_cmp (address, - n->primary_address.address)) ) - { - GNUNET_break (0); - return; - } - if (NULL == session) - { - GNUNET_break (0); - GST_ats_block_address (address, - session); - return; - } - if (NULL != n->primary_address.address) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Replacing existing primary address with another one\n"); - free_address (&n->primary_address); - } - n->primary_address.address = GNUNET_HELLO_address_copy (address); - n->primary_address.bandwidth_in = bandwidth_in; - n->primary_address.bandwidth_out = bandwidth_out; - n->primary_address.session = session; - n->primary_address.keep_alive_nonce = 0; - GNUNET_assert (GNUNET_YES == - GST_ats_is_known (n->primary_address.address, - n->primary_address.session)); - /* subsystems about address use */ - GST_validation_set_address_use (n->primary_address.address, - GNUNET_YES); - GST_neighbours_set_incoming_quota (&address->peer, - bandwidth_in); - send_outbound_quota_to_clients (&address->peer, - bandwidth_out); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Neighbour `%s' switched to address `%s'\n", - GNUNET_i2s (&n->id), - GST_plugins_a2s(address)); + struct GNUNET_TRANSPORT_PluginFunctions *papi; + struct GNUNET_TIME_Relative result = GNUNET_TIME_UNIT_FOREVER_REL; - neighbours_changed_notification (&n->id, - n->primary_address.address, - n->state, - n->timeout, - n->primary_address.bandwidth_in, - n->primary_address.bandwidth_out); + GNUNET_assert (NULL != n->primary_address.session); + if ( ((NULL == (papi = GST_plugins_find (n->primary_address.address->transport_name)) || + (-1 == papi->send (papi->cls, + n->primary_address.session, + msgbuf, + msgbuf_size, + priority, + (result = (GNUNET_NO == use_keepalive_timeout) ? timeout : + GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + papi->query_keepalive_factor (papi->cls))), + cont, + cont_cls)))) && + (NULL != cont)) + cont (cont_cls, + &n->id, + GNUNET_SYSERR, + msgbuf_size, + 0); + GST_neighbours_notify_data_sent (n->primary_address.address, + n->primary_address.session, + msgbuf_size); + GNUNET_break (NULL != papi); + return result; } @@ -1040,61 +971,6 @@ free_neighbour (struct NeighbourMapEntry *n) } -/** - * Transmit a message using the current session of the given - * neighbour. - * - * @param n entry for the recipient - * @param msgbuf buffer to transmit - * @param msgbuf_size number of bytes in @a msgbuf buffer - * @param priority transmission priority - * @param timeout transmission timeout - * @param use_keepalive_timeout #GNUNET_YES to use plugin-specific keep-alive - * timeout (@a timeout is ignored in that case), #GNUNET_NO otherwise - * @param cont continuation to call when finished (can be NULL) - * @param cont_cls closure for @a cont - * @return timeout (copy of @a timeout or a calculated one if - * @a use_keepalive_timeout is #GNUNET_YES. - */ -static struct GNUNET_TIME_Relative -send_with_session (struct NeighbourMapEntry *n, - const void *msgbuf, - size_t msgbuf_size, - uint32_t priority, - struct GNUNET_TIME_Relative timeout, - unsigned int use_keepalive_timeout, - GNUNET_TRANSPORT_TransmitContinuation cont, - void *cont_cls) -{ - struct GNUNET_TRANSPORT_PluginFunctions *papi; - struct GNUNET_TIME_Relative result = GNUNET_TIME_UNIT_FOREVER_REL; - - GNUNET_assert (NULL != n->primary_address.session); - if ( ((NULL == (papi = GST_plugins_find (n->primary_address.address->transport_name)) || - (-1 == papi->send (papi->cls, - n->primary_address.session, - msgbuf, - msgbuf_size, - priority, - (result = (GNUNET_NO == use_keepalive_timeout) ? timeout : - GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, - papi->query_keepalive_factor (papi->cls))), - cont, - cont_cls)))) && - (NULL != cont)) - cont (cont_cls, - &n->id, - GNUNET_SYSERR, - msgbuf_size, - 0); - GST_neighbours_notify_data_sent (n->primary_address.address, - n->primary_address.session, - msgbuf_size); - GNUNET_break (NULL != papi); - return result; -} - - /** * Function called when the 'DISCONNECT' message has been sent by the * plugin. Frees the neighbour --- if the entry still exists. @@ -1114,6 +990,10 @@ send_disconnect_cont (void *cls, { struct NeighbourMapEntry *n; + (void) cls; + (void) result; + (void) payload; + (void) physical; n = lookup_neighbour (target); if (NULL == n) return; /* already gone */ @@ -1133,12 +1013,12 @@ send_disconnect_cont (void *cls, static void send_disconnect (struct NeighbourMapEntry *n) { - struct SessionDisconnectMessage disconnect_msg; + struct GNUNET_ATS_SessionDisconnectMessage disconnect_msg; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending DISCONNECT message to peer `%4s'\n", GNUNET_i2s (&n->id)); - disconnect_msg.header.size = htons (sizeof (struct SessionDisconnectMessage)); + disconnect_msg.header.size = htons (sizeof (struct GNUNET_ATS_SessionDisconnectMessage)); disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT); disconnect_msg.reserved = htonl (0); @@ -1224,26 +1104,161 @@ disconnect_neighbour (struct NeighbourMapEntry *n) * cannot send DISCONNECT */ free_neighbour (n); return; - case GNUNET_TRANSPORT_PS_DISCONNECT: - /* already disconnected, ignore */ - break; - case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: - /* already cleaned up, how did we get here!? */ - GNUNET_assert (0); - break; - default: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unhandled state `%s'\n", - GNUNET_TRANSPORT_ps2s (n->state)); + case GNUNET_TRANSPORT_PS_DISCONNECT: + /* already disconnected, ignore */ + break; + case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: + /* already cleaned up, how did we get here!? */ + GNUNET_assert (0); + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unhandled state `%s'\n", + GNUNET_TRANSPORT_ps2s (n->state)); + GNUNET_break (0); + break; + } + /* schedule timeout to clean up */ + if (NULL != n->task) + GNUNET_SCHEDULER_cancel (n->task); + n->task = GNUNET_SCHEDULER_add_delayed (DISCONNECT_SENT_TIMEOUT, + &master_task, + n); +} + + +/** + * Change the incoming quota for the given peer. Updates + * our own receive rate and informs the neighbour about + * the new quota. + * + * @param n neighbour entry to change quota for + * @param quota new quota + * @return #GNUNET_YES if @a n is still valid, #GNUNET_NO if + * @a n was freed + */ +static int +set_incoming_quota (struct NeighbourMapEntry *n, + struct GNUNET_BANDWIDTH_Value32NBO quota) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting inbound quota of %u Bps for peer `%s' to all clients\n", + ntohl (quota.value__), GNUNET_i2s (&n->id)); + GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, + quota); + if (0 != ntohl (quota.value__)) + { + struct GNUNET_ATS_SessionQuotaMessage sqm; + + sqm.header.size = htons (sizeof (struct GNUNET_ATS_SessionQuotaMessage)); + sqm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA); + sqm.quota = quota.value__; + if (NULL != n->primary_address.session) + (void) send_with_session (n, + &sqm, + sizeof (sqm), + UINT32_MAX - 1, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, + NULL, NULL); + return GNUNET_YES; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Disconnecting peer `%s' due to SET_QUOTA\n", + GNUNET_i2s (&n->id)); + if (GNUNET_YES == test_connected (n)) + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# disconnects due to quota of 0"), + 1, GNUNET_NO); + disconnect_neighbour (n); + return GNUNET_NO; +} + + +/** + * Initialize the primary address of a neighbour + * + * @param n the neighbour + * @param address address of the other peer, NULL if other peer + * connected to us + * @param session session to use (or NULL, in which case an + * address must be setup) + * @param bandwidth_in inbound quota to be used when connection is up + * @param bandwidth_out outbound quota to be used when connection is up + */ +static void +set_primary_address (struct NeighbourMapEntry *n, + const struct GNUNET_HELLO_Address *address, + struct GNUNET_ATS_Session *session, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) +{ + if (session == n->primary_address.session) + { + GST_validation_set_address_use (n->primary_address.address, + GNUNET_YES); + if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__) + { + n->primary_address.bandwidth_in = bandwidth_in; + if (GNUNET_YES != + set_incoming_quota (n, + bandwidth_in)) + return; + } + if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__) + { + n->primary_address.bandwidth_out = bandwidth_out; + send_outbound_quota_to_clients (n); + } + return; + } + if ( (NULL != n->primary_address.address) && + (0 == GNUNET_HELLO_address_cmp (address, + n->primary_address.address)) ) + { GNUNET_break (0); - break; + return; } - /* schedule timeout to clean up */ - if (NULL != n->task) - GNUNET_SCHEDULER_cancel (n->task); - n->task = GNUNET_SCHEDULER_add_delayed (DISCONNECT_SENT_TIMEOUT, - &master_task, - n); + if (NULL == session) + { + GNUNET_break (0); + GST_ats_block_address (address, + session); + return; + } + if (NULL != n->primary_address.address) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Replacing existing primary address with another one\n"); + free_address (&n->primary_address); + } + n->primary_address.address = GNUNET_HELLO_address_copy (address); + n->primary_address.bandwidth_in = bandwidth_in; + n->primary_address.bandwidth_out = bandwidth_out; + n->primary_address.session = session; + n->primary_address.keep_alive_nonce = 0; + GNUNET_assert (GNUNET_YES == + GST_ats_is_known (n->primary_address.address, + n->primary_address.session)); + /* subsystems about address use */ + GST_validation_set_address_use (n->primary_address.address, + GNUNET_YES); + if (GNUNET_YES != + set_incoming_quota (n, + bandwidth_in)) + return; + send_outbound_quota_to_clients (n); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Neighbour `%s' switched to address `%s'\n", + GNUNET_i2s (&n->id), + GST_plugins_a2s(address)); + + neighbours_changed_notification (&n->id, + n->primary_address.address, + n->state, + n->timeout, + n->primary_address.bandwidth_in, + n->primary_address.bandwidth_out); } @@ -1289,12 +1304,12 @@ transmit_send_continuation (void *cls, if (bytes_in_send_queue < mq->message_buf_size) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Bytes_in_send_queue `%u', Message_size %u, result: %s, payload %u, on wire %u\n", + "Bytes_in_send_queue `%llu', Message_size %u, result: %s, payload %u, on wire %u\n", bytes_in_send_queue, - mq->message_buf_size, + (unsigned int) mq->message_buf_size, (GNUNET_OK == success) ? "OK" : "FAIL", - size_payload, - physical); + (unsigned int) size_payload, + (unsigned int) physical); GNUNET_break (0); } @@ -1318,7 +1333,7 @@ transmit_send_continuation (void *cls, "Sending message to `%s' of type %u with %u bytes was a %s\n", GNUNET_i2s (receiver), ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type), - mq->message_buf_size, + (unsigned int) mq->message_buf_size, (success == GNUNET_OK) ? "success" : "FAILURE"); if (NULL != mq->cont) mq->cont (mq->cont_cls, @@ -1387,6 +1402,14 @@ try_transmission_to_peer (struct NeighbourMapEntry *n) } if (NULL == mq) return; /* no more messages */ + if (NULL == n->primary_address.address) + { + /* transmit_send_continuation() caused us to drop session, + can't try transmission anymore. */ + return; + } + + GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq); @@ -1394,7 +1417,7 @@ try_transmission_to_peer (struct NeighbourMapEntry *n) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Giving message with %u bytes to plugin session %p\n", - mq->message_buf_size, + (unsigned int) mq->message_buf_size, n->primary_address.session); (void) send_with_session (n, mq->message_buf, @@ -1418,7 +1441,7 @@ try_transmission_to_peer (struct NeighbourMapEntry *n) static void send_keepalive (struct NeighbourMapEntry *n) { - struct SessionKeepAliveMessage m; + struct GNUNET_ATS_SessionKeepAliveMessage m; struct GNUNET_TIME_Relative timeout; uint32_t nonce; @@ -1436,7 +1459,7 @@ send_keepalive (struct NeighbourMapEntry *n) "Sending KEEPALIVE to peer `%s' with nonce %u\n", GNUNET_i2s (&n->id), nonce); - m.header.size = htons (sizeof (struct SessionKeepAliveMessage)); + m.header.size = htons (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage)); m.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE); m.nonce = htonl (nonce); @@ -1470,16 +1493,16 @@ GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m) { struct NeighbourMapEntry *n; - const struct SessionKeepAliveMessage *msg_in; - struct SessionKeepAliveMessage msg; + const struct GNUNET_ATS_SessionKeepAliveMessage *msg_in; + struct GNUNET_ATS_SessionKeepAliveMessage msg; - if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size)) + if (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs (m->size)) { GNUNET_break_op (0); return; } - msg_in = (const struct SessionKeepAliveMessage *) m; + msg_in = (const struct GNUNET_ATS_SessionKeepAliveMessage *) m; if (NULL == (n = lookup_neighbour (neighbour))) { GNUNET_STATISTICS_update (GST_stats, @@ -1507,12 +1530,12 @@ GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour, GNUNET_NO); /* send reply to allow neighbour to measure latency */ - msg.header.size = htons (sizeof (struct SessionKeepAliveMessage)); + msg.header.size = htons (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE); msg.nonce = msg_in->nonce; (void) send_with_session (n, &msg, - sizeof (struct SessionKeepAliveMessage), + sizeof (struct GNUNET_ATS_SessionKeepAliveMessage), UINT32_MAX /* priority */, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, @@ -1533,17 +1556,17 @@ GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m) { struct NeighbourMapEntry *n; - const struct SessionKeepAliveMessage *msg; + const struct GNUNET_ATS_SessionKeepAliveMessage *msg; struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_TIME_Relative latency; - if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size)) + if (sizeof (struct GNUNET_ATS_SessionKeepAliveMessage) != ntohs (m->size)) { GNUNET_break_op (0); return; } - msg = (const struct SessionKeepAliveMessage *) m; + msg = (const struct GNUNET_ATS_SessionKeepAliveMessage *) m; if (NULL == (n = lookup_neighbour (neighbour))) { GNUNET_STATISTICS_update (GST_stats, @@ -1650,16 +1673,12 @@ GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity *sender } if (NULL == (n = lookup_neighbour (sender))) { - GST_neighbours_try_connect (sender); - if (NULL == (n = lookup_neighbour (sender))) - { - GNUNET_STATISTICS_update (GST_stats, - gettext_noop - ("# messages discarded due to lack of neighbour record"), - 1, GNUNET_NO); - *do_forward = GNUNET_NO; - return GNUNET_TIME_UNIT_ZERO; - } + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# messages discarded due to lack of neighbour record"), + 1, + GNUNET_NO); + *do_forward = GNUNET_NO; + return GNUNET_TIME_UNIT_ZERO; } if (! test_connected (n)) { @@ -1763,14 +1782,14 @@ GST_neighbours_send (const struct GNUNET_PeerIdentity *target, mq = GNUNET_malloc (sizeof (struct MessageQueue) + msg_size); mq->cont = cont; mq->cont_cls = cont_cls; - memcpy (&mq[1], msg, msg_size); + GNUNET_memcpy (&mq[1], msg, msg_size); mq->message_buf = (const char *) &mq[1]; mq->message_buf_size = msg_size; mq->timeout = GNUNET_TIME_relative_to_absolute (timeout); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Enqueueing %u bytes to send to peer %s\n", - msg_size, + (unsigned int) msg_size, GNUNET_i2s (target)); GNUNET_CONTAINER_DLL_insert_tail (n->messages_head, n->messages_tail, @@ -1802,6 +1821,9 @@ send_session_syn_cont (void *cls, { struct NeighbourMapEntry *n; + (void) cls; + (void) size_payload; + (void) size_on_wire; n = lookup_neighbour (target); if (NULL == n) { @@ -1975,6 +1997,9 @@ send_session_syn_ack_cont (void *cls, { struct NeighbourMapEntry *n; + (void) cls; + (void) size_payload; + (void) size_on_wire; n = lookup_neighbour (target); if (NULL == n) { @@ -2023,7 +2048,7 @@ send_syn_ack_message (struct NeighbourAddress *na, struct GNUNET_TIME_Absolute timestamp) { const struct GNUNET_HELLO_Address *address = na->address; - struct Session *session = na->session; + struct GNUNET_ATS_Session *session = na->session; struct GNUNET_TRANSPORT_PluginFunctions *papi; struct TransportSynMessage connect_msg; struct NeighbourMapEntry *n; @@ -2114,7 +2139,9 @@ inbound_bw_tracker_update (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New inbound delay for peer `%s' is %llu ms\n", GNUNET_i2s (&n->id), - delay.rel_value_us / 1000); + (unsigned long long) delay.rel_value_us / 1000LL); + if (NULL == n->primary_address.session) + return; papi->update_inbound_delay (papi->cls, &n->id, n->primary_address.session, @@ -2133,6 +2160,15 @@ setup_neighbour (const struct GNUNET_PeerIdentity *peer) { struct NeighbourMapEntry *n; + if (0 == + memcmp (&GST_my_identity, + peer, + sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cowardly refusing to consider myself my neighbour!\n"); + return NULL; + } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating new neighbour entry for `%s'\n", GNUNET_i2s (peer)); @@ -2140,6 +2176,7 @@ setup_neighbour (const struct GNUNET_PeerIdentity *peer) n->id = *peer; n->ack_state = ACK_UNDEFINED; n->last_util_transmission = GNUNET_TIME_absolute_get(); + n->neighbour_receive_quota = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT; GNUNET_BANDWIDTH_tracker_init (&n->in_tracker, &inbound_bw_tracker_update, n, @@ -2151,10 +2188,12 @@ setup_neighbour (const struct GNUNET_PeerIdentity *peer) GNUNET_TIME_UNIT_FOREVER_ABS); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (neighbours, - &n->id, n, + &n->id, + n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); n->suggest_handle = GNUNET_ATS_connectivity_suggest (GST_ats_connect, - peer); + peer, + 0); return n; } @@ -2192,139 +2231,6 @@ struct BlacklistCheckSwitchContext }; -/** - * Black list check result for try_connect call - * If connection to the peer is allowed request adddress and - * - * @param cls blc_ctx bl context - * @param peer the peer - * @param address address associated with the request - * @param session session associated with the request - * @param result #GNUNET_OK if the connection is allowed, - * #GNUNET_NO if not, - * #GNUNET_SYSERR if operation was aborted - */ -static void -try_connect_bl_check_cont (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_HELLO_Address *address, - struct Session *session, - int result) -{ - struct BlacklistCheckSwitchContext *blc_ctx = cls; - struct NeighbourMapEntry *n; - - GNUNET_CONTAINER_DLL_remove (pending_bc_head, - pending_bc_tail, - blc_ctx); - GNUNET_free (blc_ctx); - if (GNUNET_OK != result) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Blacklisting disapproved to connect to peer `%s'\n"), - GNUNET_i2s (peer)); - return; - } - - /* Setup a new neighbour */ - if (NULL != lookup_neighbour(peer)) - return; /* The neighbor was created in the meantime while waited for BL clients */ - - n = setup_neighbour (peer); - - /* Request address suggestions for this peer */ - set_state_and_timeout (n, - GNUNET_TRANSPORT_PS_INIT_ATS, - GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); -} - - -/** - * Try to create a connection to the given target (eventually). - * - * @param target peer to try to connect to - */ -void -GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target) -{ - struct NeighbourMapEntry *n; - struct GST_BlacklistCheck *blc; - struct BlacklistCheckSwitchContext *blc_ctx; - - if (NULL == neighbours) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Asked to connect to peer `%s' during shutdown\n", - GNUNET_i2s (target)); - return; /* during shutdown, do nothing */ - } - n = lookup_neighbour (target); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Asked to connect to peer `%s' (state: %s)\n", - GNUNET_i2s (target), - (NULL != n) ? GNUNET_TRANSPORT_ps2s(n->state) : "NEW PEER"); - if (NULL != n) - { - switch (n->state) - { - case GNUNET_TRANSPORT_PS_NOT_CONNECTED: - /* this should not be possible */ - GNUNET_break (0); - free_neighbour (n); - break; - case GNUNET_TRANSPORT_PS_INIT_ATS: - case GNUNET_TRANSPORT_PS_SYN_SENT: - case GNUNET_TRANSPORT_PS_SYN_RECV_ATS: - case GNUNET_TRANSPORT_PS_SYN_RECV_ACK: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Ignoring request to try to connect to `%s', already trying!\n", - GNUNET_i2s (target)); - return; /* already trying */ - case GNUNET_TRANSPORT_PS_CONNECTED: - case GNUNET_TRANSPORT_PS_RECONNECT_ATS: - case GNUNET_TRANSPORT_PS_RECONNECT_SENT: - case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Ignoring request to try to connect, already connected to `%s'!\n", - GNUNET_i2s (target)); - return; /* already connected */ - case GNUNET_TRANSPORT_PS_DISCONNECT: - /* get rid of remains, ready to re-try immediately */ - free_neighbour (n); - break; - case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: - /* should not be possible */ - GNUNET_assert (0); - return; - default: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unhandled state `%s'\n", - GNUNET_TRANSPORT_ps2s (n->state)); - GNUNET_break (0); - free_neighbour (n); - break; - } - } - - /* Do blacklist check if connecting to this peer is allowed */ - blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext); - GNUNET_CONTAINER_DLL_insert (pending_bc_head, - pending_bc_tail, - blc_ctx); - - if (NULL != - (blc = GST_blacklist_test_allowed (target, - NULL, - &try_connect_bl_check_cont, - blc_ctx, - NULL, - NULL))) - { - blc_ctx->blc = blc; - } -} - - /** * We received a 'SYN' message from the other peer. * Consider switching to it. @@ -2360,11 +2266,20 @@ GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message, scm = (const struct TransportSynMessage *) message; GNUNET_break_op (0 == ntohl (scm->reserved)); ts = GNUNET_TIME_absolute_ntoh (scm->timestamp); + if (0 == + memcmp (&GST_my_identity, + peer, + sizeof (struct GNUNET_PeerIdentity))) + { + /* loopback connection-to-self, ignore */ + return GNUNET_SYSERR; + } n = lookup_neighbour (peer); if (NULL == n) { /* This is a new neighbour and set to not connected */ n = setup_neighbour (peer); + GNUNET_assert (NULL != n); } /* Remember this SYN message in neighbour */ @@ -2434,6 +2349,7 @@ GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message, /* Get rid of remains and re-try */ free_neighbour (n); n = setup_neighbour (peer); + GNUNET_assert (NULL != n); /* Remember the SYN time stamp for ACK message */ n->ack_state = ACK_SEND_SYN_ACK; n->connect_ack_timestamp = ts; @@ -2475,12 +2391,11 @@ GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message, */ static int try_run_fast_ats_update (const struct GNUNET_HELLO_Address *address, - struct Session *session, + struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { struct NeighbourMapEntry *n; - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min; n = lookup_neighbour (&address->peer); if ( (NULL == n) || @@ -2499,14 +2414,19 @@ try_run_fast_ats_update (const struct GNUNET_HELLO_Address *address, GST_ats_is_known (n->primary_address.address, n->primary_address.session)); } - n->primary_address.bandwidth_in = bandwidth_in; - n->primary_address.bandwidth_out = bandwidth_out; - GST_neighbours_set_incoming_quota (&address->peer, - bandwidth_in); - bandwidth_min = GNUNET_BANDWIDTH_value_min (bandwidth_out, - n->neighbour_receive_quota); - send_outbound_quota_to_clients (&address->peer, - bandwidth_min); + if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__) + { + n->primary_address.bandwidth_in = bandwidth_in; + if (GNUNET_YES != + set_incoming_quota (n, + bandwidth_in)) + return GNUNET_NO; + } + if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__) + { + n->primary_address.bandwidth_out = bandwidth_out; + send_outbound_quota_to_clients (n); + } return GNUNET_OK; } @@ -2528,7 +2448,7 @@ static void switch_address_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, - struct Session *session, + struct GNUNET_ATS_Session *session, int result) { struct BlacklistCheckSwitchContext *blc_ctx = cls; @@ -2539,7 +2459,10 @@ switch_address_bl_check_cont (void *cls, goto cleanup; papi = GST_plugins_find (address->transport_name); - GNUNET_assert (NULL != papi); + if (NULL == papi) { + /* This can happen during shutdown. */ + goto cleanup; + } if (GNUNET_NO == result) { @@ -2552,8 +2475,9 @@ switch_address_bl_check_cont (void *cls, "# ATS suggestions ignored (blacklist denied)", 1, GNUNET_NO); - papi->disconnect_session (papi->cls, - session); + if (NULL != session) + papi->disconnect_session (papi->cls, + session); if (GNUNET_YES != GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)) @@ -2608,6 +2532,12 @@ switch_address_bl_check_cont (void *cls, if (NULL == (n = lookup_neighbour (peer))) { n = setup_neighbour (peer); + if (NULL == n) + { + /* not sure how this can happen... */ + GNUNET_break (0); + goto cleanup; + } n->state = GNUNET_TRANSPORT_PS_INIT_ATS; } @@ -2821,7 +2751,7 @@ switch_address_bl_check_cont (void *cls, */ void GST_neighbours_switch_to_address (const struct GNUNET_HELLO_Address *address, - struct Session *session, + struct GNUNET_ATS_Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { @@ -2901,6 +2831,7 @@ send_utilization_data (void *cls, uint32_t bps_out; struct GNUNET_TIME_Relative delta; + (void) cls; if ( (GNUNET_YES != test_connected (n)) || (NULL == n->primary_address.address) ) return GNUNET_OK; @@ -2931,13 +2862,12 @@ send_utilization_data (void *cls, /** * Task transmitting utilization in a regular interval * - * @param cls the 'struct NeighbourMapEntry' for which we are running - * @param tc scheduler context (unused) + * @param cls the `struct NeighbourMapEntry` for which we are running */ static void -utilization_transmission (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +utilization_transmission (void *cls) { + (void) cls; util_transmission_tk = NULL; GNUNET_CONTAINER_multipeermap_iterate (neighbours, &send_utilization_data, @@ -2981,7 +2911,7 @@ GST_neighbours_notify_data_recv (const struct GNUNET_HELLO_Address *address, */ void GST_neighbours_notify_data_sent (const struct GNUNET_HELLO_Address *address, - struct Session *session, + struct GNUNET_ATS_Session *session, size_t size) { struct NeighbourMapEntry *n; @@ -3001,11 +2931,9 @@ GST_neighbours_notify_data_sent (const struct GNUNET_HELLO_Address *address, * clean up after disconnect). * * @param cls the 'struct NeighbourMapEntry' for which we are running - * @param tc scheduler context (unused) */ static void -master_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +master_task (void *cls) { struct NeighbourMapEntry *n = cls; struct GNUNET_TIME_Relative delay; @@ -3179,7 +3107,7 @@ send_session_ack_message (struct NeighbourMapEntry *n) * We received a 'SESSION_SYN_ACK' message from the other peer. * Consider switching to it. * - * @param message possibly a `struct SessionConnectMessage` (check format) + * @param message possibly a `struct GNUNET_ATS_SessionConnectMessage` (check format) * @param peer identity of the peer to switch the address for * @param address address of the other peer, NULL if other peer * connected to us @@ -3189,12 +3117,13 @@ send_session_ack_message (struct NeighbourMapEntry *n) int GST_neighbours_handle_session_syn_ack (const struct GNUNET_MessageHeader *message, const struct GNUNET_HELLO_Address *address, - struct Session *session) + struct GNUNET_ATS_Session *session) { const struct TransportSynMessage *scm; struct GNUNET_TIME_Absolute ts; struct NeighbourMapEntry *n; + (void) session; if (ntohs (message->size) != sizeof (struct TransportSynMessage)) { GNUNET_break_op (0); @@ -3330,28 +3259,10 @@ GST_neighbours_handle_session_syn_ack (const struct GNUNET_MessageHeader *messag */ int GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer, - struct Session *session) + struct GNUNET_ATS_Session *session) { struct NeighbourMapEntry *n; - struct BlackListCheckContext *bcc; - struct BlackListCheckContext *bcc_next; - /* make sure to cancel all ongoing blacklist checks involving 'session' */ - bcc_next = bc_head; - while (NULL != (bcc = bcc_next)) - { - bcc_next = bcc->next; - if (bcc->na.session == session) - { - if (NULL != bcc->bc) - GST_blacklist_test_cancel (bcc->bc); - GNUNET_HELLO_address_free (bcc->na.address); - GNUNET_CONTAINER_DLL_remove (bc_head, - bc_tail, - bcc); - GNUNET_free (bcc); - } - } if (NULL == (n = lookup_neighbour (peer))) return GNUNET_NO; /* can't affect us */ if (session != n->primary_address.session) @@ -3386,11 +3297,9 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer, /* The session used to send the SYN terminated: * this implies a connect error*/ GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to send SYN in %s with `%s' %p: session terminated\n", - "CONNECT_SENT", + "Failed to send SYN in CONNECT_SENT with `%s' %p: session terminated\n", GST_plugins_a2s (n->primary_address.address), - n->primary_address.session, - GNUNET_i2s (peer)); + n->primary_address.session); /* Destroy the address since it cannot be used */ unset_primary_address (n); @@ -3416,11 +3325,9 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer, break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to send SYN in %s with `%s' %p: session terminated\n", - "RECONNECT_SENT", + "Failed to send SYN in RECONNECT_SENT with `%s' %p: session terminated\n", GST_plugins_a2s (n->primary_address.address), - n->primary_address.session, - GNUNET_i2s (peer)); + n->primary_address.session); /* Destroy the address since it cannot be used */ unset_primary_address (n); set_state_and_timeout (n, @@ -3478,7 +3385,7 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer, * If we sent a 'SYN_ACK' last, this means we are now * connected. Otherwise, do nothing. * - * @param message possibly a 'struct SessionConnectMessage' (check format) + * @param message possibly a 'struct GNUNET_ATS_SessionConnectMessage' (check format) * @param address address of the other peer * @param session session to use (or NULL) * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error @@ -3486,10 +3393,11 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer, int GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message, const struct GNUNET_HELLO_Address *address, - struct Session *session) + struct GNUNET_ATS_Session *session) { struct NeighbourMapEntry *n; + (void) session; if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); @@ -3521,8 +3429,9 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message, now wait for the ACK to finally be connected - If we sent a SYN_ACK to this peer before */ - if ( (GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) && - (ACK_SEND_ACK != n->ack_state)) + if ( ( (GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) && + (ACK_SEND_ACK != n->ack_state) ) || + (NULL == n->primary_address.address) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received unexpected ACK message from peer `%s' in state %s/%s\n", @@ -3547,6 +3456,18 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message, GNUNET_TRANSPORT_PS_CONNECTED, GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT)); + if (NULL == n->primary_address.address) { + /* See issue #3693. + * We are in state = PSY_SYN_RECV_ACK or ack_state = ACK_SEND_ACK, which + * really means we did try (and succeed) to send a SYN and are waiting for + * an ACK. + * That suggests that the primary_address used to be non-NULL, but maybe it + * got reset to NULL without the state being changed appropriately? + */ + GNUNET_break (0); + return GNUNET_OK; + } + /* Reset backoff for primary address */ GST_ats_block_reset (n->primary_address.address, n->primary_address.session); @@ -3567,52 +3488,13 @@ GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target) } -/** - * Change the incoming quota for the given peer. - * - * @param neighbour identity of peer to change qutoa for - * @param quota new quota - */ -void -GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour, - struct GNUNET_BANDWIDTH_Value32NBO quota) -{ - struct NeighbourMapEntry *n; - - if (NULL == (n = lookup_neighbour (neighbour))) - { - GNUNET_STATISTICS_update (GST_stats, - gettext_noop - ("# SET QUOTA messages ignored (no such peer)"), - 1, GNUNET_NO); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Setting inbound quota of %u Bps for peer `%s' to all clients\n", - ntohl (quota.value__), GNUNET_i2s (&n->id)); - GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, quota); - if (0 != ntohl (quota.value__)) - return; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Disconnecting peer `%4s' due to SET_QUOTA\n", - GNUNET_i2s (&n->id)); - if (GNUNET_YES == test_connected (n)) - GNUNET_STATISTICS_update (GST_stats, - gettext_noop ("# disconnects due to quota of 0"), - 1, GNUNET_NO); - disconnect_neighbour (n); -} - - /** * Task to asynchronously run #free_neighbour(). * * @param cls the `struct NeighbourMapEntry` to free - * @param tc unused */ static void -delayed_disconnect (void *cls, - const struct GNUNET_SCHEDULER_TaskContext* tc) +delayed_disconnect (void *cls) { struct NeighbourMapEntry *n = cls; @@ -3625,7 +3507,7 @@ delayed_disconnect (void *cls, /** - * We received a quoat message from the given peer, + * We received a quota message from the given peer, * validate and process. * * @param peer sender of the message @@ -3636,13 +3518,13 @@ GST_neighbours_handle_quota_message (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg) { struct NeighbourMapEntry *n; - const struct SessionQuotaMessage *sqm; - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_min; + const struct GNUNET_ATS_SessionQuotaMessage *sqm; + struct GNUNET_BANDWIDTH_Value32NBO last; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received QUOTA message from peer `%s'\n", GNUNET_i2s (peer)); - if (ntohs (msg->size) != sizeof (struct SessionQuotaMessage)) + if (ntohs (msg->size) != sizeof (struct GNUNET_ATS_SessionQuotaMessage)) { GNUNET_break_op (0); GNUNET_STATISTICS_update (GST_stats, @@ -3655,18 +3537,19 @@ GST_neighbours_handle_quota_message (const struct GNUNET_PeerIdentity *peer, gettext_noop ("# QUOTA messages received"), 1, GNUNET_NO); - sqm = (const struct SessionQuotaMessage *) msg; + sqm = (const struct GNUNET_ATS_SessionQuotaMessage *) msg; if (NULL == (n = lookup_neighbour (peer))) { /* gone already */ return; } - n->neighbour_receive_quota = GNUNET_BANDWIDTH_value_init (ntohl (sqm->quota)); - - bandwidth_min = GNUNET_BANDWIDTH_value_min (n->primary_address.bandwidth_out, - n->neighbour_receive_quota); - send_outbound_quota_to_clients (peer, - bandwidth_min); + last = GNUNET_BANDWIDTH_value_max (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, + GNUNET_BANDWIDTH_value_init (ntohl (sqm->quota))); + if (last.value__ != n->neighbour_receive_quota.value__) + { + n->neighbour_receive_quota = last; + send_outbound_quota_to_clients (n); + } } @@ -3682,12 +3565,12 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer const struct GNUNET_MessageHeader *msg) { struct NeighbourMapEntry *n; - const struct SessionDisconnectMessage *sdm; + const struct GNUNET_ATS_SessionDisconnectMessage *sdm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DISCONNECT message from peer `%s'\n", GNUNET_i2s (peer)); - if (ntohs (msg->size) != sizeof (struct SessionDisconnectMessage)) + if (ntohs (msg->size) != sizeof (struct GNUNET_ATS_SessionDisconnectMessage)) { GNUNET_break_op (0); GNUNET_STATISTICS_update (GST_stats, @@ -3701,7 +3584,7 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer gettext_noop ("# DISCONNECT messages received"), 1, GNUNET_NO); - sdm = (const struct SessionDisconnectMessage *) msg; + sdm = (const struct GNUNET_ATS_SessionDisconnectMessage *) msg; if (NULL == (n = lookup_neighbour (peer))) { /* gone already */ @@ -3745,7 +3628,11 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer GNUNET_break_op (0); return; } - n->delayed_disconnect_task = GNUNET_SCHEDULER_add_now (&delayed_disconnect, n); + if (NULL == n->delayed_disconnect_task) + { + n->delayed_disconnect_task = GNUNET_SCHEDULER_add_now (&delayed_disconnect, + n); + } } @@ -3784,6 +3671,7 @@ neighbours_iterate (void *cls, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; + (void) key; if (NULL != n->primary_address.address) { bandwidth_in = n->primary_address.bandwidth_in; @@ -3808,10 +3696,11 @@ neighbours_iterate (void *cls, * Iterate over all connected neighbours. * * @param cb function to call - * @param cb_cls closure for cb + * @param cb_cls closure for @a cb */ void -GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls) +GST_neighbours_iterate (GST_NeighbourIterator cb, + void *cb_cls) { struct IteratorContext ic; @@ -3855,7 +3744,7 @@ GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target) * @param peer * @return address currently used */ -struct GNUNET_HELLO_Address * +const struct GNUNET_HELLO_Address * GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer) { struct NeighbourMapEntry *n; @@ -3875,6 +3764,7 @@ GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer) void GST_neighbours_start (unsigned int max_fds) { + (void) max_fds; neighbours = GNUNET_CONTAINER_multipeermap_create (NEIGHBOUR_TABLE_SIZE, GNUNET_NO); util_transmission_tk = GNUNET_SCHEDULER_add_delayed (UTIL_TRANSMISSION_INTERVAL, @@ -3888,7 +3778,7 @@ GST_neighbours_start (unsigned int max_fds) * * @param cls unused * @param key hash of neighbour's public key (not used) - * @param value the 'struct NeighbourMapEntry' of the neighbour + * @param value the `struct NeighbourMapEntry` of the neighbour * @return #GNUNET_OK (continue to iterate) */ static int @@ -3898,6 +3788,8 @@ disconnect_all_neighbours (void *cls, { struct NeighbourMapEntry *n = value; + (void) cls; + (void) key; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s' during shutdown\n", GNUNET_i2s (&n->id)); @@ -3912,9 +3804,6 @@ disconnect_all_neighbours (void *cls, void GST_neighbours_stop () { - struct BlacklistCheckSwitchContext *cur; - struct BlacklistCheckSwitchContext *next; - if (NULL == neighbours) return; if (NULL != util_transmission_tk) @@ -3927,21 +3816,6 @@ GST_neighbours_stop () NULL); GNUNET_CONTAINER_multipeermap_destroy (neighbours); neighbours = NULL; - next = pending_bc_head; - for (cur = next; NULL != cur; cur = next) - { - next = cur->next; - GNUNET_CONTAINER_DLL_remove (pending_bc_head, - pending_bc_tail, - cur); - - if (NULL != cur->blc) - { - GST_blacklist_test_cancel (cur->blc); - cur->blc = NULL; - } - GNUNET_free (cur); - } }