-remove trailing whitespace
[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_MultiPeerMap *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_multipeermap_get (man_handle.peers, &tm->peer)))
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_multipeermap_put (man_handle.peers,
340                                                            &tm->peer, tmp,
341                                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
342         }
343
344         ats = (struct GNUNET_ATS_Information *) &tm[1];
345         for (c = 0; c < ntohs (tm->ats_count); c++)
346         {
347                         type = htonl (ats[c].type);
348                         value = htonl (ats[c].value);
349                         set_metric (tmp, direction, type, value);
350         }
351
352   GNUNET_SERVER_receive_done (client, GNUNET_OK);
353 }
354
355 static void
356 send_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
357 {
358         struct DelayQueueEntry *dqe = cls;
359         struct DelayQueueEntry *next;
360         struct TM_Peer *tmp = dqe->tmp;
361         struct GNUNET_TIME_Relative delay;
362
363         if (NULL != tmp)
364         {
365                         GNUNET_break (GNUNET_YES == GST_neighbours_test_connected (&dqe->id));
366                         tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
367                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
368                         GST_neighbours_send (&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls);
369
370                         next = tmp->send_head;
371                         if (NULL != next)
372                         {
373                                 /* More delayed messages */
374                                 delay = GNUNET_TIME_absolute_get_remaining (next->sent_at);
375                                 tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, next);
376                         }
377         }
378         else
379         {
380                         /* Remove from generic queue */
381                         GNUNET_break (GNUNET_YES == GST_neighbours_test_connected (&dqe->id));
382                         generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK;
383                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, dqe);
384                         GST_neighbours_send (&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls);
385                         next = generic_dqe_head;
386                         if (NULL != next)
387                         {
388                                 /* More delayed messages */
389                                 delay = GNUNET_TIME_absolute_get_remaining (next->sent_at);
390                                 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, next);
391                         }
392         }
393         GNUNET_free (dqe);
394 }
395
396
397 /**
398  * Adapter function between transport's send function and transport plugins
399  *
400  * @param target the peer the message to send to
401  * @param msg the message received
402  * @param msg_size message size
403  * @param timeout timeout
404  * @param cont the continuation to call after sending
405  * @param cont_cls cls for continuation
406  */
407 void
408 GST_manipulation_send (const struct GNUNET_PeerIdentity *target, const void *msg,
409     size_t msg_size, struct GNUNET_TIME_Relative timeout,
410     GST_NeighbourSendContinuation cont, void *cont_cls)
411 {
412   struct TM_Peer *tmp;
413   struct DelayQueueEntry *dqe;
414   struct GNUNET_TIME_Relative delay;
415
416   if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get (man_handle.peers, target)))
417   {
418     GNUNET_break (GNUNET_YES == GST_neighbours_test_connected(target));
419     /* Manipulate here */
420     /* Delay */
421     if (UINT32_MAX != find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
422     {
423       /* We have a delay */
424       delay.rel_value_us = find_metric (tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND);
425       dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
426       dqe->id = *target;
427       dqe->tmp = tmp;
428       dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
429       dqe->cont = cont;
430       dqe->cont_cls = cont_cls;
431       dqe->msg = &dqe[1];
432       dqe->msg_size = msg_size;
433       dqe->timeout = timeout;
434       memcpy (dqe->msg, msg, msg_size);
435       GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe);
436       if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task)
437         tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
438       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
439           "Delaying %u byte message to peer `%s' with generic delay for %ms\n",
440           msg_size, GNUNET_i2s (target),
441           GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
442       return;
443     }
444   }
445   else if (UINT32_MAX != find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
446   {
447     GNUNET_break (GNUNET_YES == GST_neighbours_test_connected(target));
448     /* We have a delay */
449     delay.rel_value_us = find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND);
450     dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
451     dqe->id = *target;
452     dqe->tmp = NULL;
453     dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
454     dqe->cont = cont;
455     dqe->cont_cls = cont_cls;
456     dqe->msg = &dqe[1];
457     dqe->msg_size = msg_size;
458     dqe->timeout = timeout;
459     memcpy (dqe->msg, msg, msg_size);
460     GNUNET_CONTAINER_DLL_insert_tail (generic_dqe_head, generic_dqe_tail, dqe);
461     if (GNUNET_SCHEDULER_NO_TASK == generic_send_delay_task)
462     {
463         generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
464     }
465     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
466         "Delaying %u byte message to peer `%s' with peer specific delay for %s\n",
467         msg_size, GNUNET_i2s (target),
468         GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
469     return;
470   }
471
472   /* Normal sending */
473   GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls);
474 }
475
476
477 /**
478  * Function that will be called to manipulate ATS information according to
479  * current manipulation settings
480  *
481  * @param peer the peer
482  * @param address binary address
483  * @param session the session
484  * @param ats the ats information
485  * @param ats_count the number of ats information
486  */
487 struct GNUNET_ATS_Information *
488 GST_manipulation_manipulate_metrics (const struct GNUNET_PeerIdentity *peer,
489                 const struct GNUNET_HELLO_Address *address,
490                 struct Session *session,
491                 const struct GNUNET_ATS_Information *ats,
492                 uint32_t ats_count)
493 {
494         struct GNUNET_ATS_Information *ats_new = GNUNET_malloc (sizeof (struct GNUNET_ATS_Information) *ats_count);
495         struct TM_Peer *tmp;
496         uint32_t m_tmp;
497         uint32_t g_tmp;
498         int d;
499         tmp = GNUNET_CONTAINER_multipeermap_get (man_handle.peers, peer);
500
501         for (d = 0; d < ats_count; d++)
502         {
503                 ats_new[d] = ats[d];
504                 m_tmp = UINT32_MAX;
505                 if (NULL != tmp)
506                         m_tmp = find_metric (tmp, ntohl(ats[d].type), TM_RECEIVE);
507                 g_tmp = find_metric (&man_handle.general, ntohl(ats[d].type), TM_RECEIVE);
508
509                 if (UINT32_MAX != g_tmp)
510                                 ats_new[d].value = htonl(g_tmp);
511                 if (UINT32_MAX != m_tmp)
512                                 ats_new[d].value = htonl(m_tmp);
513         }
514
515         return ats_new;
516 }
517
518
519 /**
520  * Adapter function between transport plugins and transport receive function
521  * manipulation delays for next send.
522  *
523  * @param cls the closure for transport
524  * @param peer the peer the message was received from
525  * @param message the message received
526  * @param session the session the message was received on
527  * @param sender_address the sender address
528  * @param sender_address_len the length of the sender address
529  * @return manipulated delay for next receive
530  */
531 struct GNUNET_TIME_Relative
532 GST_manipulation_recv (void *cls,
533                 const struct GNUNET_PeerIdentity *peer,
534     const struct GNUNET_MessageHeader *message,
535     struct Session *session,
536     const char *sender_address,
537     uint16_t sender_address_len)
538 {
539         struct TM_Peer *tmp;
540         uint32_t p_recv_delay;
541         uint32_t g_recv_delay;
542         struct GNUNET_TIME_Relative quota_delay;
543         struct GNUNET_TIME_Relative m_delay;
544
545         g_recv_delay = find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE);
546         if ((g_recv_delay >= GNUNET_TIME_UNIT_ZERO.rel_value_us) && (UINT32_MAX != g_recv_delay))
547           m_delay.rel_value_us = g_recv_delay; /* Global delay */
548         else
549           m_delay = GNUNET_TIME_UNIT_ZERO;
550
551         if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get (man_handle.peers, peer)))
552         {
553           /* Manipulate receive delay */
554           p_recv_delay = find_metric (tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE);
555           if (UINT32_MAX != p_recv_delay)
556             m_delay.rel_value_us = p_recv_delay; /* Peer specific delay */
557         }
558
559         quota_delay = GST_receive_callback (cls, peer, message,
560                         session, sender_address, sender_address_len);
561
562         if (quota_delay.rel_value_us > m_delay.rel_value_us)
563                 m_delay = quota_delay;
564
565         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
566                     "Delaying next receive for peer `%s' for %s\n",
567                     GNUNET_i2s (peer),
568                     GNUNET_STRINGS_relative_time_to_string (m_delay, GNUNET_YES));
569         return m_delay;
570
571 }
572
573
574 /**
575  * Initialize traffic manipulation
576  *
577  * @param GST_cfg configuration handle
578  */
579 void
580 GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg)
581 {
582   unsigned long long tmp;
583   struct GNUNET_TIME_Relative delay;
584
585   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
586                                                           "transport",
587                                                           "MANIPULATE_DISTANCE_IN",
588                                                             &tmp)) &&
589         (tmp > 0) )
590   {
591     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
592                 "Setting inbound distance_in to %llu\n",
593                 (unsigned long long) tmp);
594     set_metric (&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
595   }
596
597   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
598                                                             "transport",
599                                                             "MANIPULATE_DISTANCE_OUT",
600                                                             &tmp)) &&
601        (tmp > 0) )
602   {
603     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
604                 "Setting outbound distance_in to %llu\n",
605                 (unsigned long long) tmp);
606     set_metric (&man_handle.general, TM_SEND,
607                 GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
608   }
609
610   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
611                                                           "transport",
612                                                           "MANIPULATE_DELAY_IN",
613                                                           &delay)) &&
614        (delay.rel_value_us > 0) )
615   {
616     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
617                 "Delaying inbound traffic for %s\n",
618                 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
619     set_metric (&man_handle.general, TM_RECEIVE,
620                 GNUNET_ATS_QUALITY_NET_DELAY,
621                 delay.rel_value_us);
622   }
623   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
624                                                           "transport",
625                                                           "MANIPULATE_DELAY_OUT",
626                                                           &delay)) &&
627        (delay.rel_value_us > 0) )
628   {
629     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
630                 "Delaying outbound traffic for %s\n",
631                 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
632     set_metric (&man_handle.general,
633                 TM_SEND,
634                 GNUNET_ATS_QUALITY_NET_DELAY,
635                 delay.rel_value_us);
636   }
637   man_handle.peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
638 }
639
640
641 static int
642 free_tmps (void *cls,
643            const struct GNUNET_PeerIdentity *key,
644            void *value)
645 {
646   struct DelayQueueEntry *dqe;
647   struct DelayQueueEntry *next;
648
649   if (NULL != value)
650   {
651     struct TM_Peer *tmp = (struct TM_Peer *) value;
652
653     if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (man_handle.peers, key, value))
654       GNUNET_break (0);
655     free_metric (tmp);
656     next = tmp->send_head;
657     while (NULL != (dqe = next))
658       {
659         next = dqe->next;
660         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
661         if (NULL != dqe->cont)
662           dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
663         GNUNET_free (dqe);
664       }
665     if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task)
666       {
667         GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
668         tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
669       }
670     GNUNET_free (tmp);
671   }
672   return GNUNET_OK;
673 }
674
675
676 /**
677  * Notify manipulation about disconnect so it can discard queued messages
678  *
679  * @param peer the disconnecting peer
680  */
681 void
682 GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
683 {
684         struct TM_Peer *tmp;
685         struct DelayQueueEntry *dqe;
686         struct DelayQueueEntry *next;
687
688         if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get (man_handle.peers, peer)))
689         {
690                         next = tmp->send_head;
691                         while (NULL != (dqe = next))
692                         {
693                                         next = dqe->next;
694                                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
695                                         if (NULL != dqe->cont)
696                                                         dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
697                                         GNUNET_free (dqe);
698                         }
699         }
700         else if (UINT32_MAX != find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
701         {
702                         next = generic_dqe_head;
703                         while (NULL != (dqe = next))
704                         {
705                                         next = dqe->next;
706                                         if (0 == memcmp (peer, &dqe->id, sizeof (dqe->id)))
707                                         {
708                                                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, dqe);
709                                                         if (NULL != dqe->cont)
710                                                                 dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
711                                                         GNUNET_free (dqe);
712                                         }
713                         }
714                         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
715                         {
716                                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
717                                         if (NULL != generic_dqe_head)
718                                                 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (
719                                                                 GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at),
720                                                                 &send_delayed, generic_dqe_head);
721                         }
722         }
723 }
724
725
726 /**
727  * Stop traffic manipulation
728  */
729 void
730 GST_manipulation_stop ()
731 {
732         struct DelayQueueEntry *cur;
733         struct DelayQueueEntry *next;
734         GNUNET_CONTAINER_multipeermap_iterate (man_handle.peers, &free_tmps,NULL);
735         GNUNET_CONTAINER_multipeermap_destroy (man_handle.peers);
736
737         next = generic_dqe_head;
738         while (NULL != (cur = next))
739         {
740                         next = cur->next;
741                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, cur);
742                         if (NULL != cur->cont)
743                                 cur->cont (cur->cont_cls, GNUNET_SYSERR, cur->msg_size, 0);
744                         GNUNET_free (cur);
745         }
746         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
747         {
748                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
749                         generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK;
750         }
751
752         free_metric (&man_handle.general);
753         man_handle.peers = NULL;
754 }
755
756
757 /* end of file gnunet-service-transport_manipulation.c */