-bring set/gns into the fold of non-experimental subsystems
[oweals/gnunet.git] / src / transport / gnunet-service-transport_manipulation.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010-2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file transport/gnunet-service-transport_manipulation.c
23  * @brief transport component manipulation traffic for simulation
24  * @author Christian Grothoff
25  * @author Matthias Wachs
26  */
27 #include "platform.h"
28 #include "gnunet-service-transport_blacklist.h"
29 #include "gnunet-service-transport_clients.h"
30 #include "gnunet-service-transport_hello.h"
31 #include "gnunet-service-transport_neighbours.h"
32 #include "gnunet-service-transport_plugins.h"
33 #include "gnunet-service-transport_validation.h"
34 #include "gnunet-service-transport.h"
35 #include "transport.h"
36
37 enum TRAFFIC_METRIC_DIRECTION
38 {
39         TM_SEND = 0,
40         TM_RECEIVE = 1,
41         TM_BOTH = 2
42 };
43
44 struct GST_ManipulationHandle man_handle;
45
46
47
48 /**
49  * Struct containing information about manipulations to a specific peer
50  */
51 struct TM_Peer;
52
53 /**
54  * Manipulation entry
55  */
56 struct PropManipulationEntry
57 {
58         /**
59          * Next in DLL
60          */
61         struct PropManipulationEntry *next;
62
63         /**
64          * Previous in DLL
65          */
66         struct PropManipulationEntry *prev;
67
68         /**
69          * ATS type in HBO
70          */
71         uint32_t type;
72
73         /**
74          * Value in HBO
75          */
76         uint32_t metrics[TM_BOTH];
77
78 };
79
80 /**
81  * Struct containing information about manipulations to a specific peer
82  */
83 struct TM_Peer
84 {
85         /**
86          * Peer ID
87          */
88         struct GNUNET_PeerIdentity peer;
89
90         struct PropManipulationEntry *head;
91         struct PropManipulationEntry *tail;
92
93         /**
94          * Peer specific manipulation metrics
95          */
96         uint32_t metrics [TM_BOTH][GNUNET_ATS_QualityPropertiesCount];
97
98         /**
99          * Task to schedule delayed sendding
100          */
101         GNUNET_SCHEDULER_TaskIdentifier send_delay_task;
102
103         /**
104          * Send queue DLL head
105          */
106         struct DelayQueueEntry *send_head;
107
108         /**
109          * Send queue DLL tail
110          */
111         struct DelayQueueEntry *send_tail;
112 };
113
114
115 struct GST_ManipulationHandle
116 {
117         /**
118          * Hashmap contain all peers currently manipulated
119          */
120         struct GNUNET_CONTAINER_MultiHashMap *peers;
121
122         /**
123          * Peer containing information for general manipulation
124          */
125         struct TM_Peer general;
126 };
127
128
129
130 /**
131  * Entry in the delay queue for an outbound delayed message
132  */
133 struct DelayQueueEntry
134 {
135         /**
136          * Next in DLL
137          */
138         struct DelayQueueEntry *prev;
139
140         /**
141          * Previous in DLL
142          */
143         struct DelayQueueEntry *next;
144
145         /**
146          * Peer this entry is belonging to
147          * if (NULL == tmp): enqueued in generic DLL and scheduled by generic_send_delay_task
148          * else: enqueued in tmp->send_head and tmp->send_tail and scheduled by tmp->send_delay_task
149          */
150         struct TM_Peer *tmp;
151
152         /**
153          * Peer ID
154          */
155         struct GNUNET_PeerIdentity id;
156
157         /**
158          * Absolute time when to send
159          */
160         struct GNUNET_TIME_Absolute sent_at;
161
162         /**
163          * The message
164          */
165         void *msg;
166
167         /**
168          * The message size
169          */
170         size_t msg_size;
171
172         /**
173          * Message timeout
174          */
175         struct GNUNET_TIME_Relative timeout;
176
177         /**
178          * Transports send continuation
179          */
180         GST_NeighbourSendContinuation cont;
181
182         /**
183          * Transports send continuation cls
184          */
185         void *cont_cls;
186 };
187
188 /**
189  * DLL head for delayed messages based on general delay
190  */
191 struct DelayQueueEntry *generic_dqe_head;
192
193 /**
194  * DLL tail for delayed messages based on general delay
195  */
196 struct DelayQueueEntry *generic_dqe_tail;
197
198 /**
199  * Task to schedule delayed sending based on general delay
200  */
201 GNUNET_SCHEDULER_TaskIdentifier generic_send_delay_task;
202
203 static void
204 set_metric (struct TM_Peer *dest, int direction, uint32_t type, uint32_t value)
205 {
206         struct PropManipulationEntry *cur;
207         for (cur = dest->head; NULL != cur; cur = cur->next)
208         {
209                 if (cur->type == type)
210                         break;
211         }
212         if (NULL == cur)
213         {
214                 cur = GNUNET_malloc (sizeof (struct PropManipulationEntry));
215                 GNUNET_CONTAINER_DLL_insert (dest->head, dest->tail, cur);
216                 cur->type = type;
217                 cur->metrics[TM_SEND] = UINT32_MAX;
218                 cur->metrics[TM_RECEIVE] = UINT32_MAX;
219         }
220
221
222         switch (direction) {
223                 case TM_BOTH:
224                         cur->metrics[TM_SEND] = value;
225                         cur->metrics[TM_RECEIVE] = value;
226                         break;
227                 case TM_SEND:
228                         cur->metrics[TM_SEND] = value;
229                         break;
230                 case TM_RECEIVE:
231                         cur->metrics[TM_RECEIVE] = value;
232                         break;
233                 default:
234                         break;
235         }
236
237 }
238
239 static uint32_t
240 find_metric (struct TM_Peer *dest, uint32_t type, int direction)
241 {
242         struct PropManipulationEntry *cur;
243
244         for (cur = dest->head; NULL != cur; cur = cur->next)
245         {
246                 if (cur->type == type)
247                         return cur->metrics[direction];
248
249         }
250         return UINT32_MAX;
251 }
252
253 /**
254  * Clean up metrics for a peer
255  */
256
257 static void
258 free_metric (struct TM_Peer *dest)
259 {
260         struct PropManipulationEntry *cur;
261         struct PropManipulationEntry *next;
262
263         for (cur = dest->head; NULL != cur; cur = next)
264         {
265                 next = cur->next;
266                 GNUNET_CONTAINER_DLL_remove (dest->head, dest->tail, cur);
267                 GNUNET_free (cur);
268         }
269 }
270
271
272 /**
273  * Set traffic metric to manipulate
274  *
275  * @param cls closure
276  * @param client client sending message
277  * @param message containing information
278  */
279 void
280 GST_manipulation_set_metric (void *cls, struct GNUNET_SERVER_Client *client,
281     const struct GNUNET_MessageHeader *message)
282 {
283         struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message;
284         struct GNUNET_PeerIdentity dummy;
285         struct GNUNET_ATS_Information *ats;
286         struct TM_Peer *tmp;
287         uint32_t type;
288         uint32_t value;
289         uint16_t direction;
290         int c;
291         int c2;
292
293         if (0 == ntohs (tm->ats_count))
294           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
295
296         direction = TM_BOTH;
297         switch (ntohs(tm->direction)) {
298                 case 1:
299                         direction = TM_SEND;
300                         break;
301                 case 2:
302                         direction = TM_RECEIVE;
303                         break;
304                 case 3:
305                         direction = TM_BOTH;
306                         break;
307                 default:
308                         break;
309         }
310
311         memset (&dummy, '\0', sizeof (struct GNUNET_PeerIdentity));
312         if (0 == memcmp (&tm->peer, &dummy, sizeof (struct GNUNET_PeerIdentity)))
313         {
314                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for all peers \n");
315
316                         ats = (struct GNUNET_ATS_Information *) &tm[1];
317                         for (c = 0; c < ntohs (tm->ats_count); c++)
318                         {
319                                         type = htonl (ats[c].type);
320                                         value = htonl (ats[c].value);
321                                         set_metric (&man_handle.general, direction, type, value);
322                         }
323                         return;
324         }
325
326         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for peer `%s'\n",
327                         GNUNET_i2s(&tm->peer));
328
329         if (NULL == (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &tm->peer.hashPubKey)))
330         {
331                         tmp = GNUNET_malloc (sizeof (struct TM_Peer));
332                         tmp->peer = (tm->peer);
333                         for (c = 0; c < TM_BOTH; c++)
334                         {
335                                         for (c2 = 0; c2 < GNUNET_ATS_QualityPropertiesCount; c2++)
336                                         {
337                                                         tmp->metrics[c][c2] = UINT32_MAX;
338                                         }
339                         }
340                         GNUNET_CONTAINER_multihashmap_put (man_handle.peers, &tm->peer.hashPubKey, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
341         }
342
343         ats = (struct GNUNET_ATS_Information *) &tm[1];
344         for (c = 0; c < ntohs (tm->ats_count); c++)
345         {
346                         type = htonl (ats[c].type);
347                         value = htonl (ats[c].value);
348                         set_metric (tmp, direction, type, value);
349         }
350
351   GNUNET_SERVER_receive_done (client, GNUNET_OK);
352 }
353
354 static void
355 send_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
356 {
357         struct DelayQueueEntry *dqe = cls;
358         struct DelayQueueEntry *next;
359         struct TM_Peer *tmp = dqe->tmp;
360         struct GNUNET_TIME_Relative delay;
361
362         if (NULL != tmp)
363         {
364                         GNUNET_break (GNUNET_YES == GST_neighbours_test_connected (&dqe->id));
365                         tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
366                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
367                         GST_neighbours_send (&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls);
368
369                         next = tmp->send_head;
370                         if (NULL != next)
371                         {
372                                 /* More delayed messages */
373                                 delay = GNUNET_TIME_absolute_get_remaining (next->sent_at);
374                                 tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, next);
375                         }
376         }
377         else
378         {
379                         /* Remove from generic queue */
380                         GNUNET_break (GNUNET_YES == GST_neighbours_test_connected (&dqe->id));
381                         generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK;
382                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, dqe);
383                         GST_neighbours_send (&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls);
384                         next = generic_dqe_head;
385                         if (NULL != next)
386                         {
387                                 /* More delayed messages */
388                                 delay = GNUNET_TIME_absolute_get_remaining (next->sent_at);
389                                 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, next);
390                         }
391         }
392         GNUNET_free (dqe);
393 }
394
395
396 /**
397  * Adapter function between transport's send function and transport plugins
398  *
399  * @param target the peer the message to send to
400  * @param msg the message received
401  * @param msg_size message size
402  * @param timeout timeout
403  * @param cont the continuation to call after sending
404  * @param cont_cls cls for continuation
405  */
406 void
407 GST_manipulation_send (const struct GNUNET_PeerIdentity *target, const void *msg,
408     size_t msg_size, struct GNUNET_TIME_Relative timeout,
409     GST_NeighbourSendContinuation cont, void *cont_cls)
410 {
411         struct TM_Peer *tmp;
412         struct DelayQueueEntry *dqe;
413         struct GNUNET_TIME_Relative delay;
414
415         if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &target->hashPubKey)))
416         {
417                         GNUNET_break (GNUNET_YES == GST_neighbours_test_connected(target));
418                         /* Manipulate here */
419                         /* Delay */
420                         if (UINT32_MAX != find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
421                         {
422                                         /* We have a delay */
423                                         delay.rel_value = find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND);
424                                         dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
425                                         dqe->id = *target;
426                                         dqe->tmp = tmp;
427                                         dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
428                                         dqe->cont = cont;
429                                         dqe->cont_cls = cont_cls;
430                                         dqe->msg = &dqe[1];
431                                         dqe->msg_size = msg_size;
432                                         dqe->timeout = timeout;
433                                         memcpy (dqe->msg, msg, msg_size);
434                                         GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe);
435                                         if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task)
436                                                 tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
437                                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
438                                                         "Delaying %u byte message to peer `%s' with generic delay for %llu ms\n",
439                                                         msg_size, GNUNET_i2s (target), (long long unsigned int) delay.rel_value);
440                                         return;
441                         }
442         }
443         else if (UINT32_MAX != find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
444         {
445                         GNUNET_break (GNUNET_YES == GST_neighbours_test_connected(target));
446                         /* We have a delay */
447                         delay.rel_value = find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND);
448                         dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
449                         dqe->id = *target;
450                         dqe->tmp = NULL;
451                         dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
452                         dqe->cont = cont;
453                         dqe->cont_cls = cont_cls;
454                         dqe->msg = &dqe[1];
455                         dqe->msg_size = msg_size;
456                         dqe->timeout = timeout;
457                         memcpy (dqe->msg, msg, msg_size);
458                         GNUNET_CONTAINER_DLL_insert_tail (generic_dqe_head, generic_dqe_tail, dqe);
459                         if (GNUNET_SCHEDULER_NO_TASK == generic_send_delay_task)
460                         {
461                                 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
462                         }
463                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464                                         "Delaying %u byte message to peer `%s' with peer specific delay for %llu ms\n",
465                                         msg_size, GNUNET_i2s (target), (long long unsigned int) delay.rel_value);
466                         return;
467         }
468
469         /* Normal sending */
470         GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls);
471 }
472
473
474 /**
475  * Function that will be called to manipulate ATS information according to
476  * current manipulation settings
477  *
478  * @param peer the peer
479  * @param address binary address
480  * @param session the session
481  * @param ats the ats information
482  * @param ats_count the number of ats information
483  */
484 struct GNUNET_ATS_Information *
485 GST_manipulation_manipulate_metrics (const struct GNUNET_PeerIdentity *peer,
486                 const struct GNUNET_HELLO_Address *address,
487                 struct Session *session,
488                 const struct GNUNET_ATS_Information *ats,
489                 uint32_t ats_count)
490 {
491         struct GNUNET_ATS_Information *ats_new = GNUNET_malloc (sizeof (struct GNUNET_ATS_Information) *ats_count);
492         struct TM_Peer *tmp;
493         uint32_t m_tmp;
494         uint32_t g_tmp;
495         int d;
496         tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey);
497
498         for (d = 0; d < ats_count; d++)
499         {
500                 ats_new[d] = ats[d];
501                 m_tmp = UINT32_MAX;
502                 g_tmp = UINT32_MAX;
503                 if (NULL != tmp)
504                         m_tmp = find_metric (tmp, ntohl(ats[d].type), TM_RECEIVE);
505                 g_tmp = find_metric (&man_handle.general, ntohl(ats[d].type), TM_RECEIVE);
506
507                 if (UINT32_MAX != g_tmp)
508                                 ats_new[d].value = htonl(g_tmp);
509                 if (UINT32_MAX != m_tmp)
510                                 ats_new[d].value = htonl(m_tmp);
511         }
512
513         return ats_new;
514 }
515
516
517 /**
518  * Adapter function between transport plugins and transport receive function
519  * manipulation delays for next send.
520  *
521  * @param cls the closure for transport
522  * @param peer the peer the message was received from
523  * @param message the message received
524  * @param session the session the message was received on
525  * @param sender_address the sender address
526  * @param sender_address_len the length of the sender address
527  * @return manipulated delay for next receive
528  */
529 struct GNUNET_TIME_Relative
530 GST_manipulation_recv (void *cls,
531                 const struct GNUNET_PeerIdentity *peer,
532     const struct GNUNET_MessageHeader *message,
533     struct Session *session,
534     const char *sender_address,
535     uint16_t sender_address_len)
536 {
537         struct TM_Peer *tmp;
538         uint32_t p_recv_delay;
539         uint32_t g_recv_delay;
540         struct GNUNET_TIME_Relative quota_delay;
541         struct GNUNET_TIME_Relative m_delay;
542
543         g_recv_delay = find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE);
544         if ((g_recv_delay >= GNUNET_TIME_UNIT_ZERO.rel_value) && (UINT32_MAX != g_recv_delay))
545                 m_delay.rel_value = g_recv_delay; /* Global delay */
546         else
547                 m_delay = GNUNET_TIME_UNIT_ZERO;
548
549         if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey)))
550         {
551                         /* Manipulate receive delay */
552                         p_recv_delay = find_metric (tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE);
553                         if (UINT32_MAX != p_recv_delay)
554                                         m_delay.rel_value = p_recv_delay; /* Peer specific delay */
555         }
556
557         quota_delay = GST_receive_callback (cls, peer, message,
558                         session, sender_address, sender_address_len);
559
560         if (quota_delay.rel_value > m_delay.rel_value)
561                 m_delay = quota_delay;
562
563         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564                         "Delaying next receive for peer `%s' for %llu ms\n",
565                         GNUNET_i2s (peer), (long long unsigned int) m_delay.rel_value);
566         return m_delay;
567
568 }
569
570
571 /**
572  * Initialize traffic manipulation
573  *
574  * @param GST_cfg configuration handle
575  */
576 void
577 GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg)
578 {
579         unsigned long long tmp;
580
581         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
582                         "transport", "MANIPULATE_DISTANCE_IN", &tmp) && (tmp > 0))
583         {
584                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting inbound distance_in to %u\n",
585                                 (unsigned long long) tmp);
586                 set_metric (&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
587         }
588
589         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
590                         "transport", "MANIPULATE_DISTANCE_OUT", &tmp) && (tmp > 0))
591         {
592                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting outbound distance_in to %u\n",
593                                 (unsigned long long) tmp);
594                 set_metric (&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
595         }
596
597         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
598                         "transport", "MANIPULATE_DELAY_IN", &tmp) && (tmp > 0))
599         {
600                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying inbound traffic for %llu ms\n",
601                                 (unsigned long long) tmp);
602                 set_metric (&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DELAY, tmp);
603         }
604
605
606         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
607                         "transport", "MANIPULATE_DELAY_OUT", &tmp) && (tmp > 0))
608         {
609                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying outbound traffic for %llu ms\n",
610                                 (unsigned long long) tmp);
611                 set_metric (&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DELAY, tmp);
612         }
613
614         man_handle.peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
615 }
616
617
618 static int 
619 free_tmps (void *cls,
620            const struct GNUNET_HashCode * key,
621            void *value)
622 {
623         struct DelayQueueEntry *dqe;
624         struct DelayQueueEntry *next;
625         if (NULL != value)
626         {
627                         struct TM_Peer *tmp = (struct TM_Peer *) value;
628                         if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (man_handle.peers, key, value))
629                                 GNUNET_break (0);
630                         free_metric (tmp);
631                         next = tmp->send_head;
632                         while (NULL != (dqe = next))
633                         {
634                                         next = dqe->next;
635                                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
636                                         if (NULL != dqe->cont)
637                                                         dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
638                                         GNUNET_free (dqe);
639                         }
640                         if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task)
641                         {
642                                         GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
643                                         tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
644                         }
645                         GNUNET_free (tmp);
646         }
647         return GNUNET_OK;
648 }
649
650 /**
651  * Notify manipulation about disconnect so it can discard queued messages
652  *
653  * @param peer the disconnecting peer
654  */
655 void
656 GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
657 {
658         struct TM_Peer *tmp;
659         struct DelayQueueEntry *dqe;
660         struct DelayQueueEntry *next;
661
662         if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey)))
663         {
664                         next = tmp->send_head;
665                         while (NULL != (dqe = next))
666                         {
667                                         next = dqe->next;
668                                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
669                                         if (NULL != dqe->cont)
670                                                         dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
671                                         GNUNET_free (dqe);
672                         }
673         }
674         else if (UINT32_MAX != find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
675         {
676                         next = generic_dqe_head;
677                         while (NULL != (dqe = next))
678                         {
679                                         next = dqe->next;
680                                         if (0 == memcmp (peer, &dqe->id, sizeof (dqe->id)))
681                                         {
682                                                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, dqe);
683                                                         if (NULL != dqe->cont)
684                                                                 dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
685                                                         GNUNET_free (dqe);
686                                         }
687                         }
688                         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
689                         {
690                                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
691                                         generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at), &send_delayed, generic_dqe_head);
692                         }
693         }
694 }
695
696
697 /**
698  * Stop traffic manipulation
699  */
700 void
701 GST_manipulation_stop ()
702 {
703         struct DelayQueueEntry *cur;
704         struct DelayQueueEntry *next;
705         GNUNET_CONTAINER_multihashmap_iterate (man_handle.peers, &free_tmps,NULL);
706         GNUNET_CONTAINER_multihashmap_destroy (man_handle.peers);
707
708         next = generic_dqe_head;
709         while (NULL != (cur = next))
710         {
711                         next = cur->next;
712                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, cur);
713                         if (NULL != cur->cont)
714                                 cur->cont (cur->cont_cls, GNUNET_SYSERR, cur->msg_size, 0);
715                         GNUNET_free (cur);
716         }
717         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
718         {
719                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
720                         generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK;
721         }
722
723         free_metric (&man_handle.general);
724         man_handle.peers = NULL;
725 }
726
727
728 /* end of file gnunet-service-transport_manipulation.c */