-some minor code cleanup
[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_us = 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 %ms\n",
438                                                         msg_size, GNUNET_i2s (target),
439                                                     GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
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_us = 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 %s\n",
465                                     msg_size, GNUNET_i2s (target),
466                                     GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
467                         return;
468         }
469
470         /* Normal sending */
471         GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls);
472 }
473
474
475 /**
476  * Function that will be called to manipulate ATS information according to
477  * current manipulation settings
478  *
479  * @param peer the peer
480  * @param address binary address
481  * @param session the session
482  * @param ats the ats information
483  * @param ats_count the number of ats information
484  */
485 struct GNUNET_ATS_Information *
486 GST_manipulation_manipulate_metrics (const struct GNUNET_PeerIdentity *peer,
487                 const struct GNUNET_HELLO_Address *address,
488                 struct Session *session,
489                 const struct GNUNET_ATS_Information *ats,
490                 uint32_t ats_count)
491 {
492         struct GNUNET_ATS_Information *ats_new = GNUNET_malloc (sizeof (struct GNUNET_ATS_Information) *ats_count);
493         struct TM_Peer *tmp;
494         uint32_t m_tmp;
495         uint32_t g_tmp;
496         int d;
497         tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey);
498
499         for (d = 0; d < ats_count; d++)
500         {
501                 ats_new[d] = ats[d];
502                 m_tmp = UINT32_MAX;
503                 g_tmp = UINT32_MAX;
504                 if (NULL != tmp)
505                         m_tmp = find_metric (tmp, ntohl(ats[d].type), TM_RECEIVE);
506                 g_tmp = find_metric (&man_handle.general, ntohl(ats[d].type), TM_RECEIVE);
507
508                 if (UINT32_MAX != g_tmp)
509                                 ats_new[d].value = htonl(g_tmp);
510                 if (UINT32_MAX != m_tmp)
511                                 ats_new[d].value = htonl(m_tmp);
512         }
513
514         return ats_new;
515 }
516
517
518 /**
519  * Adapter function between transport plugins and transport receive function
520  * manipulation delays for next send.
521  *
522  * @param cls the closure for transport
523  * @param peer the peer the message was received from
524  * @param message the message received
525  * @param session the session the message was received on
526  * @param sender_address the sender address
527  * @param sender_address_len the length of the sender address
528  * @return manipulated delay for next receive
529  */
530 struct GNUNET_TIME_Relative
531 GST_manipulation_recv (void *cls,
532                 const struct GNUNET_PeerIdentity *peer,
533     const struct GNUNET_MessageHeader *message,
534     struct Session *session,
535     const char *sender_address,
536     uint16_t sender_address_len)
537 {
538         struct TM_Peer *tmp;
539         uint32_t p_recv_delay;
540         uint32_t g_recv_delay;
541         struct GNUNET_TIME_Relative quota_delay;
542         struct GNUNET_TIME_Relative m_delay;
543
544         g_recv_delay = find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE);
545         if ((g_recv_delay >= GNUNET_TIME_UNIT_ZERO.rel_value_us) && (UINT32_MAX != g_recv_delay))
546           m_delay.rel_value_us = g_recv_delay; /* Global delay */
547         else
548           m_delay = GNUNET_TIME_UNIT_ZERO;
549
550         if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey)))
551         {
552           /* Manipulate receive delay */
553           p_recv_delay = find_metric (tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE);
554           if (UINT32_MAX != p_recv_delay)
555             m_delay.rel_value_us = p_recv_delay; /* Peer specific delay */
556         }
557
558         quota_delay = GST_receive_callback (cls, peer, message,
559                         session, sender_address, sender_address_len);
560
561         if (quota_delay.rel_value_us > m_delay.rel_value_us)
562                 m_delay = quota_delay;
563
564         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
565                     "Delaying next receive for peer `%s' for %s\n",
566                     GNUNET_i2s (peer),
567                     GNUNET_STRINGS_relative_time_to_string (m_delay, GNUNET_YES));
568         return m_delay;
569
570 }
571
572
573 /**
574  * Initialize traffic manipulation
575  *
576  * @param GST_cfg configuration handle
577  */
578 void
579 GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg)
580 {
581         unsigned long long tmp;
582
583         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
584                         "transport", "MANIPULATE_DISTANCE_IN", &tmp) && (tmp > 0))
585         {
586                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting inbound distance_in to %u\n",
587                                 (unsigned long long) tmp);
588                 set_metric (&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
589         }
590
591         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
592                         "transport", "MANIPULATE_DISTANCE_OUT", &tmp) && (tmp > 0))
593         {
594                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting outbound distance_in to %u\n",
595                                 (unsigned long long) tmp);
596                 set_metric (&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
597         }
598
599         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
600                         "transport", "MANIPULATE_DELAY_IN", &tmp) && (tmp > 0))
601         {
602                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying inbound traffic for %llu ms\n",
603                                 (unsigned long long) tmp);
604                 set_metric (&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DELAY, tmp);
605         }
606
607
608         if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
609                         "transport", "MANIPULATE_DELAY_OUT", &tmp) && (tmp > 0))
610         {
611                 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying outbound traffic for %llu ms\n",
612                                 (unsigned long long) tmp);
613                 set_metric (&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DELAY, tmp);
614         }
615
616         man_handle.peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
617 }
618
619
620 static int 
621 free_tmps (void *cls,
622            const struct GNUNET_HashCode * key,
623            void *value)
624 {
625         struct DelayQueueEntry *dqe;
626         struct DelayQueueEntry *next;
627         if (NULL != value)
628         {
629                         struct TM_Peer *tmp = (struct TM_Peer *) value;
630                         if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (man_handle.peers, key, value))
631                                 GNUNET_break (0);
632                         free_metric (tmp);
633                         next = tmp->send_head;
634                         while (NULL != (dqe = next))
635                         {
636                                         next = dqe->next;
637                                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
638                                         if (NULL != dqe->cont)
639                                                         dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
640                                         GNUNET_free (dqe);
641                         }
642                         if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task)
643                         {
644                                         GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
645                                         tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
646                         }
647                         GNUNET_free (tmp);
648         }
649         return GNUNET_OK;
650 }
651
652 /**
653  * Notify manipulation about disconnect so it can discard queued messages
654  *
655  * @param peer the disconnecting peer
656  */
657 void
658 GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
659 {
660         struct TM_Peer *tmp;
661         struct DelayQueueEntry *dqe;
662         struct DelayQueueEntry *next;
663
664         if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey)))
665         {
666                         next = tmp->send_head;
667                         while (NULL != (dqe = next))
668                         {
669                                         next = dqe->next;
670                                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
671                                         if (NULL != dqe->cont)
672                                                         dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
673                                         GNUNET_free (dqe);
674                         }
675         }
676         else if (UINT32_MAX != find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
677         {
678                         next = generic_dqe_head;
679                         while (NULL != (dqe = next))
680                         {
681                                         next = dqe->next;
682                                         if (0 == memcmp (peer, &dqe->id, sizeof (dqe->id)))
683                                         {
684                                                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, dqe);
685                                                         if (NULL != dqe->cont)
686                                                                 dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
687                                                         GNUNET_free (dqe);
688                                         }
689                         }
690                         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
691                         {
692                                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
693                                         generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at), &send_delayed, generic_dqe_head);
694                         }
695         }
696 }
697
698
699 /**
700  * Stop traffic manipulation
701  */
702 void
703 GST_manipulation_stop ()
704 {
705         struct DelayQueueEntry *cur;
706         struct DelayQueueEntry *next;
707         GNUNET_CONTAINER_multihashmap_iterate (man_handle.peers, &free_tmps,NULL);
708         GNUNET_CONTAINER_multihashmap_destroy (man_handle.peers);
709
710         next = generic_dqe_head;
711         while (NULL != (cur = next))
712         {
713                         next = cur->next;
714                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, cur);
715                         if (NULL != cur->cont)
716                                 cur->cont (cur->cont_cls, GNUNET_SYSERR, cur->msg_size, 0);
717                         GNUNET_free (cur);
718         }
719         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
720         {
721                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
722                         generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK;
723         }
724
725         free_metric (&man_handle.general);
726         man_handle.peers = NULL;
727 }
728
729
730 /* end of file gnunet-service-transport_manipulation.c */