diff options
Diffstat (limited to 'src/transport/gnunet-service-transport_manipulation.c')
-rw-r--r-- | src/transport/gnunet-service-transport_manipulation.c | 586 |
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 | */ | ||
39 | struct 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 | */ | ||
81 | struct 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 | */ | ||
140 | static struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
141 | |||
142 | /** | ||
143 | * Inbound delay to apply to all peers. | ||
144 | */ | ||
145 | static struct GNUNET_TIME_Relative delay_in; | ||
146 | |||
147 | /** | ||
148 | * Outbound delay to apply to all peers. | ||
149 | */ | ||
150 | static struct GNUNET_TIME_Relative delay_out; | ||
151 | |||
152 | /** | ||
153 | * DLL head for delayed messages based on general delay | ||
154 | */ | ||
155 | static struct DelayQueueEntry *generic_dqe_head; | ||
156 | |||
157 | /** | ||
158 | * DLL tail for delayed messages based on general delay | ||
159 | */ | ||
160 | static struct DelayQueueEntry *generic_dqe_tail; | ||
161 | |||
162 | /** | ||
163 | * Task to schedule delayed sending based on general delay | ||
164 | */ | ||
165 | static struct GNUNET_SCHEDULER_Task *generic_send_delay_task; | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Set traffic metric to manipulate | ||
170 | * | ||
171 | * @param message containing information | ||
172 | */ | ||
173 | void | ||
174 | GST_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 | */ | ||
216 | static void | ||
217 | send_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 | */ | ||
277 | void | ||
278 | GST_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 | */ | ||
354 | void | ||
355 | GST_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 | */ | ||
379 | struct GNUNET_TIME_Relative | ||
380 | GST_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 | */ | ||
414 | void | ||
415 | GST_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 | */ | ||
455 | void | ||
456 | GST_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 | */ | ||
519 | static int | ||
520 | free_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 | */ | ||
556 | void | ||
557 | GST_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 */ | ||