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.c586
1 files changed, 0 insertions, 586 deletions
diff --git a/src/transport/gnunet-service-transport_manipulation.c b/src/transport/gnunet-service-transport_manipulation.c
deleted file mode 100644
index 04d1774c0..000000000
--- a/src/transport/gnunet-service-transport_manipulation.c
+++ /dev/null
@@ -1,586 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
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_hello.h"
29#include "gnunet-service-transport_neighbours.h"
30#include "gnunet-service-transport_plugins.h"
31#include "gnunet-service-transport_validation.h"
32#include "gnunet-service-transport.h"
33#include "transport.h"
34
35
36/**
37 * Struct containing information about manipulations to a specific peer
38 */
39struct TM_Peer
40{
41 /**
42 * Peer ID
43 */
44 struct GNUNET_PeerIdentity peer;
45
46 /**
47 * How long to delay incoming messages for this peer.
48 */
49 struct GNUNET_TIME_Relative delay_in;
50
51 /**
52 * How long to delay outgoing messages for this peer.
53 */
54 struct GNUNET_TIME_Relative delay_out;
55
56 /**
57 * Manipulated properties to use for this peer.
58 */
59 struct GNUNET_ATS_Properties properties;
60
61 /**
62 * Task to schedule delayed sendding
63 */
64 struct GNUNET_SCHEDULER_Task *send_delay_task;
65
66 /**
67 * Send queue DLL head
68 */
69 struct DelayQueueEntry *send_head;
70
71 /**
72 * Send queue DLL tail
73 */
74 struct DelayQueueEntry *send_tail;
75};
76
77
78/**
79 * Entry in the delay queue for an outbound delayed message
80 */
81struct DelayQueueEntry
82{
83 /**
84 * Next in DLL
85 */
86 struct DelayQueueEntry *prev;
87
88 /**
89 * Previous in DLL
90 */
91 struct DelayQueueEntry *next;
92
93 /**
94 * Peer this entry is belonging to if (NULL == tmp): enqueued in
95 * generic DLL and scheduled by generic_send_delay_task else:
96 * enqueued in tmp->send_head and tmp->send_tail and scheduled by
97 * tmp->send_delay_task
98 */
99 struct TM_Peer *tmp;
100
101 /**
102 * Peer ID
103 */
104 struct GNUNET_PeerIdentity id;
105
106 /**
107 * Absolute time when to send
108 */
109 struct GNUNET_TIME_Absolute sent_at;
110
111 /**
112 * The message
113 */
114 void *msg;
115
116 /**
117 * The message size
118 */
119 size_t msg_size;
120
121 /**
122 * Message timeout
123 */
124 struct GNUNET_TIME_Relative timeout;
125
126 /**
127 * Transports send continuation
128 */
129 GST_NeighbourSendContinuation cont;
130
131 /**
132 * Transports send continuation cls
133 */
134 void *cont_cls;
135};
136
137/**
138 * Hashmap contain all peers currently manipulated
139 */
140static struct GNUNET_CONTAINER_MultiPeerMap *peers;
141
142/**
143 * Inbound delay to apply to all peers.
144 */
145static struct GNUNET_TIME_Relative delay_in;
146
147/**
148 * Outbound delay to apply to all peers.
149 */
150static struct GNUNET_TIME_Relative delay_out;
151
152/**
153 * DLL head for delayed messages based on general delay
154 */
155static struct DelayQueueEntry *generic_dqe_head;
156
157/**
158 * DLL tail for delayed messages based on general delay
159 */
160static struct DelayQueueEntry *generic_dqe_tail;
161
162/**
163 * Task to schedule delayed sending based on general delay
164 */
165static struct GNUNET_SCHEDULER_Task *generic_send_delay_task;
166
167
168/**
169 * Set traffic metric to manipulate
170 *
171 * @param message containing information
172 */
173void
174GST_manipulation_set_metric (const struct TrafficMetricMessage *tm)
175{
176 static struct GNUNET_PeerIdentity zero;
177 struct TM_Peer *tmp;
178
179 if (0 == memcmp (&tm->peer,
180 &zero,
181 sizeof(struct GNUNET_PeerIdentity)))
182 {
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "Received traffic metrics for all peers\n");
185 delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in);
186 delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out);
187 return;
188 }
189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
190 "Received traffic metrics for peer `%s'\n",
191 GNUNET_i2s (&tm->peer));
192 if (NULL ==
193 (tmp = GNUNET_CONTAINER_multipeermap_get (peers,
194 &tm->peer)))
195 {
196 tmp = GNUNET_new (struct TM_Peer);
197 tmp->peer = tm->peer;
198 GNUNET_CONTAINER_multipeermap_put (peers,
199 &tm->peer,
200 tmp,
201 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
202 }
203 GNUNET_ATS_properties_ntoh (&tmp->properties,
204 &tm->properties);
205 tmp->delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in);
206 tmp->delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out);
207}
208
209
210/**
211 * We have delayed transmission, now it is time to send the
212 * message.
213 *
214 * @param cls the `struct DelayQueueEntry` to transmit
215 */
216static void
217send_delayed (void *cls)
218{
219 struct DelayQueueEntry *dqe = cls;
220 struct DelayQueueEntry *next;
221 struct TM_Peer *tmp = dqe->tmp;
222
223 GNUNET_break (GNUNET_YES ==
224 GST_neighbours_test_connected (&dqe->id));
225 if (NULL != tmp)
226 {
227 tmp->send_delay_task = NULL;
228 GNUNET_CONTAINER_DLL_remove (tmp->send_head,
229 tmp->send_tail,
230 dqe);
231 next = tmp->send_head;
232 if (NULL != next)
233 {
234 /* More delayed messages */
235 tmp->send_delay_task = GNUNET_SCHEDULER_add_at (next->sent_at,
236 &send_delayed,
237 next);
238 }
239 }
240 else
241 {
242 /* Remove from generic queue */
243 generic_send_delay_task = NULL;
244 GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
245 generic_dqe_tail,
246 dqe);
247 next = generic_dqe_head;
248 if (NULL != next)
249 {
250 /* More delayed messages */
251 generic_send_delay_task = GNUNET_SCHEDULER_add_at (next->sent_at,
252 &send_delayed,
253 next);
254 }
255 }
256 GST_neighbours_send (&dqe->id,
257 dqe->msg,
258 dqe->msg_size,
259 dqe->timeout,
260 dqe->cont,
261 dqe->cont_cls);
262 GNUNET_free (dqe);
263}
264
265
266/**
267 * Adapter function between transport's send function and transport plugins.
268 * Delays message transmission if an artificial delay is configured.
269 *
270 * @param target the peer the message to send to
271 * @param msg the message received
272 * @param msg_size message size
273 * @param timeout timeout
274 * @param cont the continuation to call after sending
275 * @param cont_cls cls for @a cont
276 */
277void
278GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
279 const void *msg,
280 size_t msg_size,
281 struct GNUNET_TIME_Relative timeout,
282 GST_NeighbourSendContinuation cont,
283 void *cont_cls)
284{
285 struct TM_Peer *tmp;
286 struct DelayQueueEntry *dqe;
287 struct GNUNET_TIME_Relative delay;
288
289 if (NULL != (tmp =
290 GNUNET_CONTAINER_multipeermap_get (peers,
291 target)))
292 delay = tmp->delay_out;
293 else
294 delay = delay_out;
295 if (0 == delay.rel_value_us)
296 {
297 /* Normal sending */
298 GST_neighbours_send (target,
299 msg,
300 msg_size,
301 timeout,
302 cont, cont_cls);
303 return;
304 }
305 dqe = GNUNET_malloc (sizeof(struct DelayQueueEntry) + msg_size);
306 dqe->id = *target;
307 dqe->tmp = tmp;
308 dqe->sent_at = GNUNET_TIME_relative_to_absolute (delay);
309 dqe->cont = cont;
310 dqe->cont_cls = cont_cls;
311 dqe->msg = &dqe[1];
312 dqe->msg_size = msg_size;
313 dqe->timeout = timeout;
314 GNUNET_memcpy (dqe->msg,
315 msg,
316 msg_size);
317 if (NULL == tmp)
318 {
319 GNUNET_CONTAINER_DLL_insert_tail (generic_dqe_head,
320 generic_dqe_tail,
321 dqe);
322 if (NULL == generic_send_delay_task)
323 generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
324 &send_delayed,
325 dqe);
326 }
327 else
328 {
329 GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head,
330 tmp->send_tail,
331 dqe);
332 if (NULL == tmp->send_delay_task)
333 tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
334 &send_delayed,
335 dqe);
336 }
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Delaying %u byte message to peer `%s' with peer specific delay for %s\n",
339 (unsigned int) msg_size,
340 GNUNET_i2s (target),
341 GNUNET_STRINGS_relative_time_to_string (delay,
342 GNUNET_YES));
343}
344
345
346/**
347 * Function that will be called to manipulate ATS information according to
348 * current manipulation settings
349 *
350 * @param address binary address
351 * @param session the session
352 * @param prop[IN|OUT] metrics to modify
353 */
354void
355GST_manipulation_manipulate_metrics (const struct GNUNET_HELLO_Address *address,
356 struct GNUNET_ATS_Session *session,
357 struct GNUNET_ATS_Properties *prop)
358{
359 const struct GNUNET_PeerIdentity *peer = &address->peer;
360 struct TM_Peer *tmp;
361
362 tmp = GNUNET_CONTAINER_multipeermap_get (peers,
363 peer);
364 if (NULL != tmp)
365 *prop = tmp->properties;
366}
367
368
369/**
370 * Adapter function between transport plugins and transport receive function
371 * manipulation delays for next send.
372 *
373 * @param cls the closure for transport
374 * @param address the address and the peer the message was received from
375 * @param message the message received
376 * @param session the session the message was received on
377 * @return manipulated delay for next receive
378 */
379struct GNUNET_TIME_Relative
380GST_manipulation_recv (void *cls,
381 const struct GNUNET_HELLO_Address *address,
382 struct GNUNET_ATS_Session *session,
383 const struct GNUNET_MessageHeader *message)
384{
385 struct TM_Peer *tmp;
386 struct GNUNET_TIME_Relative quota_delay;
387 struct GNUNET_TIME_Relative m_delay;
388
389 if (NULL !=
390 (tmp = GNUNET_CONTAINER_multipeermap_get (peers,
391 &address->peer)))
392 m_delay = tmp->delay_in;
393 else
394 m_delay = delay_in;
395
396 quota_delay = GST_receive_callback (cls,
397 address,
398 session,
399 message);
400 m_delay = GNUNET_TIME_relative_max (m_delay,
401 quota_delay);
402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
403 "Delaying next receive for peer `%s' for %s\n",
404 GNUNET_i2s (&address->peer),
405 GNUNET_STRINGS_relative_time_to_string (m_delay,
406 GNUNET_YES));
407 return m_delay;
408}
409
410
411/**
412 * Initialize traffic manipulation
413 */
414void
415GST_manipulation_init ()
416{
417 struct GNUNET_TIME_Relative delay;
418
419 if ((GNUNET_OK ==
420 GNUNET_CONFIGURATION_get_value_time (GST_cfg,
421 "transport",
422 "MANIPULATE_DELAY_IN",
423 &delay)) &&
424 (delay.rel_value_us > 0))
425 {
426 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
427 "Delaying inbound traffic for %s\n",
428 GNUNET_STRINGS_relative_time_to_string (delay,
429 GNUNET_YES));
430 delay_in = delay;
431 }
432 if ((GNUNET_OK ==
433 GNUNET_CONFIGURATION_get_value_time (GST_cfg,
434 "transport",
435 "MANIPULATE_DELAY_OUT",
436 &delay)) &&
437 (delay.rel_value_us > 0))
438 {
439 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
440 "Delaying outbound traffic for %s\n",
441 GNUNET_STRINGS_relative_time_to_string (delay,
442 GNUNET_YES));
443 delay_out = delay;
444 }
445 peers = GNUNET_CONTAINER_multipeermap_create (4,
446 GNUNET_NO);
447}
448
449
450/**
451 * Notify manipulation about disconnect so it can discard queued messages
452 *
453 * @param peer the disconnecting peer
454 */
455void
456GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
457{
458 struct TM_Peer *tmp;
459 struct DelayQueueEntry *dqe;
460 struct DelayQueueEntry *next;
461
462 tmp = GNUNET_CONTAINER_multipeermap_get (peers,
463 peer);
464 if (NULL != tmp)
465 {
466 while (NULL != (dqe = tmp->send_head))
467 {
468 GNUNET_CONTAINER_DLL_remove (tmp->send_head,
469 tmp->send_tail,
470 dqe);
471 if (NULL != dqe->cont)
472 dqe->cont (dqe->cont_cls,
473 GNUNET_SYSERR,
474 dqe->msg_size,
475 0);
476 GNUNET_free (dqe);
477 }
478 }
479 next = generic_dqe_head;
480 while (NULL != (dqe = next))
481 {
482 next = dqe->next;
483 if (0 == memcmp (peer,
484 &dqe->id,
485 sizeof(dqe->id)))
486 {
487 GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
488 generic_dqe_tail,
489 dqe);
490 if (NULL != dqe->cont)
491 dqe->cont (dqe->cont_cls,
492 GNUNET_SYSERR,
493 dqe->msg_size,
494 0);
495 GNUNET_free (dqe);
496 }
497 }
498 if (NULL != generic_send_delay_task)
499 {
500 GNUNET_SCHEDULER_cancel (generic_send_delay_task);
501 generic_send_delay_task = NULL;
502 if (NULL != generic_dqe_head)
503 generic_send_delay_task
504 = GNUNET_SCHEDULER_add_at (generic_dqe_head->sent_at,
505 &send_delayed,
506 generic_dqe_head);
507 }
508}
509
510
511/**
512 * Free manipulation information about a peer.
513 *
514 * @param cls NULL
515 * @param key peer the info is about
516 * @param value a `struct TM_Peer` to free
517 * @return #GNUNET_OK (continue to iterate)
518 */
519static int
520free_tmps (void *cls,
521 const struct GNUNET_PeerIdentity *key,
522 void *value)
523{
524 struct TM_Peer *tmp = value;
525 struct DelayQueueEntry *dqe;
526
527 GNUNET_break (GNUNET_YES ==
528 GNUNET_CONTAINER_multipeermap_remove (peers,
529 key,
530 value));
531 while (NULL != (dqe = tmp->send_head))
532 {
533 GNUNET_CONTAINER_DLL_remove (tmp->send_head,
534 tmp->send_tail,
535 dqe);
536 if (NULL != dqe->cont)
537 dqe->cont (dqe->cont_cls,
538 GNUNET_SYSERR,
539 dqe->msg_size,
540 0);
541 GNUNET_free (dqe);
542 }
543 if (NULL != tmp->send_delay_task)
544 {
545 GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
546 tmp->send_delay_task = NULL;
547 }
548 GNUNET_free (tmp);
549 return GNUNET_OK;
550}
551
552
553/**
554 * Stop traffic manipulation
555 */
556void
557GST_manipulation_stop ()
558{
559 struct DelayQueueEntry *cur;
560
561 GNUNET_CONTAINER_multipeermap_iterate (peers,
562 &free_tmps,
563 NULL);
564 GNUNET_CONTAINER_multipeermap_destroy (peers);
565 peers = NULL;
566 while (NULL != (cur = generic_dqe_head))
567 {
568 GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
569 generic_dqe_tail,
570 cur);
571 if (NULL != cur->cont)
572 cur->cont (cur->cont_cls,
573 GNUNET_SYSERR,
574 cur->msg_size,
575 0);
576 GNUNET_free (cur);
577 }
578 if (NULL != generic_send_delay_task)
579 {
580 GNUNET_SCHEDULER_cancel (generic_send_delay_task);
581 generic_send_delay_task = NULL;
582 }
583}
584
585
586/* end of file gnunet-service-transport_manipulation.c */