Removing all the tests for the bluetooth transport plugin.
[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                 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_us) && (UINT32_MAX != g_recv_delay))
545           m_delay.rel_value_us = 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_us = 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_us > m_delay.rel_value_us)
561                 m_delay = quota_delay;
562
563         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564                     "Delaying next receive for peer `%s' for %s\n",
565                     GNUNET_i2s (peer),
566                     GNUNET_STRINGS_relative_time_to_string (m_delay, GNUNET_YES));
567         return m_delay;
568
569 }
570
571
572 /**
573  * Initialize traffic manipulation
574  *
575  * @param GST_cfg configuration handle
576  */
577 void
578 GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg)
579 {
580   unsigned long long tmp;
581   struct GNUNET_TIME_Relative delay;
582   
583   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
584                                                           "transport",
585                                                           "MANIPULATE_DISTANCE_IN",
586                                                             &tmp)) && 
587         (tmp > 0) )
588   {
589     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
590                 "Setting inbound distance_in to %llu\n",
591                 (unsigned long long) tmp);
592     set_metric (&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
593   }
594        
595   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
596                                                             "transport", 
597                                                             "MANIPULATE_DISTANCE_OUT",
598                                                             &tmp)) &&
599        (tmp > 0) )
600   {
601     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
602                 "Setting outbound distance_in to %llu\n",
603                 (unsigned long long) tmp);
604     set_metric (&man_handle.general, TM_SEND, 
605                 GNUNET_ATS_QUALITY_NET_DISTANCE, tmp);
606   }
607   
608   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
609                                                           "transport",
610                                                           "MANIPULATE_DELAY_IN",
611                                                           &delay)) && 
612        (delay.rel_value_us > 0) )
613   {
614     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
615                 "Delaying inbound traffic for %s\n",
616                 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
617     set_metric (&man_handle.general, TM_RECEIVE,
618                 GNUNET_ATS_QUALITY_NET_DELAY, 
619                 delay.rel_value_us);
620   }
621   if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
622                                                           "transport",
623                                                           "MANIPULATE_DELAY_OUT",
624                                                           &delay)) && 
625        (delay.rel_value_us > 0) )
626   {
627     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
628                 "Delaying outbound traffic for %s\n",
629                 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
630     set_metric (&man_handle.general, 
631                 TM_SEND,
632                 GNUNET_ATS_QUALITY_NET_DELAY, 
633                 delay.rel_value_us);
634   }  
635   man_handle.peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
636 }
637
638
639 static int 
640 free_tmps (void *cls,
641            const struct GNUNET_HashCode * key,
642            void *value)
643 {
644   struct DelayQueueEntry *dqe;
645   struct DelayQueueEntry *next;
646
647   if (NULL != value)
648   {
649     struct TM_Peer *tmp = (struct TM_Peer *) value;
650
651     if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (man_handle.peers, key, value))
652       GNUNET_break (0);
653     free_metric (tmp);
654     next = tmp->send_head;
655     while (NULL != (dqe = next))
656       {
657         next = dqe->next;
658         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
659         if (NULL != dqe->cont)
660           dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
661         GNUNET_free (dqe);
662       }
663     if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task)
664       {
665         GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
666         tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
667       }
668     GNUNET_free (tmp);
669   }
670   return GNUNET_OK;
671 }
672
673
674 /**
675  * Notify manipulation about disconnect so it can discard queued messages
676  *
677  * @param peer the disconnecting peer
678  */
679 void
680 GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
681 {
682         struct TM_Peer *tmp;
683         struct DelayQueueEntry *dqe;
684         struct DelayQueueEntry *next;
685
686         if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey)))
687         {
688                         next = tmp->send_head;
689                         while (NULL != (dqe = next))
690                         {
691                                         next = dqe->next;
692                                         GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
693                                         if (NULL != dqe->cont)
694                                                         dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
695                                         GNUNET_free (dqe);
696                         }
697         }
698         else if (UINT32_MAX != find_metric (&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND))
699         {
700                         next = generic_dqe_head;
701                         while (NULL != (dqe = next))
702                         {
703                                         next = dqe->next;
704                                         if (0 == memcmp (peer, &dqe->id, sizeof (dqe->id)))
705                                         {
706                                                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, dqe);
707                                                         if (NULL != dqe->cont)
708                                                                 dqe->cont (dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0);
709                                                         GNUNET_free (dqe);
710                                         }
711                         }
712                         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
713                         {
714                                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
715                                         if (NULL != generic_dqe_head)
716                                                 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (
717                                                                 GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at),
718                                                                 &send_delayed, generic_dqe_head);
719                         }
720         }
721 }
722
723
724 /**
725  * Stop traffic manipulation
726  */
727 void
728 GST_manipulation_stop ()
729 {
730         struct DelayQueueEntry *cur;
731         struct DelayQueueEntry *next;
732         GNUNET_CONTAINER_multihashmap_iterate (man_handle.peers, &free_tmps,NULL);
733         GNUNET_CONTAINER_multihashmap_destroy (man_handle.peers);
734
735         next = generic_dqe_head;
736         while (NULL != (cur = next))
737         {
738                         next = cur->next;
739                         GNUNET_CONTAINER_DLL_remove (generic_dqe_head, generic_dqe_tail, cur);
740                         if (NULL != cur->cont)
741                                 cur->cont (cur->cont_cls, GNUNET_SYSERR, cur->msg_size, 0);
742                         GNUNET_free (cur);
743         }
744         if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task)
745         {
746                         GNUNET_SCHEDULER_cancel (generic_send_delay_task);
747                         generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK;
748         }
749
750         free_metric (&man_handle.general);
751         man_handle.peers = NULL;
752 }
753
754
755 /* end of file gnunet-service-transport_manipulation.c */