aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_manipulation.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/gnunet-service-transport_manipulation.c')
-rw-r--r--src/transport/gnunet-service-transport_manipulation.c667
1 files changed, 230 insertions, 437 deletions
diff --git a/src/transport/gnunet-service-transport_manipulation.c b/src/transport/gnunet-service-transport_manipulation.c
index f52634edc..b58ade999 100644
--- a/src/transport/gnunet-service-transport_manipulation.c
+++ b/src/transport/gnunet-service-transport_manipulation.c
@@ -34,66 +34,36 @@
34#include "gnunet-service-transport.h" 34#include "gnunet-service-transport.h"
35#include "transport.h" 35#include "transport.h"
36 36
37enum TRAFFIC_METRIC_DIRECTION
38{
39 TM_SEND = 0, TM_RECEIVE = 1, TM_BOTH = 2
40};
41
42 37
43/** 38/**
44 * Struct containing information about manipulations to a specific peer 39 * Struct containing information about manipulations to a specific peer
45 */ 40 */
46struct TM_Peer; 41struct TM_Peer
47
48/**
49 * Manipulation entry
50 */
51struct PropManipulationEntry
52{ 42{
53 /** 43 /**
54 * Next in DLL 44 * Peer ID
55 */
56 struct PropManipulationEntry *next;
57
58 /**
59 * Previous in DLL
60 */
61 struct PropManipulationEntry *prev;
62
63 /**
64 * ATS type in HBO
65 */ 45 */
66 uint32_t type; 46 struct GNUNET_PeerIdentity peer;
67 47
68 /** 48 /**
69 * Value in HBO 49 * How long to delay incoming messages for this peer.
70 */ 50 */
71 uint32_t metrics[TM_BOTH]; 51 struct GNUNET_TIME_Relative delay_in;
72 52
73};
74
75/**
76 * Struct containing information about manipulations to a specific peer
77 */
78struct TM_Peer
79{
80 /** 53 /**
81 * Peer ID 54 * How long to delay outgoing messages for this peer.
82 */ 55 */
83 struct GNUNET_PeerIdentity peer; 56 struct GNUNET_TIME_Relative delay_out;
84
85 struct PropManipulationEntry *head;
86 struct PropManipulationEntry *tail;
87 57
88 /** 58 /**
89 * Peer specific manipulation metrics 59 * Manipulated properties to use for this peer.
90 */ 60 */
91 uint32_t metrics[TM_BOTH][GNUNET_ATS_QualityPropertiesCount]; 61 struct GNUNET_ATS_Properties properties;
92 62
93 /** 63 /**
94 * Task to schedule delayed sendding 64 * Task to schedule delayed sendding
95 */ 65 */
96 struct GNUNET_SCHEDULER_Task * send_delay_task; 66 struct GNUNET_SCHEDULER_Task *send_delay_task;
97 67
98 /** 68 /**
99 * Send queue DLL head 69 * Send queue DLL head
@@ -107,19 +77,6 @@ struct TM_Peer
107}; 77};
108 78
109 79
110struct GST_ManipulationHandle
111{
112 /**
113 * Hashmap contain all peers currently manipulated
114 */
115 struct GNUNET_CONTAINER_MultiPeerMap *peers;
116
117 /**
118 * Peer containing information for general manipulation
119 */
120 struct TM_Peer general;
121};
122
123/** 80/**
124 * Entry in the delay queue for an outbound delayed message 81 * Entry in the delay queue for an outbound delayed message
125 */ 82 */
@@ -136,9 +93,10 @@ struct DelayQueueEntry
136 struct DelayQueueEntry *next; 93 struct DelayQueueEntry *next;
137 94
138 /** 95 /**
139 * Peer this entry is belonging to 96 * Peer this entry is belonging to if (NULL == tmp): enqueued in
140 * if (NULL == tmp): enqueued in generic DLL and scheduled by generic_send_delay_task 97 * generic DLL and scheduled by generic_send_delay_task else:
141 * else: enqueued in tmp->send_head and tmp->send_tail and scheduled by tmp->send_delay_task 98 * enqueued in tmp->send_head and tmp->send_tail and scheduled by
99 * tmp->send_delay_task
142 */ 100 */
143 struct TM_Peer *tmp; 101 struct TM_Peer *tmp;
144 102
@@ -178,91 +136,35 @@ struct DelayQueueEntry
178 void *cont_cls; 136 void *cont_cls;
179}; 137};
180 138
181struct GST_ManipulationHandle man_handle;
182
183/** 139/**
184 * DLL head for delayed messages based on general delay 140 * Hashmap contain all peers currently manipulated
185 */ 141 */
186struct DelayQueueEntry *generic_dqe_head; 142static struct GNUNET_CONTAINER_MultiPeerMap *peers;
187 143
188/** 144/**
189 * DLL tail for delayed messages based on general delay 145 * Inbound delay to apply to all peers.
190 */ 146 */
191struct DelayQueueEntry *generic_dqe_tail; 147static struct GNUNET_TIME_Relative delay_in;
192 148
193/** 149/**
194 * Task to schedule delayed sending based on general delay 150 * Outbound delay to apply to all peers.
195 */ 151 */
196struct GNUNET_SCHEDULER_Task * generic_send_delay_task; 152static struct GNUNET_TIME_Relative delay_out;
197
198
199static void
200set_metric(struct TM_Peer *dest, int direction, uint32_t type, uint32_t value)
201{
202 struct PropManipulationEntry *cur;
203 for (cur = dest->head; NULL != cur; cur = cur->next)
204 {
205 if (cur->type == type)
206 break;
207 }
208 if (NULL == cur)
209 {
210 cur = GNUNET_new (struct PropManipulationEntry);
211 GNUNET_CONTAINER_DLL_insert(dest->head, dest->tail, cur);
212 cur->type = type;
213 cur->metrics[TM_SEND] = UINT32_MAX;
214 cur->metrics[TM_RECEIVE] = UINT32_MAX;
215 }
216
217 switch (direction)
218 {
219 case TM_BOTH:
220 cur->metrics[TM_SEND] = value;
221 cur->metrics[TM_RECEIVE] = value;
222 break;
223 case TM_SEND:
224 cur->metrics[TM_SEND] = value;
225 break;
226 case TM_RECEIVE:
227 cur->metrics[TM_RECEIVE] = value;
228 break;
229 default:
230 break;
231 }
232}
233
234
235static uint32_t
236find_metric(struct TM_Peer *dest, uint32_t type, int direction)
237{
238 struct PropManipulationEntry *cur;
239
240 for (cur = dest->head; NULL != cur; cur = cur->next)
241 {
242 if (cur->type == type)
243 return cur->metrics[direction];
244
245 }
246 return UINT32_MAX;
247}
248 153
154/**
155 * DLL head for delayed messages based on general delay
156 */
157static struct DelayQueueEntry *generic_dqe_head;
249 158
250/** 159/**
251 * Clean up metrics for a peer 160 * DLL tail for delayed messages based on general delay
252 */ 161 */
253static void 162static struct DelayQueueEntry *generic_dqe_tail;
254free_metric(struct TM_Peer *dest)
255{
256 struct PropManipulationEntry *cur;
257 struct PropManipulationEntry *next;
258 163
259 for (cur = dest->head; NULL != cur; cur = next) 164/**
260 { 165 * Task to schedule delayed sending based on general delay
261 next = cur->next; 166 */
262 GNUNET_CONTAINER_DLL_remove(dest->head, dest->tail, cur); 167static struct GNUNET_SCHEDULER_Task *generic_send_delay_task;
263 GNUNET_free(cur);
264 }
265}
266 168
267 169
268/** 170/**
@@ -273,134 +175,106 @@ free_metric(struct TM_Peer *dest)
273 * @param message containing information 175 * @param message containing information
274 */ 176 */
275void 177void
276GST_manipulation_set_metric(void *cls, struct GNUNET_SERVER_Client *client, 178GST_manipulation_set_metric (void *cls,
277 const struct GNUNET_MessageHeader *message) 179 struct GNUNET_SERVER_Client *client,
180 const struct GNUNET_MessageHeader *message)
278{ 181{
279 struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message; 182 const struct TrafficMetricMessage *tm;
280 struct GNUNET_PeerIdentity dummy; 183 static struct GNUNET_PeerIdentity zero;
281 struct GNUNET_ATS_Information *ats;
282 struct TM_Peer *tmp; 184 struct TM_Peer *tmp;
283 uint32_t type;
284 uint32_t value;
285 uint16_t direction;
286 int c;
287 int c2;
288
289 if (0 == ntohs(tm->ats_count))
290 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
291
292 direction = TM_BOTH;
293 switch (ntohs(tm->direction))
294 {
295 case 1:
296 direction = TM_SEND;
297 break;
298 case 2:
299 direction = TM_RECEIVE;
300 break;
301 case 3:
302 direction = TM_BOTH;
303 break;
304 default:
305 break;
306 }
307
308 memset(&dummy, '\0', sizeof(struct GNUNET_PeerIdentity));
309 if (0 == memcmp(&tm->peer, &dummy, sizeof(struct GNUNET_PeerIdentity)))
310 {
311 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
312 "Received traffic metrics for all peers \n");
313
314 ats = (struct GNUNET_ATS_Information *) &tm[1];
315 for (c = 0; c < ntohs(tm->ats_count); c++)
316 {
317 type = htonl(ats[c].type);
318 value = htonl(ats[c].value);
319 set_metric(&man_handle.general, direction, type, value);
320 }
321 return;
322 }
323
324 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
325 "Received traffic metrics for peer `%s'\n", GNUNET_i2s(&tm->peer));
326
327 if (NULL
328 == (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, &tm->peer)))
329 {
330 tmp = GNUNET_new (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, &tm->peer, tmp,
340 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
341 }
342 185
343 ats = (struct GNUNET_ATS_Information *) &tm[1]; 186 tm = (const struct TrafficMetricMessage *) message;
344 for (c = 0; c < ntohs(tm->ats_count); c++) 187 if (0 == memcmp (&tm->peer,
345 { 188 &zero,
346 type = htonl(ats[c].type); 189 sizeof(struct GNUNET_PeerIdentity)))
347 value = htonl(ats[c].value); 190 {
348 set_metric(tmp, direction, type, value); 191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
349 } 192 "Received traffic metrics for all peers\n");
350 193 delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in);
351 GNUNET_SERVER_receive_done(client, GNUNET_OK); 194 delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out);
195 GNUNET_SERVER_receive_done (client,
196 GNUNET_OK);
197 return;
198 }
199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
200 "Received traffic metrics for peer `%s'\n",
201 GNUNET_i2s(&tm->peer));
202 if (NULL ==
203 (tmp = GNUNET_CONTAINER_multipeermap_get (peers,
204 &tm->peer)))
205 {
206 tmp = GNUNET_new (struct TM_Peer);
207 tmp->peer = tm->peer;
208 GNUNET_CONTAINER_multipeermap_put (peers,
209 &tm->peer,
210 tmp,
211 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
212 }
213 GNUNET_ATS_properties_ntoh (&tmp->properties,
214 &tm->properties);
215 tmp->delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in);
216 tmp->delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out);
217 GNUNET_SERVER_receive_done (client,
218 GNUNET_OK);
352} 219}
353 220
354 221
222/**
223 * We have delayed transmission, now it is time to send the
224 * message.
225 *
226 * @param cls the `struct DelayQueueEntry` to transmit
227 * @param tc unused
228 */
355static void 229static void
356send_delayed(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 230send_delayed (void *cls,
231 const struct GNUNET_SCHEDULER_TaskContext *tc)
357{ 232{
358 struct DelayQueueEntry *dqe = cls; 233 struct DelayQueueEntry *dqe = cls;
359 struct DelayQueueEntry *next; 234 struct DelayQueueEntry *next;
360 struct TM_Peer *tmp = dqe->tmp; 235 struct TM_Peer *tmp = dqe->tmp;
361 struct GNUNET_TIME_Relative delay; 236 struct GNUNET_TIME_Relative delay;
362 237
238 GNUNET_break (GNUNET_YES ==
239 GST_neighbours_test_connected (&dqe->id));
363 if (NULL != tmp) 240 if (NULL != tmp)
241 {
242 tmp->send_delay_task = NULL;
243 GNUNET_CONTAINER_DLL_remove (tmp->send_head,
244 tmp->send_tail,
245 dqe);
246 next = tmp->send_head;
247 if (NULL != next)
364 { 248 {
365 GNUNET_break (GNUNET_YES == 249 /* More delayed messages */
366 GST_neighbours_test_connected (&dqe->id)); 250 delay = GNUNET_TIME_absolute_get_remaining(next->sent_at);
367 tmp->send_delay_task = NULL; 251 tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed(delay,
368 GNUNET_CONTAINER_DLL_remove (tmp->send_head, 252 &send_delayed, next);
369 tmp->send_tail,
370 dqe);
371 GST_neighbours_send (&dqe->id,
372 dqe->msg,
373 dqe->msg_size,
374 dqe->timeout,
375 dqe->cont,
376 dqe->cont_cls);
377
378 next = tmp->send_head;
379 if (NULL != next)
380 {
381 /* More delayed messages */
382 delay = GNUNET_TIME_absolute_get_remaining(next->sent_at);
383 tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed(delay,
384 &send_delayed, next);
385 }
386 } 253 }
254 }
387 else 255 else
256 {
257 /* Remove from generic queue */
258 generic_send_delay_task = NULL;
259 GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
260 generic_dqe_tail,
261 dqe);
262 next = generic_dqe_head;
263 if (NULL != next)
388 { 264 {
389 /* Remove from generic queue */ 265 /* More delayed messages */
390 GNUNET_break(GNUNET_YES == GST_neighbours_test_connected (&dqe->id)); 266 delay = GNUNET_TIME_absolute_get_remaining(next->sent_at);
391 generic_send_delay_task = NULL; 267 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
392 GNUNET_CONTAINER_DLL_remove(generic_dqe_head, generic_dqe_tail, dqe); 268 &send_delayed,
393 GST_neighbours_send(&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout, 269 next);
394 dqe->cont, dqe->cont_cls);
395 next = generic_dqe_head;
396 if (NULL != next)
397 {
398 /* More delayed messages */
399 delay = GNUNET_TIME_absolute_get_remaining(next->sent_at);
400 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed(delay,
401 &send_delayed, next);
402 }
403 } 270 }
271 }
272 GST_neighbours_send (&dqe->id,
273 dqe->msg,
274 dqe->msg_size,
275 dqe->timeout,
276 dqe->cont,
277 dqe->cont_cls);
404 GNUNET_free(dqe); 278 GNUNET_free(dqe);
405} 279}
406 280
@@ -427,41 +301,14 @@ GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
427 struct TM_Peer *tmp; 301 struct TM_Peer *tmp;
428 struct DelayQueueEntry *dqe; 302 struct DelayQueueEntry *dqe;
429 struct GNUNET_TIME_Relative delay; 303 struct GNUNET_TIME_Relative delay;
430 int do_delay;
431 304
432 do_delay = GNUNET_NO;
433 if (NULL != (tmp = 305 if (NULL != (tmp =
434 GNUNET_CONTAINER_multipeermap_get (man_handle.peers, 306 GNUNET_CONTAINER_multipeermap_get (peers,
435 target))) 307 target)))
436 { 308 delay = tmp->delay_out;
437 GNUNET_break (GNUNET_YES == 309 else
438 GST_neighbours_test_connected(target)); 310 delay = delay_out;
439 /* check for peer-specific delay */ 311 if (0 == delay.rel_value_us)
440 if (UINT32_MAX !=
441 find_metric (tmp,
442 GNUNET_ATS_QUALITY_NET_DELAY,
443 TM_SEND))
444 {
445 /* We have a delay */
446 delay.rel_value_us = find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY,
447 TM_SEND);
448 do_delay = GNUNET_YES;
449 }
450 }
451 else if (UINT32_MAX !=
452 find_metric(&man_handle.general,
453 GNUNET_ATS_QUALITY_NET_DELAY,
454 TM_SEND))
455 {
456 GNUNET_break (GNUNET_YES ==
457 GST_neighbours_test_connected (target));
458 /* We have a delay */
459 delay.rel_value_us = find_metric (&man_handle.general,
460 GNUNET_ATS_QUALITY_NET_DELAY,
461 TM_SEND);
462 do_delay = GNUNET_YES;
463 }
464 if (GNUNET_NO == do_delay)
465 { 312 {
466 /* Normal sending */ 313 /* Normal sending */
467 GST_neighbours_send (target, 314 GST_neighbours_send (target,
@@ -516,46 +363,22 @@ GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
516 * Function that will be called to manipulate ATS information according to 363 * Function that will be called to manipulate ATS information according to
517 * current manipulation settings 364 * current manipulation settings
518 * 365 *
519 * @param peer the peer
520 * @param address binary address 366 * @param address binary address
521 * @param session the session 367 * @param session the session
522 * @param ats the ats information 368 * @param prop[IN|OUT] metrics to modify
523 * @param ats_count the number of ats information
524 */ 369 */
525struct GNUNET_ATS_Information * 370void
526GST_manipulation_manipulate_metrics (const struct GNUNET_HELLO_Address *address, 371GST_manipulation_manipulate_metrics (const struct GNUNET_HELLO_Address *address,
527 struct Session *session, 372 struct Session *session,
528 const struct GNUNET_ATS_Information *ats, 373 struct GNUNET_ATS_Properties *prop)
529 uint32_t ats_count)
530{ 374{
531 const struct GNUNET_PeerIdentity *peer = &address->peer; 375 const struct GNUNET_PeerIdentity *peer = &address->peer;
532 struct GNUNET_ATS_Information *ats_new;
533 struct TM_Peer *tmp; 376 struct TM_Peer *tmp;
534 uint32_t m_tmp; 377
535 uint32_t g_tmp; 378 tmp = GNUNET_CONTAINER_multipeermap_get (peers,
536 uint32_t d; 379 peer);
537 380 if (NULL != tmp)
538 if (0 == ats_count) 381 *prop = tmp->properties;
539 return NULL;
540 ats_new = GNUNET_malloc (sizeof (struct GNUNET_ATS_Information) * ats_count);
541 tmp = GNUNET_CONTAINER_multipeermap_get (man_handle.peers, peer);
542 for (d = 0; d < ats_count; d++)
543 {
544 ats_new[d] = ats[d];
545 m_tmp = UINT32_MAX;
546 if (NULL != tmp)
547 m_tmp = find_metric (tmp, ntohl(ats[d].type),
548 TM_RECEIVE);
549 g_tmp = find_metric (&man_handle.general,
550 ntohl(ats[d].type),
551 TM_RECEIVE);
552
553 if (UINT32_MAX != g_tmp)
554 ats_new[d].value = htonl(g_tmp);
555 if (UINT32_MAX != m_tmp)
556 ats_new[d].value = htonl(m_tmp);
557 }
558 return ats_new;
559} 382}
560 383
561 384
@@ -576,32 +399,22 @@ GST_manipulation_recv (void *cls,
576 const struct GNUNET_MessageHeader *message) 399 const struct GNUNET_MessageHeader *message)
577{ 400{
578 struct TM_Peer *tmp; 401 struct TM_Peer *tmp;
579 uint32_t p_recv_delay;
580 uint32_t g_recv_delay;
581 struct GNUNET_TIME_Relative quota_delay; 402 struct GNUNET_TIME_Relative quota_delay;
582 struct GNUNET_TIME_Relative m_delay; 403 struct GNUNET_TIME_Relative m_delay;
583 404
584 g_recv_delay = find_metric(&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, 405 if (NULL !=
585 TM_RECEIVE); 406 (tmp = GNUNET_CONTAINER_multipeermap_get (peers,
586 if ((g_recv_delay >= GNUNET_TIME_UNIT_ZERO.rel_value_us) 407 &address->peer)))
587 && (UINT32_MAX != g_recv_delay)) 408 m_delay = tmp->delay_in;
588 m_delay.rel_value_us = g_recv_delay; /* Global delay */
589 else 409 else
590 m_delay = GNUNET_TIME_UNIT_ZERO; 410 m_delay = delay_in;
591 411
592 if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, &address->peer))) 412 quota_delay = GST_receive_callback (cls,
593 { 413 address,
594 /* Manipulate receive delay */ 414 session,
595 p_recv_delay = find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE); 415 message);
596 if (UINT32_MAX != p_recv_delay) 416 m_delay = GNUNET_TIME_relative_max (m_delay,
597 m_delay.rel_value_us = p_recv_delay; /* Peer specific delay */ 417 quota_delay);
598 }
599
600 quota_delay = GST_receive_callback(cls, address, session, message);
601
602 if (quota_delay.rel_value_us > m_delay.rel_value_us)
603 m_delay = quota_delay;
604
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606 "Delaying next receive for peer `%s' for %s\n", 419 "Delaying next receive for peer `%s' for %s\n",
607 GNUNET_i2s (&address->peer), 420 GNUNET_i2s (&address->peer),
@@ -613,63 +426,110 @@ GST_manipulation_recv (void *cls,
613 426
614/** 427/**
615 * Initialize traffic manipulation 428 * Initialize traffic manipulation
616 *
617 * @param GST_cfg configuration handle
618 */ 429 */
619void 430void
620GST_manipulation_init(const struct GNUNET_CONFIGURATION_Handle *GST_cfg) 431GST_manipulation_init ()
621{ 432{
622 unsigned long long tmp;
623 struct GNUNET_TIME_Relative delay; 433 struct GNUNET_TIME_Relative delay;
624 434
625 if ( (GNUNET_OK == 435 if ( (GNUNET_OK ==
626 GNUNET_CONFIGURATION_get_value_number(GST_cfg, 436 GNUNET_CONFIGURATION_get_value_time (GST_cfg,
627 "transport", 437 "transport",
628 "MANIPULATE_DISTANCE_IN", 438 "MANIPULATE_DELAY_IN",
629 &tmp)) && 439 &delay)) &&
630 (tmp > 0) ) 440 (delay.rel_value_us > 0) )
631 { 441 {
632 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 442 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
633 "Setting inbound distance_in to %llu\n", 443 "Delaying inbound traffic for %s\n",
634 (unsigned long long) tmp); 444 GNUNET_STRINGS_relative_time_to_string (delay,
635 set_metric (&man_handle.general, 445 GNUNET_YES));
636 TM_RECEIVE, 446 delay_in = delay;
637 GNUNET_ATS_QUALITY_NET_DISTANCE,
638 tmp);
639 } 447 }
448 if ( (GNUNET_OK ==
449 GNUNET_CONFIGURATION_get_value_time (GST_cfg,
450 "transport",
451 "MANIPULATE_DELAY_OUT",
452 &delay)) &&
453 (delay.rel_value_us > 0) )
454 {
455 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
456 "Delaying outbound traffic for %s\n",
457 GNUNET_STRINGS_relative_time_to_string (delay,
458 GNUNET_YES));
459 delay_out = delay;
460 }
461 peers = GNUNET_CONTAINER_multipeermap_create (4,
462 GNUNET_NO);
463}
640 464
641 if ((GNUNET_OK
642 == GNUNET_CONFIGURATION_get_value_number(GST_cfg, "transport",
643 "MANIPULATE_DISTANCE_OUT", &tmp)) && (tmp > 0))
644 {
645 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
646 "Setting outbound distance_in to %llu\n", (unsigned long long) tmp);
647 set_metric(&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DISTANCE,
648 tmp);
649 }
650 465
651 if ((GNUNET_OK 466/**
652 == GNUNET_CONFIGURATION_get_value_time(GST_cfg, "transport", 467 * Notify manipulation about disconnect so it can discard queued messages
653 "MANIPULATE_DELAY_IN", &delay)) && (delay.rel_value_us > 0)) 468 *
469 * @param peer the disconnecting peer
470 */
471void
472GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
473{
474 struct TM_Peer *tmp;
475 struct DelayQueueEntry *dqe;
476 struct DelayQueueEntry *next;
477
478 tmp = GNUNET_CONTAINER_multipeermap_get (peers,
479 peer);
480 if (NULL != tmp)
481 {
482 while (NULL != (dqe = tmp->send_head))
654 { 483 {
655 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 484 GNUNET_CONTAINER_DLL_remove (tmp->send_head,
656 "Delaying inbound traffic for %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); 485 tmp->send_tail,
657 set_metric(&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DELAY, 486 dqe);
658 delay.rel_value_us); 487 if (NULL != dqe->cont)
488 dqe->cont (dqe->cont_cls,
489 GNUNET_SYSERR,
490 dqe->msg_size,
491 0);
492 GNUNET_free(dqe);
659 } 493 }
660 if ((GNUNET_OK 494 }
661 == GNUNET_CONFIGURATION_get_value_time(GST_cfg, "transport", 495 next = generic_dqe_head;
662 "MANIPULATE_DELAY_OUT", &delay)) && (delay.rel_value_us > 0)) 496 while (NULL != (dqe = next))
497 {
498 next = dqe->next;
499 if (0 == memcmp(peer, &dqe->id, sizeof(dqe->id)))
663 { 500 {
664 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 501 GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
665 "Delaying outbound traffic for %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); 502 generic_dqe_tail,
666 set_metric(&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DELAY, 503 dqe);
667 delay.rel_value_us); 504 if (NULL != dqe->cont)
505 dqe->cont (dqe->cont_cls,
506 GNUNET_SYSERR,
507 dqe->msg_size,
508 0);
509 GNUNET_free(dqe);
668 } 510 }
669 man_handle.peers = GNUNET_CONTAINER_multipeermap_create(10, GNUNET_NO); 511 }
512 if (NULL != generic_send_delay_task)
513 {
514 GNUNET_SCHEDULER_cancel (generic_send_delay_task);
515 generic_send_delay_task = NULL;
516 if (NULL != generic_dqe_head)
517 generic_send_delay_task
518 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at),
519 &send_delayed,
520 generic_dqe_head);
521 }
670} 522}
671 523
672 524
525/**
526 * Free manipulation information about a peer.
527 *
528 * @param cls NULL
529 * @param key peer the info is about
530 * @param value a `struct TM_Peer` to free
531 * @return #GNUNET_OK (continue to iterate)
532 */
673static int 533static int
674free_tmps (void *cls, 534free_tmps (void *cls,
675 const struct GNUNET_PeerIdentity *key, 535 const struct GNUNET_PeerIdentity *key,
@@ -678,13 +538,10 @@ free_tmps (void *cls,
678 struct TM_Peer *tmp = value; 538 struct TM_Peer *tmp = value;
679 struct DelayQueueEntry *dqe; 539 struct DelayQueueEntry *dqe;
680 540
681 if (NULL == tmp)
682 return GNUNET_OK;
683 GNUNET_break (GNUNET_YES == 541 GNUNET_break (GNUNET_YES ==
684 GNUNET_CONTAINER_multipeermap_remove (man_handle.peers, 542 GNUNET_CONTAINER_multipeermap_remove (peers,
685 key, 543 key,
686 value)); 544 value));
687 free_metric (tmp);
688 while (NULL != (dqe = tmp->send_head)) 545 while (NULL != (dqe = tmp->send_head))
689 { 546 {
690 GNUNET_CONTAINER_DLL_remove (tmp->send_head, 547 GNUNET_CONTAINER_DLL_remove (tmp->send_head,
@@ -699,89 +556,27 @@ free_tmps (void *cls,
699 } 556 }
700 if (NULL != tmp->send_delay_task) 557 if (NULL != tmp->send_delay_task)
701 { 558 {
702 GNUNET_SCHEDULER_cancel(tmp->send_delay_task); 559 GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
703 tmp->send_delay_task = NULL; 560 tmp->send_delay_task = NULL;
704 } 561 }
705 GNUNET_free(tmp); 562 GNUNET_free (tmp);
706 return GNUNET_OK; 563 return GNUNET_OK;
707} 564}
708 565
709 566
710/** 567/**
711 * Notify manipulation about disconnect so it can discard queued messages
712 *
713 * @param peer the disconnecting peer
714 */
715void
716GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
717{
718 struct TM_Peer *tmp;
719 struct DelayQueueEntry *dqe;
720 struct DelayQueueEntry *next;
721
722 if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, peer)))
723 {
724 while (NULL != (dqe = tmp->send_head))
725 {
726 GNUNET_CONTAINER_DLL_remove (tmp->send_head,
727 tmp->send_tail,
728 dqe);
729 if (NULL != dqe->cont)
730 dqe->cont (dqe->cont_cls,
731 GNUNET_SYSERR,
732 dqe->msg_size,
733 0);
734 GNUNET_free(dqe);
735 }
736 }
737 else if (UINT32_MAX != find_metric (&man_handle.general,
738 GNUNET_ATS_QUALITY_NET_DELAY,
739 TM_SEND))
740 {
741 next = generic_dqe_head;
742 while (NULL != (dqe = next))
743 {
744 next = dqe->next;
745 if (0 == memcmp(peer, &dqe->id, sizeof(dqe->id)))
746 {
747 GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
748 generic_dqe_tail,
749 dqe);
750 if (NULL != dqe->cont)
751 dqe->cont (dqe->cont_cls,
752 GNUNET_SYSERR,
753 dqe->msg_size,
754 0);
755 GNUNET_free(dqe);
756 }
757 }
758 if (NULL != generic_send_delay_task)
759 {
760 GNUNET_SCHEDULER_cancel (generic_send_delay_task);
761 generic_send_delay_task = NULL;
762 if (NULL != generic_dqe_head)
763 generic_send_delay_task
764 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at),
765 &send_delayed,
766 generic_dqe_head);
767 }
768 }
769}
770
771
772/**
773 * Stop traffic manipulation 568 * Stop traffic manipulation
774 */ 569 */
775void 570void
776GST_manipulation_stop() 571GST_manipulation_stop ()
777{ 572{
778 struct DelayQueueEntry *cur; 573 struct DelayQueueEntry *cur;
779 574
780 GNUNET_CONTAINER_multipeermap_iterate (man_handle.peers, 575 GNUNET_CONTAINER_multipeermap_iterate (peers,
781 &free_tmps, 576 &free_tmps,
782 NULL); 577 NULL);
783 GNUNET_CONTAINER_multipeermap_destroy (man_handle.peers); 578 GNUNET_CONTAINER_multipeermap_destroy (peers);
784 579 peers = NULL;
785 while (NULL != (cur = generic_dqe_head)) 580 while (NULL != (cur = generic_dqe_head))
786 { 581 {
787 GNUNET_CONTAINER_DLL_remove (generic_dqe_head, 582 GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
@@ -799,8 +594,6 @@ GST_manipulation_stop()
799 GNUNET_SCHEDULER_cancel (generic_send_delay_task); 594 GNUNET_SCHEDULER_cancel (generic_send_delay_task);
800 generic_send_delay_task = NULL; 595 generic_send_delay_task = NULL;
801 } 596 }
802 free_metric (&man_handle.general);
803 man_handle.peers = NULL;
804} 597}
805 598
806/* end of file gnunet-service-transport_manipulation.c */ 599/* end of file gnunet-service-transport_manipulation.c */