diff options
Diffstat (limited to 'src/transport/gnunet-transport.c')
-rw-r--r-- | src/transport/gnunet-transport.c | 1437 |
1 files changed, 0 insertions, 1437 deletions
diff --git a/src/transport/gnunet-transport.c b/src/transport/gnunet-transport.c deleted file mode 100644 index b5ad43770..000000000 --- a/src/transport/gnunet-transport.c +++ /dev/null | |||
@@ -1,1437 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011-2014, 2016, 2017 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 src/transport/gnunet-transport.c | ||
23 | * @brief Tool to help configure, measure and control the transport subsystem. | ||
24 | * @author Christian Grothoff | ||
25 | * @author Nathan Evans | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_resolver_service.h" | ||
30 | #include "gnunet_protocols.h" | ||
31 | #include "gnunet_transport_service.h" | ||
32 | |||
33 | /** | ||
34 | * Timeout for a name resolution | ||
35 | */ | ||
36 | #define RESOLUTION_TIMEOUT \ | ||
37 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
38 | |||
39 | /** | ||
40 | * Timeout for an operation | ||
41 | */ | ||
42 | #define OP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Context to store name resolutions for valiation | ||
47 | */ | ||
48 | struct ValidationResolutionContext | ||
49 | { | ||
50 | /** | ||
51 | * Next in DLL | ||
52 | */ | ||
53 | struct ValidationResolutionContext *next; | ||
54 | |||
55 | /** | ||
56 | * Previous in DLL | ||
57 | */ | ||
58 | struct ValidationResolutionContext *prev; | ||
59 | |||
60 | /** | ||
61 | * Address to resolve | ||
62 | */ | ||
63 | struct GNUNET_HELLO_Address *addrcp; | ||
64 | |||
65 | /** | ||
66 | * Time of last validation | ||
67 | */ | ||
68 | struct GNUNET_TIME_Absolute last_validation; | ||
69 | |||
70 | /** | ||
71 | * Address is valid until | ||
72 | */ | ||
73 | struct GNUNET_TIME_Absolute valid_until; | ||
74 | |||
75 | /** | ||
76 | * Time of next validation | ||
77 | */ | ||
78 | struct GNUNET_TIME_Absolute next_validation; | ||
79 | |||
80 | /** | ||
81 | * Transport conversion handle | ||
82 | */ | ||
83 | struct GNUNET_TRANSPORT_AddressToStringContext *asc; | ||
84 | |||
85 | /** | ||
86 | * plugin name | ||
87 | */ | ||
88 | char *transport; | ||
89 | |||
90 | /** | ||
91 | * was the entry printed | ||
92 | */ | ||
93 | int printed; | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * Struct to store information about peers in monitor mode | ||
98 | */ | ||
99 | struct MonitoredPeer | ||
100 | { | ||
101 | /** | ||
102 | * State of the peer | ||
103 | */ | ||
104 | enum GNUNET_TRANSPORT_PeerState state; | ||
105 | |||
106 | /** | ||
107 | * Timeout | ||
108 | */ | ||
109 | struct GNUNET_TIME_Absolute state_timeout; | ||
110 | |||
111 | /** | ||
112 | * The address to convert | ||
113 | */ | ||
114 | struct GNUNET_HELLO_Address *address; | ||
115 | }; | ||
116 | |||
117 | /** | ||
118 | * Context to store name resolutions for valiation | ||
119 | */ | ||
120 | struct PeerResolutionContext | ||
121 | { | ||
122 | /** | ||
123 | * Next in DLL | ||
124 | */ | ||
125 | struct PeerResolutionContext *next; | ||
126 | |||
127 | /** | ||
128 | * Prev in DLL | ||
129 | */ | ||
130 | struct PeerResolutionContext *prev; | ||
131 | |||
132 | /** | ||
133 | * address to resolve | ||
134 | */ | ||
135 | struct GNUNET_HELLO_Address *addrcp; | ||
136 | |||
137 | /** | ||
138 | * transport conversiion context | ||
139 | */ | ||
140 | struct GNUNET_TRANSPORT_AddressToStringContext *asc; | ||
141 | |||
142 | /** | ||
143 | * peer state | ||
144 | */ | ||
145 | enum GNUNET_TRANSPORT_PeerState state; | ||
146 | |||
147 | /** | ||
148 | * state timeout | ||
149 | */ | ||
150 | struct GNUNET_TIME_Absolute state_timeout; | ||
151 | |||
152 | /** | ||
153 | * transport plugin | ||
154 | */ | ||
155 | char *transport; | ||
156 | |||
157 | /** | ||
158 | * was the entry printed | ||
159 | */ | ||
160 | int printed; | ||
161 | }; | ||
162 | |||
163 | |||
164 | /** | ||
165 | * Benchmarking block size in KB | ||
166 | */ | ||
167 | #define BLOCKSIZE 4 | ||
168 | |||
169 | /** | ||
170 | * Handle to transport service. | ||
171 | */ | ||
172 | static struct GNUNET_TRANSPORT_CoreHandle *handle; | ||
173 | |||
174 | /** | ||
175 | * Configuration handle | ||
176 | */ | ||
177 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
178 | |||
179 | /** | ||
180 | * Blacklisting handle | ||
181 | */ | ||
182 | struct GNUNET_TRANSPORT_Blacklist *blacklist; | ||
183 | |||
184 | /** | ||
185 | * Option -s. | ||
186 | */ | ||
187 | static int benchmark_send; | ||
188 | |||
189 | /** | ||
190 | * Option -b. | ||
191 | */ | ||
192 | static int benchmark_receive; | ||
193 | |||
194 | /** | ||
195 | * Option -l. | ||
196 | */ | ||
197 | static int benchmark_receive; | ||
198 | |||
199 | /** | ||
200 | * Option -i. | ||
201 | */ | ||
202 | static int iterate_connections; | ||
203 | |||
204 | /** | ||
205 | * Option -a. | ||
206 | */ | ||
207 | static int iterate_all; | ||
208 | |||
209 | /** | ||
210 | * Option -c. | ||
211 | */ | ||
212 | static int monitor_connects; | ||
213 | |||
214 | /** | ||
215 | * Option -m. | ||
216 | */ | ||
217 | static int monitor_connections; | ||
218 | |||
219 | /** | ||
220 | * Option -P. | ||
221 | */ | ||
222 | static int monitor_plugins; | ||
223 | |||
224 | /** | ||
225 | * Option -D. | ||
226 | */ | ||
227 | static int do_disconnect; | ||
228 | |||
229 | /** | ||
230 | * Option -n. | ||
231 | */ | ||
232 | static int numeric; | ||
233 | |||
234 | /** | ||
235 | * Global return value (0 success). | ||
236 | */ | ||
237 | static int ret; | ||
238 | |||
239 | /** | ||
240 | * Current number of connections in monitor mode | ||
241 | */ | ||
242 | static int monitor_connect_counter; | ||
243 | |||
244 | /** | ||
245 | * Number of bytes of traffic we received so far. | ||
246 | */ | ||
247 | static unsigned long long traffic_received; | ||
248 | |||
249 | /** | ||
250 | * Number of bytes of traffic we sent so far. | ||
251 | */ | ||
252 | static unsigned long long traffic_sent; | ||
253 | |||
254 | /** | ||
255 | * Starting time of transmitting/receiving data. | ||
256 | */ | ||
257 | static struct GNUNET_TIME_Absolute start_time; | ||
258 | |||
259 | /** | ||
260 | * Map storing information about monitored peers | ||
261 | */ | ||
262 | static struct GNUNET_CONTAINER_MultiPeerMap *monitored_peers; | ||
263 | |||
264 | /** | ||
265 | * Map storing information about monitored plugins's sessions. | ||
266 | */ | ||
267 | static struct GNUNET_CONTAINER_MultiPeerMap *monitored_plugins; | ||
268 | |||
269 | /** | ||
270 | * Handle if we are monitoring peers at the transport level. | ||
271 | */ | ||
272 | static struct GNUNET_TRANSPORT_PeerMonitoringContext *pic; | ||
273 | |||
274 | /** | ||
275 | * Handle if we are monitoring plugin session activity. | ||
276 | */ | ||
277 | static struct GNUNET_TRANSPORT_PluginMonitor *pm; | ||
278 | |||
279 | /** | ||
280 | * Identity of the peer we transmit to / connect to. | ||
281 | * ('-p' command-line option). | ||
282 | */ | ||
283 | static struct GNUNET_PeerIdentity pid; | ||
284 | |||
285 | /** | ||
286 | * Task for operation timeout | ||
287 | */ | ||
288 | static struct GNUNET_SCHEDULER_Task *op_timeout; | ||
289 | |||
290 | /** | ||
291 | * Selected level of verbosity. | ||
292 | */ | ||
293 | static unsigned int verbosity; | ||
294 | |||
295 | /** | ||
296 | * Resolver process handle. | ||
297 | */ | ||
298 | struct GNUNET_OS_Process *resolver; | ||
299 | |||
300 | /** | ||
301 | * Number of address resolutions pending | ||
302 | */ | ||
303 | static unsigned int address_resolutions; | ||
304 | |||
305 | /** | ||
306 | * DLL: head of validation resolution entries | ||
307 | */ | ||
308 | static struct ValidationResolutionContext *vc_head; | ||
309 | |||
310 | /** | ||
311 | * DLL: tail of validation resolution entries | ||
312 | */ | ||
313 | static struct ValidationResolutionContext *vc_tail; | ||
314 | |||
315 | /** | ||
316 | * DLL: head of resolution entries | ||
317 | */ | ||
318 | static struct PeerResolutionContext *rc_head; | ||
319 | |||
320 | /** | ||
321 | * DLL: head of resolution entries | ||
322 | */ | ||
323 | static struct PeerResolutionContext *rc_tail; | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Function called to release data stored in the #monitored_peers map. | ||
328 | * | ||
329 | * @param cls unused | ||
330 | * @param key the peer identity | ||
331 | * @param value a `struct MonitoredPeer` to release | ||
332 | * @return #GNUNET_OK (continue to iterate) | ||
333 | */ | ||
334 | static int | ||
335 | destroy_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | ||
336 | { | ||
337 | struct MonitoredPeer *m = value; | ||
338 | |||
339 | GNUNET_assert ( | ||
340 | GNUNET_OK == | ||
341 | GNUNET_CONTAINER_multipeermap_remove (monitored_peers, key, value)); | ||
342 | GNUNET_free (m->address); | ||
343 | GNUNET_free (value); | ||
344 | return GNUNET_OK; | ||
345 | } | ||
346 | |||
347 | |||
348 | /** | ||
349 | * Task run in monitor mode when the user presses CTRL-C to abort. | ||
350 | * Stops monitoring activity. | ||
351 | * | ||
352 | * @param cls NULL | ||
353 | */ | ||
354 | static void | ||
355 | shutdown_task (void *cls) | ||
356 | { | ||
357 | struct GNUNET_TIME_Relative duration; | ||
358 | struct ValidationResolutionContext *cur; | ||
359 | struct ValidationResolutionContext *next; | ||
360 | struct PeerResolutionContext *rc; | ||
361 | |||
362 | if (NULL != op_timeout) | ||
363 | { | ||
364 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
365 | op_timeout = NULL; | ||
366 | } | ||
367 | if (NULL != pic) | ||
368 | { | ||
369 | GNUNET_TRANSPORT_monitor_peers_cancel (pic); | ||
370 | pic = NULL; | ||
371 | } | ||
372 | if (NULL != pm) | ||
373 | { | ||
374 | GNUNET_TRANSPORT_monitor_plugins_cancel (pm); | ||
375 | pm = NULL; | ||
376 | } | ||
377 | |||
378 | next = vc_head; | ||
379 | for (cur = next; NULL != cur; cur = next) | ||
380 | { | ||
381 | next = cur->next; | ||
382 | |||
383 | GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); | ||
384 | GNUNET_CONTAINER_DLL_remove (vc_head, vc_tail, cur); | ||
385 | GNUNET_free (cur->transport); | ||
386 | GNUNET_HELLO_address_free (cur->addrcp); | ||
387 | GNUNET_free (cur); | ||
388 | } | ||
389 | while (NULL != (rc = rc_head)) | ||
390 | { | ||
391 | GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, rc); | ||
392 | GNUNET_TRANSPORT_address_to_string_cancel (rc->asc); | ||
393 | GNUNET_free (rc->transport); | ||
394 | GNUNET_free (rc->addrcp); | ||
395 | GNUNET_free (rc); | ||
396 | } | ||
397 | if (NULL != handle) | ||
398 | { | ||
399 | GNUNET_TRANSPORT_core_disconnect (handle); | ||
400 | handle = NULL; | ||
401 | } | ||
402 | if (benchmark_send) | ||
403 | { | ||
404 | duration = GNUNET_TIME_absolute_get_duration (start_time); | ||
405 | fprintf (stdout, | ||
406 | _ ("Transmitted %llu bytes/s (%llu bytes in %s)\n"), | ||
407 | 1000LL * 1000LL * traffic_sent / (1 + duration.rel_value_us), | ||
408 | traffic_sent, | ||
409 | GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); | ||
410 | } | ||
411 | if (benchmark_receive) | ||
412 | { | ||
413 | duration = GNUNET_TIME_absolute_get_duration (start_time); | ||
414 | fprintf (stdout, | ||
415 | _ ("Received %llu bytes/s (%llu bytes in %s)\n"), | ||
416 | 1000LL * 1000LL * traffic_received / (1 + duration.rel_value_us), | ||
417 | traffic_received, | ||
418 | GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); | ||
419 | } | ||
420 | |||
421 | if (NULL != monitored_peers) | ||
422 | { | ||
423 | GNUNET_CONTAINER_multipeermap_iterate (monitored_peers, &destroy_it, NULL); | ||
424 | GNUNET_CONTAINER_multipeermap_destroy (monitored_peers); | ||
425 | monitored_peers = NULL; | ||
426 | } | ||
427 | if (NULL != monitored_plugins) | ||
428 | { | ||
429 | GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (monitored_plugins)); | ||
430 | GNUNET_CONTAINER_multipeermap_destroy (monitored_plugins); | ||
431 | monitored_plugins = NULL; | ||
432 | } | ||
433 | if (NULL != blacklist) | ||
434 | { | ||
435 | GNUNET_TRANSPORT_blacklist_cancel (blacklist); | ||
436 | blacklist = NULL; | ||
437 | ret = 0; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | |||
442 | /** | ||
443 | * We are done, shut down. | ||
444 | */ | ||
445 | static void | ||
446 | operation_timeout (void *cls) | ||
447 | { | ||
448 | struct PeerResolutionContext *cur; | ||
449 | struct PeerResolutionContext *next; | ||
450 | |||
451 | op_timeout = NULL; | ||
452 | if ((benchmark_send) || (benchmark_receive)) | ||
453 | { | ||
454 | fprintf (stdout, _ ("Failed to connect to `%s'\n"), GNUNET_i2s_full (&pid)); | ||
455 | GNUNET_SCHEDULER_shutdown (); | ||
456 | ret = 1; | ||
457 | return; | ||
458 | } | ||
459 | if (iterate_connections) | ||
460 | { | ||
461 | next = rc_head; | ||
462 | while (NULL != (cur = next)) | ||
463 | { | ||
464 | next = cur->next; | ||
465 | fprintf (stdout, | ||
466 | _ ("Failed to resolve address for peer `%s'\n"), | ||
467 | GNUNET_i2s (&cur->addrcp->peer)); | ||
468 | |||
469 | GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, cur); | ||
470 | GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); | ||
471 | GNUNET_free (cur->transport); | ||
472 | GNUNET_free (cur->addrcp); | ||
473 | GNUNET_free (cur); | ||
474 | } | ||
475 | fprintf (stdout, | ||
476 | "%s", | ||
477 | _ ("Failed to list connections, timeout occurred\n")); | ||
478 | GNUNET_SCHEDULER_shutdown (); | ||
479 | ret = 1; | ||
480 | return; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | |||
485 | /** | ||
486 | * Function called to notify a client about the socket | ||
487 | * begin ready to queue more data. Sends another message. | ||
488 | * | ||
489 | * @param cls closure with the message queue | ||
490 | */ | ||
491 | static void | ||
492 | do_send (void *cls) | ||
493 | { | ||
494 | struct GNUNET_MQ_Handle *mq = cls; | ||
495 | struct GNUNET_MessageHeader *m; | ||
496 | struct GNUNET_MQ_Envelope *env; | ||
497 | |||
498 | env = GNUNET_MQ_msg_extra (m, BLOCKSIZE * 1024, GNUNET_MESSAGE_TYPE_DUMMY); | ||
499 | memset (&m[1], 52, BLOCKSIZE * 1024 - sizeof(struct GNUNET_MessageHeader)); | ||
500 | traffic_sent += BLOCKSIZE * 1024; | ||
501 | GNUNET_MQ_notify_sent (env, &do_send, mq); | ||
502 | if (verbosity > 0) | ||
503 | fprintf (stdout, | ||
504 | _ ("Transmitting %u bytes\n"), | ||
505 | (unsigned int) BLOCKSIZE * 1024); | ||
506 | GNUNET_MQ_send (mq, env); | ||
507 | } | ||
508 | |||
509 | |||
510 | /** | ||
511 | * Function called to notify transport users that another | ||
512 | * peer connected to us. | ||
513 | * | ||
514 | * @param cls closure | ||
515 | * @param peer the peer that connected | ||
516 | * @param mq message queue for sending to @a peer | ||
517 | */ | ||
518 | static void * | ||
519 | notify_connect (void *cls, | ||
520 | const struct GNUNET_PeerIdentity *peer, | ||
521 | struct GNUNET_MQ_Handle *mq) | ||
522 | { | ||
523 | if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity))) | ||
524 | return NULL; | ||
525 | ret = 0; | ||
526 | if (! benchmark_send) | ||
527 | return NULL; | ||
528 | if (NULL != op_timeout) | ||
529 | { | ||
530 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
531 | op_timeout = NULL; | ||
532 | } | ||
533 | if (verbosity > 0) | ||
534 | fprintf ( | ||
535 | stdout, | ||
536 | _ ( | ||
537 | "Successfully connected to `%s', starting to send benchmark data in %u Kb blocks\n"), | ||
538 | GNUNET_i2s (peer), | ||
539 | BLOCKSIZE); | ||
540 | start_time = GNUNET_TIME_absolute_get (); | ||
541 | do_send (mq); | ||
542 | return mq; | ||
543 | } | ||
544 | |||
545 | |||
546 | /** | ||
547 | * Function called to notify transport users that another | ||
548 | * peer disconnected from us. | ||
549 | * | ||
550 | * @param cls closure | ||
551 | * @param peer the peer that disconnected | ||
552 | * @param internal_cls what we returned from #notify_connect() | ||
553 | */ | ||
554 | static void | ||
555 | notify_disconnect (void *cls, | ||
556 | const struct GNUNET_PeerIdentity *peer, | ||
557 | void *internal_cls) | ||
558 | { | ||
559 | if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity))) | ||
560 | return; | ||
561 | if (NULL == internal_cls) | ||
562 | return; /* not about target peer */ | ||
563 | if (! benchmark_send) | ||
564 | return; /* not transmitting */ | ||
565 | fprintf (stdout, | ||
566 | _ ("Disconnected from peer `%s' while benchmarking\n"), | ||
567 | GNUNET_i2s (&pid)); | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
572 | * Function called to notify transport users that another | ||
573 | * peer connected to us. | ||
574 | * | ||
575 | * @param cls closure | ||
576 | * @param peer the peer that connected | ||
577 | * @param mq for sending messages to @a peer | ||
578 | * @return NULL | ||
579 | */ | ||
580 | static void * | ||
581 | monitor_notify_connect (void *cls, | ||
582 | const struct GNUNET_PeerIdentity *peer, | ||
583 | struct GNUNET_MQ_Handle *mq) | ||
584 | { | ||
585 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
586 | const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now); | ||
587 | |||
588 | monitor_connect_counter++; | ||
589 | fprintf (stdout, | ||
590 | _ ("%24s: %-17s %4s (%u connections in total)\n"), | ||
591 | now_str, | ||
592 | _ ("Connected to"), | ||
593 | GNUNET_i2s (peer), | ||
594 | monitor_connect_counter); | ||
595 | return NULL; | ||
596 | } | ||
597 | |||
598 | |||
599 | /** | ||
600 | * Function called to notify transport users that another | ||
601 | * peer disconnected from us. | ||
602 | * | ||
603 | * @param cls closure | ||
604 | * @param peer the peer that disconnected | ||
605 | * @param internal_cls what we returned from #monitor_notify_connect() | ||
606 | */ | ||
607 | static void | ||
608 | monitor_notify_disconnect (void *cls, | ||
609 | const struct GNUNET_PeerIdentity *peer, | ||
610 | void *internal_cls) | ||
611 | { | ||
612 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
613 | const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now); | ||
614 | |||
615 | GNUNET_assert (monitor_connect_counter > 0); | ||
616 | monitor_connect_counter--; | ||
617 | |||
618 | fprintf (stdout, | ||
619 | _ ("%24s: %-17s %4s (%u connections in total)\n"), | ||
620 | now_str, | ||
621 | _ ("Disconnected from"), | ||
622 | GNUNET_i2s (peer), | ||
623 | monitor_connect_counter); | ||
624 | } | ||
625 | |||
626 | |||
627 | /** | ||
628 | * Function called by the transport for each received message. | ||
629 | * | ||
630 | * @param cls closure | ||
631 | * @param message the message | ||
632 | * @return #GNUNET_OK | ||
633 | */ | ||
634 | static int | ||
635 | check_dummy (void *cls, const struct GNUNET_MessageHeader *message) | ||
636 | { | ||
637 | return GNUNET_OK; /* all messages are fine */ | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Function called by the transport for each received message. | ||
643 | * | ||
644 | * @param cls closure | ||
645 | * @param message the message | ||
646 | */ | ||
647 | static void | ||
648 | handle_dummy (void *cls, const struct GNUNET_MessageHeader *message) | ||
649 | { | ||
650 | if (! benchmark_receive) | ||
651 | return; | ||
652 | if (verbosity > 0) | ||
653 | fprintf (stdout, | ||
654 | _ ("Received %u bytes\n"), | ||
655 | (unsigned int) ntohs (message->size)); | ||
656 | if (0 == traffic_received) | ||
657 | start_time = GNUNET_TIME_absolute_get (); | ||
658 | traffic_received += ntohs (message->size); | ||
659 | } | ||
660 | |||
661 | |||
662 | /** | ||
663 | * Convert address to a printable format. | ||
664 | * | ||
665 | * @param address the address | ||
666 | * @param numeric #GNUNET_YES to convert to numeric format, #GNUNET_NO | ||
667 | * to try to use reverse DNS | ||
668 | * @param state state the peer is in | ||
669 | * @param state_timeout when will the peer's state expire | ||
670 | */ | ||
671 | static void | ||
672 | resolve_peer_address (const struct GNUNET_HELLO_Address *address, | ||
673 | int numeric, | ||
674 | enum GNUNET_TRANSPORT_PeerState state, | ||
675 | struct GNUNET_TIME_Absolute state_timeout); | ||
676 | |||
677 | |||
678 | static void | ||
679 | print_info (const struct GNUNET_PeerIdentity *id, | ||
680 | const char *transport, | ||
681 | const char *addr, | ||
682 | enum GNUNET_TRANSPORT_PeerState state, | ||
683 | struct GNUNET_TIME_Absolute state_timeout) | ||
684 | { | ||
685 | if (((GNUNET_YES == iterate_connections) && (GNUNET_YES == iterate_all)) || | ||
686 | (GNUNET_YES == monitor_connections)) | ||
687 | { | ||
688 | fprintf (stdout, | ||
689 | _ ("Peer `%s': %s %s in state `%s' until %s\n"), | ||
690 | GNUNET_i2s (id), | ||
691 | (NULL == transport) ? "<none>" : transport, | ||
692 | (NULL == transport) ? "<none>" : addr, | ||
693 | GNUNET_TRANSPORT_ps2s (state), | ||
694 | GNUNET_STRINGS_absolute_time_to_string (state_timeout)); | ||
695 | } | ||
696 | else if ((GNUNET_YES == iterate_connections) && | ||
697 | (GNUNET_TRANSPORT_is_connected (state))) | ||
698 | { | ||
699 | /* Only connected peers, skip state */ | ||
700 | fprintf (stdout, | ||
701 | _ ("Peer `%s': %s %s\n"), | ||
702 | GNUNET_i2s (id), | ||
703 | transport, | ||
704 | addr); | ||
705 | } | ||
706 | } | ||
707 | |||
708 | |||
709 | /** | ||
710 | * Function called with a textual representation of an address. This | ||
711 | * function will be called several times with different possible | ||
712 | * textual representations, and a last time with @a address being NULL | ||
713 | * to signal the end of the iteration. Note that @a address NULL | ||
714 | * always is the last call, regardless of the value in @a res. | ||
715 | * | ||
716 | * @param cls closure | ||
717 | * @param address NULL on end of iteration, | ||
718 | * otherwise 0-terminated printable UTF-8 string, | ||
719 | * in particular an empty string if @a res is #GNUNET_NO | ||
720 | * @param res result of the address to string conversion: | ||
721 | * if #GNUNET_OK: conversion successful | ||
722 | * if #GNUNET_NO: address was invalid (or not supported) | ||
723 | * if #GNUNET_SYSERR: communication error (IPC error) | ||
724 | */ | ||
725 | static void | ||
726 | process_peer_string (void *cls, const char *address, int res) | ||
727 | { | ||
728 | struct PeerResolutionContext *rc = cls; | ||
729 | |||
730 | if (NULL != address) | ||
731 | { | ||
732 | if (GNUNET_SYSERR == res) | ||
733 | { | ||
734 | fprintf ( | ||
735 | stderr, | ||
736 | "Failed to convert address for peer `%s' plugin `%s' length %u to string \n", | ||
737 | GNUNET_i2s (&rc->addrcp->peer), | ||
738 | rc->addrcp->transport_name, | ||
739 | (unsigned int) rc->addrcp->address_length); | ||
740 | print_info (&rc->addrcp->peer, | ||
741 | rc->transport, | ||
742 | NULL, | ||
743 | rc->state, | ||
744 | rc->state_timeout); | ||
745 | rc->printed = GNUNET_YES; | ||
746 | return; | ||
747 | } | ||
748 | if (GNUNET_OK == res) | ||
749 | { | ||
750 | print_info (&rc->addrcp->peer, | ||
751 | rc->transport, | ||
752 | address, | ||
753 | rc->state, | ||
754 | rc->state_timeout); | ||
755 | rc->printed = GNUNET_YES; | ||
756 | return; /* Wait for done call */ | ||
757 | } | ||
758 | /* GNUNET_NO == res: ignore, was simply not supported */ | ||
759 | return; | ||
760 | } | ||
761 | /* NULL == address, last call, we are done */ | ||
762 | |||
763 | rc->asc = NULL; | ||
764 | GNUNET_assert (address_resolutions > 0); | ||
765 | address_resolutions--; | ||
766 | if (GNUNET_NO == rc->printed) | ||
767 | { | ||
768 | if (numeric == GNUNET_NO) | ||
769 | { | ||
770 | /* Failed to resolve address, try numeric lookup | ||
771 | (note: this should not be needed, as transport | ||
772 | should fallback to numeric conversion if DNS takes | ||
773 | too long) */ | ||
774 | resolve_peer_address (rc->addrcp, | ||
775 | GNUNET_YES, | ||
776 | rc->state, | ||
777 | rc->state_timeout); | ||
778 | } | ||
779 | else | ||
780 | { | ||
781 | print_info (&rc->addrcp->peer, | ||
782 | rc->transport, | ||
783 | NULL, | ||
784 | rc->state, | ||
785 | rc->state_timeout); | ||
786 | } | ||
787 | } | ||
788 | GNUNET_free (rc->transport); | ||
789 | GNUNET_free (rc->addrcp); | ||
790 | GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, rc); | ||
791 | GNUNET_free (rc); | ||
792 | if ((0 == address_resolutions) && (iterate_connections)) | ||
793 | { | ||
794 | if (NULL != op_timeout) | ||
795 | { | ||
796 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
797 | op_timeout = NULL; | ||
798 | } | ||
799 | ret = 0; | ||
800 | GNUNET_SCHEDULER_shutdown (); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | |||
805 | /** | ||
806 | * Convert address to a printable format and print it | ||
807 | * together with the given state data. | ||
808 | * | ||
809 | * @param address the address | ||
810 | * @param numeric #GNUNET_YES to convert to numeric format, #GNUNET_NO | ||
811 | * to try to use reverse DNS | ||
812 | * @param state state the peer is in | ||
813 | * @param state_timeout when will the peer's state expire | ||
814 | */ | ||
815 | static void | ||
816 | resolve_peer_address (const struct GNUNET_HELLO_Address *address, | ||
817 | int numeric, | ||
818 | enum GNUNET_TRANSPORT_PeerState state, | ||
819 | struct GNUNET_TIME_Absolute state_timeout) | ||
820 | { | ||
821 | struct PeerResolutionContext *rc; | ||
822 | |||
823 | rc = GNUNET_new (struct PeerResolutionContext); | ||
824 | GNUNET_CONTAINER_DLL_insert (rc_head, rc_tail, rc); | ||
825 | address_resolutions++; | ||
826 | rc->transport = GNUNET_strdup (address->transport_name); | ||
827 | rc->addrcp = GNUNET_HELLO_address_copy (address); | ||
828 | rc->printed = GNUNET_NO; | ||
829 | rc->state = state; | ||
830 | rc->state_timeout = state_timeout; | ||
831 | /* Resolve address to string */ | ||
832 | rc->asc = GNUNET_TRANSPORT_address_to_string (cfg, | ||
833 | address, | ||
834 | numeric, | ||
835 | RESOLUTION_TIMEOUT, | ||
836 | &process_peer_string, | ||
837 | rc); | ||
838 | } | ||
839 | |||
840 | |||
841 | /** | ||
842 | * Function called with information about a peers during a one shot iteration | ||
843 | * | ||
844 | * @param cls closure | ||
845 | * @param peer identity of the peer, NULL for final callback when operation done | ||
846 | * @param address binary address used to communicate with this peer, | ||
847 | * NULL on disconnect or when done | ||
848 | * @param state current state this peer is in | ||
849 | * @param state_timeout time out for the current state | ||
850 | */ | ||
851 | static void | ||
852 | process_peer_iteration_cb (void *cls, | ||
853 | const struct GNUNET_PeerIdentity *peer, | ||
854 | const struct GNUNET_HELLO_Address *address, | ||
855 | enum GNUNET_TRANSPORT_PeerState state, | ||
856 | struct GNUNET_TIME_Absolute state_timeout) | ||
857 | { | ||
858 | if (NULL == peer) | ||
859 | { | ||
860 | /* done */ | ||
861 | pic = NULL; | ||
862 | return; | ||
863 | } | ||
864 | |||
865 | if ((GNUNET_NO == iterate_all) && | ||
866 | (GNUNET_NO == GNUNET_TRANSPORT_is_connected (state))) | ||
867 | return; /* Display only connected peers */ | ||
868 | |||
869 | if (NULL != op_timeout) | ||
870 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
871 | op_timeout = | ||
872 | GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL); | ||
873 | |||
874 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
875 | "Received address for peer `%s': %s\n", | ||
876 | GNUNET_i2s (peer), | ||
877 | address ? address->transport_name : ""); | ||
878 | |||
879 | if (NULL != address) | ||
880 | resolve_peer_address (address, numeric, state, state_timeout); | ||
881 | else | ||
882 | print_info (peer, NULL, NULL, state, state_timeout); | ||
883 | } | ||
884 | |||
885 | |||
886 | /** | ||
887 | * Context for address resolution by #plugin_monitoring_cb(). | ||
888 | */ | ||
889 | struct PluginMonitorAddress | ||
890 | { | ||
891 | /** | ||
892 | * Ongoing resolution request. | ||
893 | */ | ||
894 | struct GNUNET_TRANSPORT_AddressToStringContext *asc; | ||
895 | |||
896 | /** | ||
897 | * Resolved address as string. | ||
898 | */ | ||
899 | char *str; | ||
900 | |||
901 | /** | ||
902 | * Last event we got and did not yet print because | ||
903 | * @e str was NULL (address not yet resolved). | ||
904 | */ | ||
905 | struct GNUNET_TRANSPORT_SessionInfo si; | ||
906 | }; | ||
907 | |||
908 | |||
909 | /** | ||
910 | * Print information about a plugin monitoring event. | ||
911 | * | ||
912 | * @param addr out internal context | ||
913 | * @param info the monitoring information | ||
914 | */ | ||
915 | static void | ||
916 | print_plugin_event_info (struct PluginMonitorAddress *addr, | ||
917 | const struct GNUNET_TRANSPORT_SessionInfo *info) | ||
918 | { | ||
919 | const char *state; | ||
920 | |||
921 | switch (info->state) | ||
922 | { | ||
923 | case GNUNET_TRANSPORT_SS_INIT: | ||
924 | state = "INIT"; | ||
925 | break; | ||
926 | |||
927 | case GNUNET_TRANSPORT_SS_HANDSHAKE: | ||
928 | state = "HANDSHAKE"; | ||
929 | break; | ||
930 | |||
931 | case GNUNET_TRANSPORT_SS_UP: | ||
932 | state = "UP"; | ||
933 | break; | ||
934 | |||
935 | case GNUNET_TRANSPORT_SS_UPDATE: | ||
936 | state = "UPDATE"; | ||
937 | break; | ||
938 | |||
939 | case GNUNET_TRANSPORT_SS_DONE: | ||
940 | state = "DONE"; | ||
941 | break; | ||
942 | |||
943 | default: | ||
944 | state = "UNKNOWN"; | ||
945 | break; | ||
946 | } | ||
947 | fprintf (stdout, | ||
948 | "%s: state %s timeout in %s @ %s%s\n", | ||
949 | GNUNET_i2s (&info->address->peer), | ||
950 | state, | ||
951 | GNUNET_STRINGS_relative_time_to_string ( | ||
952 | GNUNET_TIME_absolute_get_remaining (info->session_timeout), | ||
953 | GNUNET_YES), | ||
954 | addr->str, | ||
955 | (info->is_inbound == GNUNET_YES) ? " (INBOUND)" : ""); | ||
956 | fprintf (stdout, | ||
957 | "%s: queue has %3u messages and %6u bytes\n", | ||
958 | GNUNET_i2s (&info->address->peer), | ||
959 | info->num_msg_pending, | ||
960 | info->num_bytes_pending); | ||
961 | if (0 != | ||
962 | GNUNET_TIME_absolute_get_remaining (info->receive_delay).rel_value_us) | ||
963 | fprintf (stdout, | ||
964 | "%s: receiving blocked until %s\n", | ||
965 | GNUNET_i2s (&info->address->peer), | ||
966 | GNUNET_STRINGS_absolute_time_to_string (info->receive_delay)); | ||
967 | } | ||
968 | |||
969 | |||
970 | /** | ||
971 | * Function called with a textual representation of an address. This | ||
972 | * function will be called several times with different possible | ||
973 | * textual representations, and a last time with @a address being NULL | ||
974 | * to signal the end of the iteration. Note that @a address NULL | ||
975 | * always is the last call, regardless of the value in @a res. | ||
976 | * | ||
977 | * @param cls closure | ||
978 | * @param address NULL on end of iteration, | ||
979 | * otherwise 0-terminated printable UTF-8 string, | ||
980 | * in particular an empty string if @a res is #GNUNET_NO | ||
981 | * @param res result of the address to string conversion: | ||
982 | * if #GNUNET_OK: conversion successful | ||
983 | * if #GNUNET_NO: address was invalid (or not supported) | ||
984 | * if #GNUNET_SYSERR: communication error (IPC error) | ||
985 | */ | ||
986 | static void | ||
987 | address_cb (void *cls, const char *address, int res) | ||
988 | { | ||
989 | struct PluginMonitorAddress *addr = cls; | ||
990 | |||
991 | if (NULL == address) | ||
992 | { | ||
993 | addr->asc = NULL; | ||
994 | return; | ||
995 | } | ||
996 | if (NULL != addr->str) | ||
997 | return; | ||
998 | addr->str = GNUNET_strdup (address); | ||
999 | print_plugin_event_info (addr, &addr->si); | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /** | ||
1004 | * Function called by the plugin with information about the | ||
1005 | * current sessions managed by the plugin (for monitoring). | ||
1006 | * | ||
1007 | * @param cls closure (NULL) | ||
1008 | * @param session session handle this information is about, | ||
1009 | * NULL to indicate that we are "in sync" (initial | ||
1010 | * iteration complete) | ||
1011 | * @param session_ctx storage location where the application | ||
1012 | * can store data; will point to NULL on #GNUNET_TRANSPORT_SS_INIT, | ||
1013 | * and must be reset to NULL on #GNUNET_TRANSPORT_SS_DONE | ||
1014 | * @param info information about the state of the session, | ||
1015 | * NULL if @a session is also NULL and we are | ||
1016 | * merely signalling that the initial iteration is over; | ||
1017 | * NULL with @a session being non-NULL if the monitor | ||
1018 | * was being cancelled while sessions were active | ||
1019 | */ | ||
1020 | static void | ||
1021 | plugin_monitoring_cb (void *cls, | ||
1022 | struct GNUNET_TRANSPORT_PluginSession *session, | ||
1023 | void **session_ctx, | ||
1024 | const struct GNUNET_TRANSPORT_SessionInfo *info) | ||
1025 | { | ||
1026 | struct PluginMonitorAddress *addr; | ||
1027 | |||
1028 | if ((NULL == info) && (NULL == session)) | ||
1029 | return; /* in sync with transport service */ | ||
1030 | addr = *session_ctx; | ||
1031 | if (NULL == info) | ||
1032 | { | ||
1033 | if (NULL != addr) | ||
1034 | { | ||
1035 | if (NULL != addr->asc) | ||
1036 | { | ||
1037 | GNUNET_TRANSPORT_address_to_string_cancel (addr->asc); | ||
1038 | addr->asc = NULL; | ||
1039 | } | ||
1040 | GNUNET_free (addr->str); | ||
1041 | GNUNET_free (addr); | ||
1042 | *session_ctx = NULL; | ||
1043 | } | ||
1044 | return; /* shutdown */ | ||
1045 | } | ||
1046 | if (0 != | ||
1047 | memcmp (&info->address->peer, &pid, sizeof(struct GNUNET_PeerIdentity))) | ||
1048 | return; /* filtered */ | ||
1049 | if (NULL == addr) | ||
1050 | { | ||
1051 | addr = GNUNET_new (struct PluginMonitorAddress); | ||
1052 | addr->asc = | ||
1053 | GNUNET_TRANSPORT_address_to_string (cfg, | ||
1054 | info->address, | ||
1055 | numeric, | ||
1056 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1057 | &address_cb, | ||
1058 | addr); | ||
1059 | *session_ctx = addr; | ||
1060 | } | ||
1061 | if (NULL == addr->str) | ||
1062 | addr->si = *info; | ||
1063 | else | ||
1064 | print_plugin_event_info (addr, info); | ||
1065 | if (GNUNET_TRANSPORT_SS_DONE == info->state) | ||
1066 | { | ||
1067 | if (NULL != addr->asc) | ||
1068 | { | ||
1069 | GNUNET_TRANSPORT_address_to_string_cancel (addr->asc); | ||
1070 | addr->asc = NULL; | ||
1071 | } | ||
1072 | GNUNET_free (addr->str); | ||
1073 | GNUNET_free (addr); | ||
1074 | *session_ctx = NULL; | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /** | ||
1080 | * Function called with information about a peers | ||
1081 | * | ||
1082 | * @param cls closure, NULL | ||
1083 | * @param peer identity of the peer, NULL for final callback when operation done | ||
1084 | * @param address binary address used to communicate with this peer, | ||
1085 | * NULL on disconnect or when done | ||
1086 | * @param state current state this peer is in | ||
1087 | * @param state_timeout time out for the current state | ||
1088 | */ | ||
1089 | static void | ||
1090 | process_peer_monitoring_cb (void *cls, | ||
1091 | const struct GNUNET_PeerIdentity *peer, | ||
1092 | const struct GNUNET_HELLO_Address *address, | ||
1093 | enum GNUNET_TRANSPORT_PeerState state, | ||
1094 | struct GNUNET_TIME_Absolute state_timeout) | ||
1095 | { | ||
1096 | struct MonitoredPeer *m; | ||
1097 | |||
1098 | if (NULL == peer) | ||
1099 | { | ||
1100 | fprintf (stdout, | ||
1101 | "%s", | ||
1102 | _ ( | ||
1103 | "Monitor disconnected from transport service. Reconnecting.\n")); | ||
1104 | return; | ||
1105 | } | ||
1106 | |||
1107 | if (NULL != op_timeout) | ||
1108 | GNUNET_SCHEDULER_cancel (op_timeout); | ||
1109 | op_timeout = | ||
1110 | GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL); | ||
1111 | |||
1112 | if (NULL == (m = GNUNET_CONTAINER_multipeermap_get (monitored_peers, peer))) | ||
1113 | { | ||
1114 | m = GNUNET_new (struct MonitoredPeer); | ||
1115 | GNUNET_CONTAINER_multipeermap_put ( | ||
1116 | monitored_peers, | ||
1117 | peer, | ||
1118 | m, | ||
1119 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1120 | } | ||
1121 | else | ||
1122 | { | ||
1123 | if ((m->state == state) && | ||
1124 | (m->state_timeout.abs_value_us == state_timeout.abs_value_us) && | ||
1125 | (NULL == address) && (NULL == m->address)) | ||
1126 | { | ||
1127 | return; /* No real change */ | ||
1128 | } | ||
1129 | if ((m->state == state) && (NULL != address) && (NULL != m->address) && | ||
1130 | (0 == GNUNET_HELLO_address_cmp (m->address, address))) | ||
1131 | return; /* No real change */ | ||
1132 | } | ||
1133 | |||
1134 | if (NULL != m->address) | ||
1135 | { | ||
1136 | GNUNET_free (m->address); | ||
1137 | m->address = NULL; | ||
1138 | } | ||
1139 | if (NULL != address) | ||
1140 | m->address = GNUNET_HELLO_address_copy (address); | ||
1141 | m->state = state; | ||
1142 | m->state_timeout = state_timeout; | ||
1143 | |||
1144 | if (NULL != address) | ||
1145 | resolve_peer_address (m->address, numeric, m->state, m->state_timeout); | ||
1146 | else | ||
1147 | print_info (peer, NULL, NULL, m->state, m->state_timeout); | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | /** | ||
1152 | * Function called with the transport service checking if we | ||
1153 | * want to blacklist a peer. Return #GNUNET_SYSERR for the | ||
1154 | * peer that we should disconnect from. | ||
1155 | * | ||
1156 | * @param cls NULL | ||
1157 | * @param cpid peer to check blacklisting for | ||
1158 | * @return #GNUNET_OK if the connection is allowed, #GNUNET_SYSERR if not | ||
1159 | */ | ||
1160 | static int | ||
1161 | blacklist_cb (void *cls, const struct GNUNET_PeerIdentity *cpid) | ||
1162 | { | ||
1163 | if (0 == memcmp (cpid, &pid, sizeof(struct GNUNET_PeerIdentity))) | ||
1164 | return GNUNET_SYSERR; | ||
1165 | return GNUNET_OK; | ||
1166 | } | ||
1167 | |||
1168 | |||
1169 | /** | ||
1170 | * Main function that will be run by the scheduler. | ||
1171 | * | ||
1172 | * @param cls closure | ||
1173 | * @param args remaining command-line arguments | ||
1174 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1175 | * @param mycfg configuration | ||
1176 | */ | ||
1177 | static void | ||
1178 | run (void *cls, | ||
1179 | char *const *args, | ||
1180 | const char *cfgfile, | ||
1181 | const struct GNUNET_CONFIGURATION_Handle *mycfg) | ||
1182 | { | ||
1183 | static struct GNUNET_PeerIdentity zero_pid; | ||
1184 | int counter = 0; | ||
1185 | |||
1186 | ret = 1; | ||
1187 | |||
1188 | cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; | ||
1189 | |||
1190 | counter = benchmark_send + benchmark_receive + iterate_connections | ||
1191 | + monitor_connections + monitor_connects + do_disconnect | ||
1192 | + monitor_plugins; | ||
1193 | |||
1194 | if (1 < counter) | ||
1195 | { | ||
1196 | fprintf ( | ||
1197 | stderr, | ||
1198 | _ ( | ||
1199 | "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, %s, %s %s\n"), | ||
1200 | "disconnect", | ||
1201 | "benchmark send", | ||
1202 | "benchmark receive", | ||
1203 | "information", | ||
1204 | "monitor", | ||
1205 | "events", | ||
1206 | "plugins"); | ||
1207 | return; | ||
1208 | } | ||
1209 | if (0 == counter) | ||
1210 | { | ||
1211 | fprintf ( | ||
1212 | stderr, | ||
1213 | _ ( | ||
1214 | "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s, %s\n"), | ||
1215 | "disconnect", | ||
1216 | "benchmark send", | ||
1217 | "benchmark receive", | ||
1218 | "information", | ||
1219 | "monitor", | ||
1220 | "events", | ||
1221 | "plugins"); | ||
1222 | return; | ||
1223 | } | ||
1224 | |||
1225 | if (do_disconnect) /* -D: Disconnect from peer */ | ||
1226 | { | ||
1227 | if (0 == memcmp (&zero_pid, &pid, sizeof(pid))) | ||
1228 | { | ||
1229 | fprintf (stderr, | ||
1230 | _ ("Option `%s' makes no sense without option `%s'.\n"), | ||
1231 | "-D", | ||
1232 | "-p"); | ||
1233 | ret = 1; | ||
1234 | return; | ||
1235 | } | ||
1236 | blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_cb, NULL); | ||
1237 | if (NULL == blacklist) | ||
1238 | { | ||
1239 | fprintf (stderr, | ||
1240 | "%s", | ||
1241 | _ ( | ||
1242 | "Failed to connect to transport service for disconnection\n")); | ||
1243 | ret = 1; | ||
1244 | return; | ||
1245 | } | ||
1246 | fprintf (stdout, | ||
1247 | "%s", | ||
1248 | _ ("Blacklisting request in place, stop with CTRL-C\n")); | ||
1249 | } | ||
1250 | else if (benchmark_send) /* -s: Benchmark sending */ | ||
1251 | { | ||
1252 | if (0 == memcmp (&zero_pid, &pid, sizeof(pid))) | ||
1253 | { | ||
1254 | fprintf (stderr, | ||
1255 | _ ("Option `%s' makes no sense without option `%s'.\n"), | ||
1256 | "-s", | ||
1257 | "-p"); | ||
1258 | ret = 1; | ||
1259 | return; | ||
1260 | } | ||
1261 | handle = GNUNET_TRANSPORT_core_connect (cfg, | ||
1262 | NULL, | ||
1263 | NULL, | ||
1264 | NULL, | ||
1265 | ¬ify_connect, | ||
1266 | ¬ify_disconnect, | ||
1267 | NULL); | ||
1268 | if (NULL == handle) | ||
1269 | { | ||
1270 | fprintf (stderr, "%s", _ ("Failed to connect to transport service\n")); | ||
1271 | ret = 1; | ||
1272 | return; | ||
1273 | } | ||
1274 | start_time = GNUNET_TIME_absolute_get (); | ||
1275 | op_timeout = | ||
1276 | GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL); | ||
1277 | } | ||
1278 | else if (benchmark_receive) /* -b: Benchmark receiving */ | ||
1279 | { | ||
1280 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
1281 | { GNUNET_MQ_hd_var_size (dummy, | ||
1282 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
1283 | struct GNUNET_MessageHeader, | ||
1284 | NULL), | ||
1285 | GNUNET_MQ_handler_end () }; | ||
1286 | |||
1287 | handle = GNUNET_TRANSPORT_core_connect (cfg, | ||
1288 | NULL, | ||
1289 | handlers, | ||
1290 | NULL, | ||
1291 | NULL, | ||
1292 | NULL, | ||
1293 | NULL); | ||
1294 | if (NULL == handle) | ||
1295 | { | ||
1296 | fprintf (stderr, "%s", _ ("Failed to connect to transport service\n")); | ||
1297 | ret = 1; | ||
1298 | return; | ||
1299 | } | ||
1300 | if (verbosity > 0) | ||
1301 | fprintf (stdout, "%s", _ ("Starting to receive benchmark data\n")); | ||
1302 | start_time = GNUNET_TIME_absolute_get (); | ||
1303 | } | ||
1304 | else if (iterate_connections) /* -i: List information about peers once */ | ||
1305 | { | ||
1306 | pic = GNUNET_TRANSPORT_monitor_peers (cfg, | ||
1307 | &pid, | ||
1308 | GNUNET_YES, | ||
1309 | &process_peer_iteration_cb, | ||
1310 | (void *) cfg); | ||
1311 | op_timeout = | ||
1312 | GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL); | ||
1313 | } | ||
1314 | else if (monitor_connections) /* -m: List information about peers continuously | ||
1315 | */ | ||
1316 | { | ||
1317 | monitored_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
1318 | pic = GNUNET_TRANSPORT_monitor_peers (cfg, | ||
1319 | &pid, | ||
1320 | GNUNET_NO, | ||
1321 | &process_peer_monitoring_cb, | ||
1322 | NULL); | ||
1323 | } | ||
1324 | else if (monitor_plugins) /* -P: List information about plugins continuously | ||
1325 | */ | ||
1326 | { | ||
1327 | monitored_plugins = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
1328 | pm = GNUNET_TRANSPORT_monitor_plugins (cfg, &plugin_monitoring_cb, NULL); | ||
1329 | } | ||
1330 | else if (monitor_connects) /* -e : Monitor (dis)connect events continuously */ | ||
1331 | { | ||
1332 | monitor_connect_counter = 0; | ||
1333 | handle = GNUNET_TRANSPORT_core_connect (cfg, | ||
1334 | NULL, | ||
1335 | NULL, | ||
1336 | NULL, | ||
1337 | &monitor_notify_connect, | ||
1338 | &monitor_notify_disconnect, | ||
1339 | NULL); | ||
1340 | if (NULL == handle) | ||
1341 | { | ||
1342 | fprintf (stderr, "%s", _ ("Failed to connect to transport service\n")); | ||
1343 | ret = 1; | ||
1344 | return; | ||
1345 | } | ||
1346 | ret = 0; | ||
1347 | } | ||
1348 | else | ||
1349 | { | ||
1350 | GNUNET_break (0); | ||
1351 | return; | ||
1352 | } | ||
1353 | |||
1354 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
1355 | } | ||
1356 | |||
1357 | |||
1358 | int | ||
1359 | main (int argc, char *const *argv) | ||
1360 | { | ||
1361 | int res; | ||
1362 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
1363 | { GNUNET_GETOPT_option_flag ( | ||
1364 | 'a', | ||
1365 | "all", | ||
1366 | gettext_noop ( | ||
1367 | "print information for all peers (instead of only connected peers)"), | ||
1368 | &iterate_all), | ||
1369 | GNUNET_GETOPT_option_flag ( | ||
1370 | 'b', | ||
1371 | "benchmark", | ||
1372 | gettext_noop ( | ||
1373 | "measure how fast we are receiving data from all peers (until CTRL-C)"), | ||
1374 | &benchmark_receive), | ||
1375 | GNUNET_GETOPT_option_flag ('D', | ||
1376 | "disconnect", | ||
1377 | gettext_noop ("disconnect from a peer"), | ||
1378 | &do_disconnect), | ||
1379 | GNUNET_GETOPT_option_flag ( | ||
1380 | 'i', | ||
1381 | "information", | ||
1382 | gettext_noop ( | ||
1383 | "provide information about all current connections (once)"), | ||
1384 | &iterate_connections), | ||
1385 | GNUNET_GETOPT_option_flag ( | ||
1386 | 'm', | ||
1387 | "monitor", | ||
1388 | gettext_noop ( | ||
1389 | "provide information about all current connections (continuously)"), | ||
1390 | &monitor_connections), | ||
1391 | GNUNET_GETOPT_option_flag ( | ||
1392 | 'e', | ||
1393 | "events", | ||
1394 | gettext_noop ( | ||
1395 | "provide information about all connects and disconnect events (continuously)"), | ||
1396 | &monitor_connects), | ||
1397 | GNUNET_GETOPT_option_flag ('n', | ||
1398 | "numeric", | ||
1399 | gettext_noop ("do not resolve hostnames"), | ||
1400 | &numeric), | ||
1401 | GNUNET_GETOPT_option_base32_auto ('p', | ||
1402 | "peer", | ||
1403 | "PEER", | ||
1404 | gettext_noop ("peer identity"), | ||
1405 | &pid), | ||
1406 | GNUNET_GETOPT_option_flag ('P', | ||
1407 | "plugins", | ||
1408 | gettext_noop ("monitor plugin sessions"), | ||
1409 | &monitor_plugins), | ||
1410 | GNUNET_GETOPT_option_flag ( | ||
1411 | 's', | ||
1412 | "send", | ||
1413 | gettext_noop ( | ||
1414 | "send data for benchmarking to the other peer (until CTRL-C)"), | ||
1415 | &benchmark_send), | ||
1416 | GNUNET_GETOPT_option_verbose (&verbosity), | ||
1417 | GNUNET_GETOPT_OPTION_END }; | ||
1418 | |||
1419 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
1420 | return 2; | ||
1421 | |||
1422 | res = | ||
1423 | GNUNET_PROGRAM_run (argc, | ||
1424 | argv, | ||
1425 | "gnunet-transport", | ||
1426 | gettext_noop ("Direct access to transport service."), | ||
1427 | options, | ||
1428 | &run, | ||
1429 | NULL); | ||
1430 | GNUNET_free_nz ((void *) argv); | ||
1431 | if (GNUNET_OK == res) | ||
1432 | return ret; | ||
1433 | return 1; | ||
1434 | } | ||
1435 | |||
1436 | |||
1437 | /* end of gnunet-transport.c */ | ||