REST/NAMESTORE: rework API
[oweals/gnunet.git] / src / transport / gnunet-service-transport_manipulation.c
index f52634edc45129f2bce9a37e5a8a43139c21e76e..0b042dd6a7a4a768a5d1258b8207191d3cd47f79 100644 (file)
@@ -1,21 +1,21 @@
 /*
  This file is part of GNUnet.
- Copyright (C) 2010-2013 Christian Grothoff (and other contributing authors)
+ 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.
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 <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
  */
 
 /**
@@ -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"
 #include "gnunet-service-transport.h"
 #include "transport.h"
 
-enum TRAFFIC_METRIC_DIRECTION
-{
-  TM_SEND = 0, TM_RECEIVE = 1, TM_BOTH = 2
-};
-
 
 /**
  * Struct containing information about manipulations to a specific peer
  */
-struct TM_Peer;
-
-/**
- * Manipulation entry
- */
-struct PropManipulationEntry
+struct TM_Peer
 {
   /**
-   * Next in DLL
-   */
-  struct PropManipulationEntry *next;
-
-  /**
-   * Previous in DLL
-   */
-  struct PropManipulationEntry *prev;
-
-  /**
-   * ATS type in HBO
+   * Peer ID
    */
-  uint32_t type;
+  struct GNUNET_PeerIdentity peer;
 
   /**
-   * Value in HBO
+   * How long to delay incoming messages for this peer.
    */
-  uint32_t metrics[TM_BOTH];
+  struct GNUNET_TIME_Relative delay_in;
 
-};
-
-/**
- * Struct containing information about manipulations to a specific peer
- */
-struct TM_Peer
-{
   /**
-   * Peer ID
+   * How long to delay outgoing messages for this peer.
    */
-  struct GNUNET_PeerIdentity peer;
-
-  struct PropManipulationEntry *head;
-  struct PropManipulationEntry *tail;
+  struct GNUNET_TIME_Relative delay_out;
 
   /**
-   * Peer specific manipulation metrics
+   * Manipulated properties to use for this peer.
    */
-  uint32_t metrics[TM_BOTH][GNUNET_ATS_QualityPropertiesCount];
+  struct GNUNET_ATS_Properties properties;
 
   /**
    * Task to schedule delayed sendding
    */
-  struct GNUNET_SCHEDULER_Task * send_delay_task;
+  struct GNUNET_SCHEDULER_Task *send_delay_task;
 
   /**
    * Send queue DLL head
@@ -107,19 +75,6 @@ struct TM_Peer
 };
 
 
-struct GST_ManipulationHandle
-{
-  /**
-   * Hashmap contain all peers currently manipulated
-   */
-  struct GNUNET_CONTAINER_MultiPeerMap *peers;
-
-  /**
-   * Peer containing information for general manipulation
-   */
-  struct TM_Peer general;
-};
-
 /**
  * Entry in the delay queue for an outbound delayed message
  */
@@ -136,9 +91,10 @@ struct DelayQueueEntry
   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
+   * 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;
 
@@ -178,229 +134,131 @@ struct DelayQueueEntry
   void *cont_cls;
 };
 
-struct GST_ManipulationHandle man_handle;
-
 /**
- * DLL head for delayed messages based on general delay
+ * Hashmap contain all peers currently manipulated
  */
-struct DelayQueueEntry *generic_dqe_head;
+static struct GNUNET_CONTAINER_MultiPeerMap *peers;
 
 /**
- * DLL tail for delayed messages based on general delay
+ * Inbound delay to apply to all peers.
  */
-struct DelayQueueEntry *generic_dqe_tail;
+static struct GNUNET_TIME_Relative delay_in;
 
 /**
- * Task to schedule delayed sending based on general delay
+ * Outbound delay to apply to all peers.
  */
-struct GNUNET_SCHEDULER_Task * generic_send_delay_task;
-
-
-static void
-set_metric(struct TM_Peer *dest, int direction, uint32_t type, uint32_t value)
-{
-  struct PropManipulationEntry *cur;
-  for (cur = dest->head; NULL != cur; cur = cur->next)
-    {
-      if (cur->type == type)
-        break;
-    }
-  if (NULL == cur)
-    {
-      cur = GNUNET_new (struct PropManipulationEntry);
-      GNUNET_CONTAINER_DLL_insert(dest->head, dest->tail, cur);
-      cur->type = type;
-      cur->metrics[TM_SEND] = UINT32_MAX;
-      cur->metrics[TM_RECEIVE] = UINT32_MAX;
-    }
-
-  switch (direction)
-    {
-  case TM_BOTH:
-    cur->metrics[TM_SEND] = value;
-    cur->metrics[TM_RECEIVE] = value;
-    break;
-  case TM_SEND:
-    cur->metrics[TM_SEND] = value;
-    break;
-  case TM_RECEIVE:
-    cur->metrics[TM_RECEIVE] = value;
-    break;
-  default:
-    break;
-    }
-}
-
-
-static uint32_t
-find_metric(struct TM_Peer *dest, uint32_t type, int direction)
-{
-  struct PropManipulationEntry *cur;
-
-  for (cur = dest->head; NULL != cur; cur = cur->next)
-    {
-      if (cur->type == type)
-        return cur->metrics[direction];
-
-    }
-  return UINT32_MAX;
-}
+static struct GNUNET_TIME_Relative delay_out;
 
+/**
+ * DLL head for delayed messages based on general delay
+ */
+static struct DelayQueueEntry *generic_dqe_head;
 
 /**
- * Clean up metrics for a peer
+ * DLL tail for delayed messages based on general delay
  */
-static void
-free_metric(struct TM_Peer *dest)
-{
-  struct PropManipulationEntry *cur;
-  struct PropManipulationEntry *next;
+static struct DelayQueueEntry *generic_dqe_tail;
 
-  for (cur = dest->head; NULL != cur; cur = next)
-    {
-      next = cur->next;
-      GNUNET_CONTAINER_DLL_remove(dest->head, dest->tail, cur);
-      GNUNET_free(cur);
-    }
-}
+/**
+ * Task to schedule delayed sending based on general delay
+ */
+static struct GNUNET_SCHEDULER_Task *generic_send_delay_task;
 
 
 /**
  * Set traffic metric to manipulate
  *
- * @param cls closure
- * @param client client sending message
  * @param message containing information
  */
 void
-GST_manipulation_set_metric(void *cls, struct GNUNET_SERVER_Client *client,
-    const struct GNUNET_MessageHeader *message)
+GST_manipulation_set_metric (const struct TrafficMetricMessage *tm)
 {
-  struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message;
-  struct GNUNET_PeerIdentity dummy;
-  struct GNUNET_ATS_Information *ats;
+  static struct GNUNET_PeerIdentity zero;
   struct TM_Peer *tmp;
-  uint32_t type;
-  uint32_t value;
-  uint16_t direction;
-  int c;
-  int c2;
-
-  if (0 == ntohs(tm->ats_count))
-    GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
-
-  direction = TM_BOTH;
-  switch (ntohs(tm->direction))
-    {
-  case 1:
-    direction = TM_SEND;
-    break;
-  case 2:
-    direction = TM_RECEIVE;
-    break;
-  case 3:
-    direction = TM_BOTH;
-    break;
-  default:
-    break;
-    }
-
-  memset(&dummy, '\0', sizeof(struct GNUNET_PeerIdentity));
-  if (0 == memcmp(&tm->peer, &dummy, sizeof(struct GNUNET_PeerIdentity)))
-    {
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          "Received traffic metrics for all peers \n");
-
-      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);
-          set_metric(&man_handle.general, direction, type, value);
-        }
-      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(man_handle.peers, &tm->peer)))
-    {
-      tmp = GNUNET_new (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_multipeermap_put(man_handle.peers, &tm->peer, 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);
-      set_metric(tmp, direction, type, value);
-    }
 
-  GNUNET_SERVER_receive_done(client, GNUNET_OK);
+  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
-send_delayed(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+send_delayed (void *cls)
 {
   struct DelayQueueEntry *dqe = cls;
   struct DelayQueueEntry *next;
   struct TM_Peer *tmp = dqe->tmp;
-  struct GNUNET_TIME_Relative delay;
 
+  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)
     {
-      GNUNET_break (GNUNET_YES ==
-                    GST_neighbours_test_connected (&dqe->id));
-      tmp->send_delay_task = NULL;
-      GNUNET_CONTAINER_DLL_remove (tmp->send_head,
-                                   tmp->send_tail,
-                                   dqe);
-      GST_neighbours_send (&dqe->id,
-                           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, 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)
     {
-      /* Remove from generic queue */
-      GNUNET_break(GNUNET_YES == GST_neighbours_test_connected (&dqe->id));
-      generic_send_delay_task = NULL;
-      GNUNET_CONTAINER_DLL_remove(generic_dqe_head, generic_dqe_tail, dqe);
-      GST_neighbours_send(&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout,
-          dqe->cont, dqe->cont_cls);
-      next = generic_dqe_head;
-      if (NULL != next)
-        {
-          /* More delayed messages */
-          delay = GNUNET_TIME_absolute_get_remaining(next->sent_at);
-          generic_send_delay_task = GNUNET_SCHEDULER_add_delayed(delay,
-              &send_delayed, 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);
 }
 
@@ -427,41 +285,14 @@ GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
   struct TM_Peer *tmp;
   struct DelayQueueEntry *dqe;
   struct GNUNET_TIME_Relative delay;
-  int do_delay;
 
-  do_delay = GNUNET_NO;
   if (NULL != (tmp =
-               GNUNET_CONTAINER_multipeermap_get (man_handle.peers,
+               GNUNET_CONTAINER_multipeermap_get (peers,
                                                   target)))
-  {
-    GNUNET_break (GNUNET_YES ==
-                  GST_neighbours_test_connected(target));
-    /* check for peer-specific delay */
-    if (UINT32_MAX !=
-        find_metric (tmp,
-                     GNUNET_ATS_QUALITY_NET_DELAY,
-                     TM_SEND))
-    {
-      /* We have a delay */
-      delay.rel_value_us = find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY,
-                                       TM_SEND);
-      do_delay = GNUNET_YES;
-    }
-  }
-  else if (UINT32_MAX !=
-           find_metric(&man_handle.general,
-                       GNUNET_ATS_QUALITY_NET_DELAY,
-                       TM_SEND))
-  {
-    GNUNET_break (GNUNET_YES ==
-                  GST_neighbours_test_connected (target));
-    /* We have a delay */
-    delay.rel_value_us = find_metric (&man_handle.general,
-                                      GNUNET_ATS_QUALITY_NET_DELAY,
-                                      TM_SEND);
-    do_delay = GNUNET_YES;
-  }
-  if (GNUNET_NO == do_delay)
+    delay = tmp->delay_out;
+  else
+    delay = delay_out;
+  if (0 == delay.rel_value_us)
   {
     /* Normal sending */
     GST_neighbours_send (target,
@@ -480,7 +311,7 @@ GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
   dqe->msg = &dqe[1];
   dqe->msg_size = msg_size;
   dqe->timeout = timeout;
-  memcpy (dqe->msg,
+  GNUNET_memcpy (dqe->msg,
           msg,
           msg_size);
   if (NULL == tmp)
@@ -505,7 +336,7 @@ GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Delaying %u byte message to peer `%s' with peer specific delay for %s\n",
-              msg_size,
+              (unsigned int) msg_size,
               GNUNET_i2s (target),
               GNUNET_STRINGS_relative_time_to_string (delay,
                                                       GNUNET_YES));
@@ -516,46 +347,22 @@ GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
  * Function that will be called to manipulate ATS information according to
  * current manipulation settings
  *
- * @param peer the peer
  * @param address binary address
  * @param session the session
- * @param ats the ats information
- * @param ats_count the number of ats information
+ * @param prop[IN|OUT] metrics to modify
  */
-struct GNUNET_ATS_Information *
+void
 GST_manipulation_manipulate_metrics (const struct GNUNET_HELLO_Address *address,
-                                     struct Session *session,
-                                     const struct GNUNET_ATS_Information *ats,
-                                     uint32_t ats_count)
+                                     struct GNUNET_ATS_Session *session,
+                                     struct GNUNET_ATS_Properties *prop)
 {
   const struct GNUNET_PeerIdentity *peer = &address->peer;
-  struct GNUNET_ATS_Information *ats_new;
   struct TM_Peer *tmp;
-  uint32_t m_tmp;
-  uint32_t g_tmp;
-  uint32_t d;
-
-  if (0 == ats_count)
-    return NULL;
-  ats_new = GNUNET_malloc (sizeof (struct GNUNET_ATS_Information) * ats_count);
-  tmp = GNUNET_CONTAINER_multipeermap_get (man_handle.peers, peer);
-  for (d = 0; d < ats_count; d++)
-  {
-    ats_new[d] = ats[d];
-    m_tmp = UINT32_MAX;
-    if (NULL != tmp)
-      m_tmp = find_metric (tmp, ntohl(ats[d].type),
-                           TM_RECEIVE);
-    g_tmp = find_metric (&man_handle.general,
-                         ntohl(ats[d].type),
-                         TM_RECEIVE);
-
-    if (UINT32_MAX != g_tmp)
-      ats_new[d].value = htonl(g_tmp);
-    if (UINT32_MAX != m_tmp)
-      ats_new[d].value = htonl(m_tmp);
-  }
-  return ats_new;
+
+  tmp = GNUNET_CONTAINER_multipeermap_get (peers,
+                                           peer);
+  if (NULL != tmp)
+    *prop = tmp->properties;
 }
 
 
@@ -572,36 +379,26 @@ GST_manipulation_manipulate_metrics (const struct GNUNET_HELLO_Address *address,
 struct GNUNET_TIME_Relative
 GST_manipulation_recv (void *cls,
                        const struct GNUNET_HELLO_Address *address,
-                       struct Session *session,
+                       struct GNUNET_ATS_Session *session,
                        const struct GNUNET_MessageHeader *message)
 {
   struct TM_Peer *tmp;
-  uint32_t p_recv_delay;
-  uint32_t g_recv_delay;
   struct GNUNET_TIME_Relative quota_delay;
   struct GNUNET_TIME_Relative m_delay;
 
-  g_recv_delay = find_metric(&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY,
-      TM_RECEIVE);
-  if ((g_recv_delay >= GNUNET_TIME_UNIT_ZERO.rel_value_us)
-      && (UINT32_MAX != g_recv_delay))
-    m_delay.rel_value_us = g_recv_delay; /* Global delay */
+  if (NULL !=
+      (tmp = GNUNET_CONTAINER_multipeermap_get (peers,
+                                                &address->peer)))
+    m_delay = tmp->delay_in;
   else
-    m_delay = GNUNET_TIME_UNIT_ZERO;
-
-  if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, &address->peer)))
-    {
-      /* Manipulate receive delay */
-      p_recv_delay = find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE);
-      if (UINT32_MAX != p_recv_delay)
-        m_delay.rel_value_us = p_recv_delay; /* Peer specific delay */
-    }
-
-  quota_delay = GST_receive_callback(cls, address, session, message);
-
-  if (quota_delay.rel_value_us > m_delay.rel_value_us)
-    m_delay = quota_delay;
-
+    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),
@@ -613,63 +410,112 @@ GST_manipulation_recv (void *cls,
 
 /**
  * Initialize traffic manipulation
- *
- * @param GST_cfg configuration handle
  */
 void
-GST_manipulation_init(const struct GNUNET_CONFIGURATION_Handle *GST_cfg)
+GST_manipulation_init ()
 {
-  unsigned long long tmp;
   struct GNUNET_TIME_Relative delay;
 
   if ( (GNUNET_OK ==
-        GNUNET_CONFIGURATION_get_value_number(GST_cfg,
-                                              "transport",
-                                              "MANIPULATE_DISTANCE_IN",
-                                              &tmp)) &&
-       (tmp > 0) )
+        GNUNET_CONFIGURATION_get_value_time (GST_cfg,
+                                             "transport",
+                                             "MANIPULATE_DELAY_IN",
+                                             &delay)) &&
+       (delay.rel_value_us > 0) )
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-               "Setting inbound distance_in to %llu\n",
-               (unsigned long long) tmp);
-    set_metric (&man_handle.general,
-                TM_RECEIVE,
-                GNUNET_ATS_QUALITY_NET_DISTANCE,
-                tmp);
+    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_number(GST_cfg, "transport",
-          "MANIPULATE_DISTANCE_OUT", &tmp)) && (tmp > 0))
-    {
-      GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-          "Setting outbound distance_in to %llu\n", (unsigned long long) tmp);
-      set_metric(&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DISTANCE,
-          tmp);
-    }
 
-  if ((GNUNET_OK
-      == GNUNET_CONFIGURATION_get_value_time(GST_cfg, "transport",
-          "MANIPULATE_DELAY_IN", &delay)) && (delay.rel_value_us > 0))
+/**
+ * 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_log(GNUNET_ERROR_TYPE_INFO,
-          "Delaying inbound traffic for %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
-      set_metric(&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DELAY,
-          delay.rel_value_us);
+      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 ((GNUNET_OK
-      == GNUNET_CONFIGURATION_get_value_time(GST_cfg, "transport",
-          "MANIPULATE_DELAY_OUT", &delay)) && (delay.rel_value_us > 0))
+  }
+  next = generic_dqe_head;
+  while (NULL != (dqe = next))
+  {
+    next = dqe->next;
+    if (0 == memcmp (peer,
+                    &dqe->id,
+                    sizeof (dqe->id)))
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-          "Delaying outbound traffic for %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
-      set_metric(&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DELAY,
-          delay.rel_value_us);
+      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);
     }
-  man_handle.peers = GNUNET_CONTAINER_multipeermap_create(10, GNUNET_NO);
+  }
+  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);
+  }
 }
 
 
+/**
+ * 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,
@@ -678,13 +524,10 @@ free_tmps (void *cls,
   struct TM_Peer *tmp = value;
   struct DelayQueueEntry *dqe;
 
-  if (NULL == tmp)
-    return GNUNET_OK;
   GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multipeermap_remove (man_handle.peers,
+                GNUNET_CONTAINER_multipeermap_remove (peers,
                                                       key,
                                                       value));
-  free_metric (tmp);
   while (NULL != (dqe = tmp->send_head))
   {
     GNUNET_CONTAINER_DLL_remove (tmp->send_head,
@@ -699,89 +542,27 @@ free_tmps (void *cls,
   }
   if (NULL != tmp->send_delay_task)
   {
-    GNUNET_SCHEDULER_cancel(tmp->send_delay_task);
+    GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
     tmp->send_delay_task = NULL;
   }
-  GNUNET_free(tmp);
+  GNUNET_free (tmp);
   return GNUNET_OK;
 }
 
 
-/**
- * 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;
-
-  if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, peer)))
-  {
-    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);
-    }
-  }
-  else if (UINT32_MAX != find_metric (&man_handle.general,
-                                      GNUNET_ATS_QUALITY_NET_DELAY,
-                                      TM_SEND))
-  {
-    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_delayed (GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at),
-                                          &send_delayed,
-                                          generic_dqe_head);
-    }
-  }
-}
-
-
 /**
  * Stop traffic manipulation
  */
 void
-GST_manipulation_stop()
+GST_manipulation_stop ()
 {
   struct DelayQueueEntry *cur;
 
-  GNUNET_CONTAINER_multipeermap_iterate (man_handle.peers,
+  GNUNET_CONTAINER_multipeermap_iterate (peers,
                                          &free_tmps,
                                          NULL);
-  GNUNET_CONTAINER_multipeermap_destroy (man_handle.peers);
-
+  GNUNET_CONTAINER_multipeermap_destroy (peers);
+  peers = NULL;
   while (NULL != (cur = generic_dqe_head))
   {
     GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
@@ -799,8 +580,6 @@ GST_manipulation_stop()
     GNUNET_SCHEDULER_cancel (generic_send_delay_task);
     generic_send_delay_task = NULL;
   }
-  free_metric (&man_handle.general);
-  man_handle.peers = NULL;
 }
 
 /* end of file gnunet-service-transport_manipulation.c */