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