X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fgnunet-service-transport_manipulation.c;h=0b042dd6a7a4a768a5d1258b8207191d3cd47f79;hb=31adcb0e020b7861ee7f306a6e2fac0df9b10290;hp=fa8621e3d32ecf5d5c64fa37ff12117a90ca7af5;hpb=08cd1ab49a879b8c8357d3bc60fe05deaeb929c9;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-service-transport_manipulation.c b/src/transport/gnunet-service-transport_manipulation.c index fa8621e3d..0b042dd6a 100644 --- a/src/transport/gnunet-service-transport_manipulation.c +++ b/src/transport/gnunet-service-transport_manipulation.c @@ -1,22 +1,22 @@ /* - This file is part of GNUnet. - (C) 2010,2011 Christian Grothoff (and other contributing authors) + This file is part of GNUnet. + Copyright (C) 2010-2013 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 Affero 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. + 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 + Affero 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. -*/ + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later + */ /** * @file transport/gnunet-service-transport_manipulation.c @@ -25,8 +25,6 @@ * @author Matthias Wachs */ #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" @@ -34,357 +32,554 @@ #include "gnunet-service-transport.h" #include "transport.h" -#define DELAY 0 -#define DISTANCE 1 - -struct GST_ManipulationHandle man_handle; - -struct GST_ManipulationHandle +/** + * Struct containing information about manipulations to a specific peer + */ +struct TM_Peer { - struct GNUNET_CONTAINER_MultiHashMap *peers; - - /** - * General inbound delay - */ - struct GNUNET_TIME_Relative delay_in; + /** + * Peer ID + */ + struct GNUNET_PeerIdentity peer; + + /** + * How long to delay incoming messages for this peer. + */ + struct GNUNET_TIME_Relative delay_in; + + /** + * How long to delay outgoing messages for this peer. + */ + struct GNUNET_TIME_Relative delay_out; + + /** + * Manipulated properties to use for this peer. + */ + struct GNUNET_ATS_Properties properties; + + /** + * Task to schedule delayed sendding + */ + struct GNUNET_SCHEDULER_Task *send_delay_task; + + /** + * Send queue DLL head + */ + struct DelayQueueEntry *send_head; + + /** + * Send queue DLL tail + */ + struct DelayQueueEntry *send_tail; +}; - /** - * General outbound delay - */ - struct GNUNET_TIME_Relative delay_out; +/** + * Entry in the delay queue for an outbound delayed message + */ +struct DelayQueueEntry +{ + /** + * Next in DLL + */ + struct DelayQueueEntry *prev; + + /** + * Previous in DLL + */ + struct DelayQueueEntry *next; + + /** + * Peer this entry is belonging to if (NULL == tmp): enqueued in + * generic DLL and scheduled by generic_send_delay_task else: + * enqueued in tmp->send_head and tmp->send_tail and scheduled by + * tmp->send_delay_task + */ + struct TM_Peer *tmp; + + /** + * Peer ID + */ + struct GNUNET_PeerIdentity id; + + /** + * Absolute time when to send + */ + struct GNUNET_TIME_Absolute sent_at; + + /** + * The message + */ + void *msg; + + /** + * The message size + */ + size_t msg_size; + + /** + * Message timeout + */ + struct GNUNET_TIME_Relative timeout; + + /** + * Transports send continuation + */ + GST_NeighbourSendContinuation cont; + + /** + * Transports send continuation cls + */ + void *cont_cls; }; +/** + * Hashmap contain all peers currently manipulated + */ +static struct GNUNET_CONTAINER_MultiPeerMap *peers; -struct TM_Peer; - +/** + * Inbound delay to apply to all peers. + */ +static struct GNUNET_TIME_Relative delay_in; +/** + * Outbound delay to apply to all peers. + */ +static struct GNUNET_TIME_Relative delay_out; -struct DelayQueueEntry -{ - struct DelayQueueEntry *prev; - struct DelayQueueEntry *next; - struct TM_Peer *tmp; - struct GNUNET_TIME_Absolute sent_at; - void *msg; - size_t msg_size; - struct GNUNET_TIME_Relative timeout; - GST_NeighbourSendContinuation cont; - void *cont_cls; -}; +/** + * DLL head for delayed messages based on general delay + */ +static struct DelayQueueEntry *generic_dqe_head; -struct TM_Peer -{ - struct GNUNET_PeerIdentity peer; - uint32_t metrics [TM_BOTH][GNUNET_ATS_QualityPropertiesCount]; - GNUNET_SCHEDULER_TaskIdentifier send_delay_task; - struct DelayQueueEntry *send_head; - struct DelayQueueEntry *send_tail; -}; +/** + * DLL tail for delayed messages based on general delay + */ +static struct DelayQueueEntry *generic_dqe_tail; +/** + * Task to schedule delayed sending based on general delay + */ +static struct GNUNET_SCHEDULER_Task *generic_send_delay_task; -static void -set_delay(struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value) +/** + * Set traffic metric to manipulate + * + * @param message containing information + */ +void +GST_manipulation_set_metric (const struct TrafficMetricMessage *tm) { - uint32_t val; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Set traffic metrics %s for peer `%s' in direction %s to %u\n", - "DELAY", GNUNET_i2s(peer), - (TM_BOTH == direction) ? "BOTH" : (TM_SEND == direction) ? "SEND": "RECEIVE", value); - - if (UINT32_MAX == value) - val = UINT32_MAX - 1; /* prevent overflow */ - else if (0 == value) - val = UINT32_MAX; /* disable */ - else - val = value; - - switch (direction) { - case TM_BOTH: - tmp->metrics[TM_SEND][DELAY] = val; - tmp->metrics[TM_RECEIVE][DELAY] = val; - break; - case TM_SEND: - tmp->metrics[TM_SEND][DELAY] = val; - break; - case TM_RECEIVE: - tmp->metrics[TM_RECEIVE][DELAY] = val; - break; - default: - break; - } - + static struct GNUNET_PeerIdentity zero; + struct TM_Peer *tmp; + + if (0 == memcmp (&tm->peer, + &zero, + sizeof(struct GNUNET_PeerIdentity))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received traffic metrics for all peers\n"); + delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in); + delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received traffic metrics for peer `%s'\n", + GNUNET_i2s (&tm->peer)); + if (NULL == + (tmp = GNUNET_CONTAINER_multipeermap_get (peers, + &tm->peer))) + { + tmp = GNUNET_new (struct TM_Peer); + tmp->peer = tm->peer; + GNUNET_CONTAINER_multipeermap_put (peers, + &tm->peer, + tmp, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); + } + GNUNET_ATS_properties_ntoh (&tmp->properties, + &tm->properties); + tmp->delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in); + tmp->delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out); } + +/** + * We have delayed transmission, now it is time to send the + * message. + * + * @param cls the `struct DelayQueueEntry` to transmit + */ static void -set_distance (struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value) +send_delayed (void *cls) { - uint32_t val; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Set traffic metrics %s for peer `%s' in direction %s to %u\n", - "DISTANCE", GNUNET_i2s(peer), - (TM_BOTH == direction) ? "BOTH" : (TM_SEND == direction) ? "SEND": "RECEIVE", value); - - if (UINT32_MAX == value) - val = UINT32_MAX - 1; /* prevent overflow */ - else if (0 == value) - val = UINT32_MAX; /* disable */ - else - val = value; - - switch (direction) { - case TM_BOTH: - tmp->metrics[TM_SEND][DISTANCE] = val; - tmp->metrics[TM_RECEIVE][DISTANCE] = val; - break; - case TM_SEND: - tmp->metrics[TM_SEND][DISTANCE] = val; - break; - case TM_RECEIVE: - tmp->metrics[TM_RECEIVE][DISTANCE] = val; - break; - default: - break; - } + struct DelayQueueEntry *dqe = cls; + struct DelayQueueEntry *next; + struct TM_Peer *tmp = dqe->tmp; + + GNUNET_break (GNUNET_YES == + GST_neighbours_test_connected (&dqe->id)); + if (NULL != tmp) + { + tmp->send_delay_task = NULL; + GNUNET_CONTAINER_DLL_remove (tmp->send_head, + tmp->send_tail, + dqe); + next = tmp->send_head; + if (NULL != next) + { + /* More delayed messages */ + tmp->send_delay_task = GNUNET_SCHEDULER_add_at (next->sent_at, + &send_delayed, + next); + } + } + else + { + /* Remove from generic queue */ + generic_send_delay_task = NULL; + GNUNET_CONTAINER_DLL_remove (generic_dqe_head, + generic_dqe_tail, + dqe); + next = generic_dqe_head; + if (NULL != next) + { + /* More delayed messages */ + generic_send_delay_task = GNUNET_SCHEDULER_add_at (next->sent_at, + &send_delayed, + next); + } + } + GST_neighbours_send (&dqe->id, + dqe->msg, + dqe->msg_size, + dqe->timeout, + dqe->cont, + dqe->cont_cls); + GNUNET_free(dqe); } + +/** + * Adapter function between transport's send function and transport plugins. + * Delays message transmission if an artificial delay is configured. + * + * @param target the peer the message to send to + * @param msg the message received + * @param msg_size message size + * @param timeout timeout + * @param cont the continuation to call after sending + * @param cont_cls cls for @a cont + */ void -GST_manipulation_set_metric (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +GST_manipulation_send (const struct GNUNET_PeerIdentity *target, + const void *msg, + size_t msg_size, + struct GNUNET_TIME_Relative timeout, + GST_NeighbourSendContinuation cont, + void *cont_cls) { - struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message; - struct GNUNET_ATS_Information *ats; - struct TM_Peer *tmp; - uint32_t type; - uint32_t value; - int c; - int c2; - - if (0 == ntohs (tm->ats_count)) - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for peer `%s'\n", - GNUNET_i2s(&tm->peer)); - - if (NULL == (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &tm->peer.hashPubKey))) - { - tmp = GNUNET_malloc (sizeof (struct TM_Peer)); - tmp->peer = (tm->peer); - for (c = 0; c < TM_BOTH; c++) - { - for (c2 = 0; c2 < GNUNET_ATS_QualityPropertiesCount; c2++) - { - tmp->metrics[c][c2] = UINT32_MAX; - } - } - GNUNET_CONTAINER_multihashmap_put (man_handle.peers, &tm->peer.hashPubKey, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - } - - ats = (struct GNUNET_ATS_Information *) &tm[1]; - for (c = 0; c < ntohs (tm->ats_count); c++) - { - type = htonl (ats[c].type); - value = htonl (ats[c].value); - switch (type) { - case GNUNET_ATS_QUALITY_NET_DELAY: - set_delay (tmp, &tm->peer, ntohs (tm->direction), value); - break; - case GNUNET_ATS_QUALITY_NET_DISTANCE: - set_distance (tmp, &tm->peer, ntohs (tm->direction), value); - break; - default: - break; - } - } - - GNUNET_SERVER_receive_done (client, GNUNET_OK); + struct TM_Peer *tmp; + struct DelayQueueEntry *dqe; + struct GNUNET_TIME_Relative delay; + + if (NULL != (tmp = + GNUNET_CONTAINER_multipeermap_get (peers, + target))) + delay = tmp->delay_out; + else + delay = delay_out; + if (0 == delay.rel_value_us) + { + /* Normal sending */ + GST_neighbours_send (target, + msg, + msg_size, + timeout, + cont, cont_cls); + return; + } + dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size); + dqe->id = *target; + dqe->tmp = tmp; + dqe->sent_at = GNUNET_TIME_relative_to_absolute (delay); + dqe->cont = cont; + dqe->cont_cls = cont_cls; + dqe->msg = &dqe[1]; + dqe->msg_size = msg_size; + dqe->timeout = timeout; + GNUNET_memcpy (dqe->msg, + msg, + msg_size); + if (NULL == tmp) + { + GNUNET_CONTAINER_DLL_insert_tail (generic_dqe_head, + generic_dqe_tail, + dqe); + if (NULL == generic_send_delay_task) + generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, + &send_delayed, + dqe); + } + else + { + GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, + tmp->send_tail, + dqe); + if (NULL == tmp->send_delay_task) + tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, + &send_delayed, + dqe); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Delaying %u byte message to peer `%s' with peer specific delay for %s\n", + (unsigned int) msg_size, + GNUNET_i2s (target), + GNUNET_STRINGS_relative_time_to_string (delay, + GNUNET_YES)); } -static void -send_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct DelayQueueEntry *dqe = cls; - struct DelayQueueEntry *next; - struct TM_Peer *tmp = dqe->tmp; - struct GNUNET_TIME_Relative delay; - tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe); - GST_neighbours_send (&tmp->peer, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls); - - next = tmp->send_head; - if (NULL != next) - { - /* More delayed messages */ - delay = GNUNET_TIME_absolute_get_remaining (next->sent_at); - tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe); - } - - GNUNET_free (dqe); -} +/** + * Function that will be called to manipulate ATS information according to + * current manipulation settings + * + * @param address binary address + * @param session the session + * @param prop[IN|OUT] metrics to modify + */ void -GST_manipulation_send (const struct GNUNET_PeerIdentity *target, const void *msg, - size_t msg_size, struct GNUNET_TIME_Relative timeout, - GST_NeighbourSendContinuation cont, void *cont_cls) +GST_manipulation_manipulate_metrics (const struct GNUNET_HELLO_Address *address, + struct GNUNET_ATS_Session *session, + struct GNUNET_ATS_Properties *prop) { - struct TM_Peer *tmp; - struct DelayQueueEntry *dqe; - struct GNUNET_TIME_Relative delay; - - if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &target->hashPubKey))) - { - /* Manipulate here */ - /* Delay */ - if (UINT32_MAX != tmp->metrics[TM_SEND][DELAY]) - { - /* We have a delay */ - delay.rel_value = tmp->metrics[TM_SEND][DELAY]; - dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size); - dqe->tmp = tmp; - dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay); - dqe->cont = cont; - dqe->cont_cls = cont_cls; - dqe->msg = &dqe[1]; - dqe->msg_size = msg_size; - dqe->timeout = timeout; - memcpy (dqe->msg, msg, msg_size); - GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe); - if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task) - tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe); - return; - } - } - else if (man_handle.delay_out.rel_value != 0) - { - /* We have a delay */ - delay = man_handle.delay_out; - dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size); - dqe->tmp = tmp; - dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay); - dqe->cont = cont; - dqe->cont_cls = cont_cls; - dqe->msg = &dqe[1]; - dqe->msg_size = msg_size; - dqe->timeout = timeout; - memcpy (dqe->msg, msg, msg_size); - GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe); - if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task) - tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe); - return; - } - - /* Normal sending */ - GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls); + const struct GNUNET_PeerIdentity *peer = &address->peer; + struct TM_Peer *tmp; + + tmp = GNUNET_CONTAINER_multipeermap_get (peers, + peer); + if (NULL != tmp) + *prop = tmp->properties; } + +/** + * Adapter function between transport plugins and transport receive function + * manipulation delays for next send. + * + * @param cls the closure for transport + * @param address the address and the peer the message was received from + * @param message the message received + * @param session the session the message was received on + * @return manipulated delay for next receive + */ struct GNUNET_TIME_Relative -GST_manipulation_recv (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *ats, - uint32_t ats_count, struct Session *session, - const char *sender_address, - uint16_t sender_address_len) +GST_manipulation_recv (void *cls, + const struct GNUNET_HELLO_Address *address, + struct GNUNET_ATS_Session *session, + const struct GNUNET_MessageHeader *message) { - struct TM_Peer *tmp; - int d; - struct GNUNET_ATS_Information ats_new[ats_count]; - struct GNUNET_TIME_Relative q_delay; - struct GNUNET_TIME_Relative m_delay; - - for (d = 0; d < ats_count; d++) - - if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey))) - { - /* Manipulate distance */ - for (d = 0; d < ats_count; d++) - { - ats_new[d] = ats[d]; - /* Set distance */ - if ((ntohl(ats[d].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) && - (UINT32_MAX != tmp->metrics[TM_RECEIVE][DISTANCE])) - ats_new[d].value = htonl(tmp->metrics[TM_RECEIVE][DISTANCE]); - } - /* Manipulate receive delay */ - if (UINT32_MAX != tmp->metrics[TM_RECEIVE][DELAY]) - { - m_delay.rel_value = tmp->metrics[TM_RECEIVE][DELAY]; - q_delay = GST_receive_callback (cls, peer, message, &ats_new[0], ats_count, - session, sender_address, sender_address_len); - - if (q_delay.rel_value >= m_delay.rel_value) - { - return q_delay; - } - else - { - return m_delay; - } - } - else - return GST_receive_callback (cls, peer, message, &ats_new[0], ats_count, - session, sender_address, sender_address_len); - } - - return GST_receive_callback (cls, peer, message, ats, ats_count, - session, sender_address, sender_address_len); + struct TM_Peer *tmp; + struct GNUNET_TIME_Relative quota_delay; + struct GNUNET_TIME_Relative m_delay; + + if (NULL != + (tmp = GNUNET_CONTAINER_multipeermap_get (peers, + &address->peer))) + m_delay = tmp->delay_in; + else + m_delay = delay_in; + + quota_delay = GST_receive_callback (cls, + address, + session, + message); + m_delay = GNUNET_TIME_relative_max (m_delay, + quota_delay); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Delaying next receive for peer `%s' for %s\n", + GNUNET_i2s (&address->peer), + GNUNET_STRINGS_relative_time_to_string (m_delay, + GNUNET_YES)); + return m_delay; } + +/** + * Initialize traffic manipulation + */ void -GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg) +GST_manipulation_init () { + struct GNUNET_TIME_Relative delay; + + if ( (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_time (GST_cfg, + "transport", + "MANIPULATE_DELAY_IN", + &delay)) && + (delay.rel_value_us > 0) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Delaying inbound traffic for %s\n", + GNUNET_STRINGS_relative_time_to_string (delay, + GNUNET_YES)); + delay_in = delay; + } + if ( (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_time (GST_cfg, + "transport", + "MANIPULATE_DELAY_OUT", + &delay)) && + (delay.rel_value_us > 0) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Delaying outbound traffic for %s\n", + GNUNET_STRINGS_relative_time_to_string (delay, + GNUNET_YES)); + delay_out = delay; + } + peers = GNUNET_CONTAINER_multipeermap_create (4, + GNUNET_NO); +} + - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg, - "transport", "MANIPULATE_DELAY_IN", &man_handle.delay_in)) - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying inbound traffic for %llu ms\n", - (unsigned long long) man_handle.delay_in.rel_value); - else - man_handle.delay_in.rel_value = 0; - - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg, - "transport", "MANIPULATE_DELAY_OUT", &man_handle.delay_out)) - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying outbound traffic for %llu ms\n", - (unsigned long long) man_handle.delay_out.rel_value); - else - man_handle.delay_out.rel_value = 0; - - man_handle.peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); +/** + * Notify manipulation about disconnect so it can discard queued messages + * + * @param peer the disconnecting peer + */ +void +GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer) +{ + struct TM_Peer *tmp; + struct DelayQueueEntry *dqe; + struct DelayQueueEntry *next; + + tmp = GNUNET_CONTAINER_multipeermap_get (peers, + peer); + if (NULL != tmp) + { + while (NULL != (dqe = tmp->send_head)) + { + GNUNET_CONTAINER_DLL_remove (tmp->send_head, + tmp->send_tail, + dqe); + if (NULL != dqe->cont) + dqe->cont (dqe->cont_cls, + GNUNET_SYSERR, + dqe->msg_size, + 0); + GNUNET_free(dqe); + } + } + next = generic_dqe_head; + while (NULL != (dqe = next)) + { + next = dqe->next; + if (0 == memcmp (peer, + &dqe->id, + sizeof (dqe->id))) + { + GNUNET_CONTAINER_DLL_remove (generic_dqe_head, + generic_dqe_tail, + dqe); + if (NULL != dqe->cont) + dqe->cont (dqe->cont_cls, + GNUNET_SYSERR, + dqe->msg_size, + 0); + GNUNET_free(dqe); + } + } + if (NULL != generic_send_delay_task) + { + GNUNET_SCHEDULER_cancel (generic_send_delay_task); + generic_send_delay_task = NULL; + if (NULL != generic_dqe_head) + generic_send_delay_task + = GNUNET_SCHEDULER_add_at (generic_dqe_head->sent_at, + &send_delayed, + generic_dqe_head); + } } -int free_tmps (void *cls, - const struct GNUNET_HashCode * key, - void *value) + +/** + * Free manipulation information about a peer. + * + * @param cls NULL + * @param key peer the info is about + * @param value a `struct TM_Peer` to free + * @return #GNUNET_OK (continue to iterate) + */ +static int +free_tmps (void *cls, + const struct GNUNET_PeerIdentity *key, + void *value) { - struct DelayQueueEntry *dqe; - struct DelayQueueEntry *next; - if (NULL != value) - { - struct TM_Peer *tmp = (struct TM_Peer *) value; - GNUNET_CONTAINER_multihashmap_remove (man_handle.peers, key, value); - next = tmp->send_head; - while (NULL != (dqe = next)) - { - next = dqe->next; - GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe); - GNUNET_free (dqe); - } - if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task) - { - GNUNET_SCHEDULER_cancel (tmp->send_delay_task); - tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_free (tmp); - } - return GNUNET_OK; + struct TM_Peer *tmp = value; + struct DelayQueueEntry *dqe; + + GNUNET_break (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (peers, + key, + value)); + while (NULL != (dqe = tmp->send_head)) + { + GNUNET_CONTAINER_DLL_remove (tmp->send_head, + tmp->send_tail, + dqe); + if (NULL != dqe->cont) + dqe->cont (dqe->cont_cls, + GNUNET_SYSERR, + dqe->msg_size, + 0); + GNUNET_free (dqe); + } + if (NULL != tmp->send_delay_task) + { + GNUNET_SCHEDULER_cancel (tmp->send_delay_task); + tmp->send_delay_task = NULL; + } + GNUNET_free (tmp); + return GNUNET_OK; } + +/** + * Stop traffic manipulation + */ void GST_manipulation_stop () { - GNUNET_CONTAINER_multihashmap_iterate (man_handle.peers, &free_tmps,NULL); - - GNUNET_CONTAINER_multihashmap_destroy (man_handle.peers); - man_handle.peers = NULL; + struct DelayQueueEntry *cur; + + GNUNET_CONTAINER_multipeermap_iterate (peers, + &free_tmps, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (peers); + peers = NULL; + while (NULL != (cur = generic_dqe_head)) + { + GNUNET_CONTAINER_DLL_remove (generic_dqe_head, + generic_dqe_tail, + cur); + if (NULL != cur->cont) + cur->cont (cur->cont_cls, + GNUNET_SYSERR, + cur->msg_size, + 0); + GNUNET_free (cur); + } + if (NULL != generic_send_delay_task) + { + GNUNET_SCHEDULER_cancel (generic_send_delay_task); + generic_send_delay_task = NULL; + } } - /* end of file gnunet-service-transport_manipulation.c */