2 This file is part of GNUnet.
3 Copyright (C) 2012, 2017 GNUnet e.V.
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.
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.
17 * @file cadet/gnunet-cadet.c
18 * @brief Print information about cadet tunnels and peers.
19 * @author Bartlomiej Polot
20 * @author Christian Grothoff
23 #include "gnunet_util_lib.h"
24 #include "gnunet_cadet_service.h"
31 static int request_peers;
41 static int request_tunnels;
46 static char *tunnel_id;
56 static char *channel_id;
59 * Port to listen on (-o).
61 static char *listen_port;
64 * Request echo service
69 * Request a debug dump
74 * Time of last echo request.
76 static struct GNUNET_TIME_Absolute echo_time;
79 * Task for next echo request.
81 static struct GNUNET_SCHEDULER_Task *echo_task;
86 static char *target_id;
91 static char *target_port = "default";
96 static struct GNUNET_CADET_Handle *mh;
101 static struct GNUNET_CADET_Channel *ch;
104 * HashCode of the given port string
106 static struct GNUNET_HashCode porthash;
109 * Data structure for ongoing reception of incoming virtual circuits.
111 struct GNUNET_CADET_Port *lp;
114 * Task for reading from stdin.
116 static struct GNUNET_SCHEDULER_Task *rd_task;
121 static struct GNUNET_SCHEDULER_Task *job;
125 * Wait for input on STDIO and send it out over the #ch.
132 * Convert encryption status to human readable string.
134 * @param status Encryption status.
136 * @return Human readable string.
139 enc_2s (uint16_t status)
158 * Convert connection status to human readable string.
160 * @param status Connection status.
162 * @return Human readable string.
165 conn_2s (uint16_t status)
187 * Task to shut down this application.
189 * @param cls Closure (unused).
192 shutdown_task (void *cls)
194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
198 GNUNET_CADET_channel_destroy (ch);
203 GNUNET_CADET_disconnect (mh);
208 GNUNET_SCHEDULER_cancel (rd_task);
211 if (NULL != echo_task)
213 GNUNET_SCHEDULER_cancel (echo_task);
218 GNUNET_SCHEDULER_cancel (job);
225 * Task run in stdio mode, after some data is available at stdin.
227 * @param cls Closure (unused).
230 read_stdio (void *cls)
232 struct GNUNET_MQ_Envelope *env;
233 struct GNUNET_MessageHeader *msg;
243 GNUNET_SCHEDULER_shutdown();
246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
247 "Read %u bytes from stdio\n",
248 (unsigned int) data_size);
249 env = GNUNET_MQ_msg_extra (msg,
251 GNUNET_MESSAGE_TYPE_CADET_CLI);
252 GNUNET_memcpy (&msg[1],
255 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
257 if (GNUNET_NO == echo)
263 echo_time = GNUNET_TIME_absolute_get ();
269 * Wait for input on STDIO and send it out over the #ch.
274 struct GNUNET_NETWORK_FDSet *rs;
276 /* FIXME: why use 'rs' here, seems overly complicated... */
277 rs = GNUNET_NETWORK_fdset_create ();
278 GNUNET_NETWORK_fdset_set_native (rs,
280 rd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
281 GNUNET_TIME_UNIT_FOREVER_REL,
286 GNUNET_NETWORK_fdset_destroy (rs);
291 * Function called whenever a channel is destroyed. Should clean up
292 * any associated state.
294 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
297 * @param channel connection to the other end (henceforth invalid)
300 channel_ended (void *cls,
301 const struct GNUNET_CADET_Channel *channel)
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
305 GNUNET_assert (channel == ch);
307 GNUNET_SCHEDULER_shutdown ();
312 * Method called whenever another peer has added us to a channel
313 * the other peer initiated.
314 * Only called (once) upon reception of data with a message type which was
315 * subscribed to in #GNUNET_CADET_connect.
317 * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored.
318 * In this case the handler MUST return NULL.
321 * @param channel new handle to the channel
322 * @param initiator peer that started the channel
323 * @return initial channel context for the channel, we use @a channel
326 channel_incoming (void *cls,
327 struct GNUNET_CADET_Channel *channel,
328 const struct GNUNET_PeerIdentity *initiator)
330 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
331 "Incoming connection from %s\n",
332 GNUNET_i2s_full (initiator));
333 GNUNET_assert (NULL == ch);
334 GNUNET_assert (NULL != lp);
335 GNUNET_CADET_close_port (lp);
338 if (GNUNET_NO == echo)
345 * @brief Send an echo request to the remote peer.
347 * @param cls Closure (NULL).
350 send_echo (void *cls)
352 struct GNUNET_MQ_Envelope *env;
353 struct GNUNET_MessageHeader *msg;
358 env = GNUNET_MQ_msg (msg,
359 GNUNET_MESSAGE_TYPE_CADET_CLI);
360 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
366 * Call CADET's monitor API, request debug dump on the service.
368 * @param cls Closure (unused).
371 request_dump (void *cls)
373 GNUNET_CADET_request_dump (mh);
374 GNUNET_SCHEDULER_shutdown ();
379 * Check data message sanity. Does nothing so far (all messages are OK).
381 * @param cls Closure (unused).
382 * @param message The message to check.
383 * @return #GNUNET_OK to keep the channel open,
384 * #GNUNET_SYSERR to close it (signal serious error).
387 check_data (void *cls,
388 const struct GNUNET_MessageHeader *message)
390 return GNUNET_OK; /* all is well-formed */
395 * Function called whenever a message is received.
397 * Each time the function must call #GNUNET_CADET_receive_done on the channel
398 * in order to receive the next message. This doesn't need to be immediate:
399 * can be delayed if some processing is done on the message.
402 * @param message The actual message.
405 handle_data (void *cls,
406 const struct GNUNET_MessageHeader *message)
408 size_t payload_size = ntohs (message->size) - sizeof (*message);
414 GNUNET_CADET_receive_done (ch);
415 if (GNUNET_YES == echo)
417 if (NULL != listen_port)
419 struct GNUNET_MQ_Envelope *env;
420 struct GNUNET_MessageHeader *msg;
422 env = GNUNET_MQ_msg_extra (msg,
424 GNUNET_MESSAGE_TYPE_CADET_CLI);
425 GNUNET_memcpy (&msg[1],
428 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
434 struct GNUNET_TIME_Relative latency;
436 latency = GNUNET_TIME_absolute_get_duration (echo_time);
437 echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
438 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
440 GNUNET_STRINGS_relative_time_to_string (latency,
442 echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
448 len = ntohs (message->size) - sizeof (*message);
449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
452 buf = (const char *) &message[1];
462 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
464 GNUNET_SCHEDULER_shutdown ();
473 * Method called to retrieve information about all peers in CADET, called
476 * After last peer has been reported, an additional call with NULL is done.
478 * @param cls Closure.
479 * @param peer Peer, or NULL on "EOF".
480 * @param tunnel Do we have a tunnel towards this peer?
481 * @param n_paths Number of known paths towards this peer.
482 * @param best_path How long is the best path?
483 * (0 = unknown, 1 = ourselves, 2 = neighbor)
486 peers_callback (void *cls,
487 const struct GNUNET_PeerIdentity *peer,
489 unsigned int n_paths,
490 unsigned int best_path)
494 GNUNET_SCHEDULER_shutdown();
498 "%s tunnel: %c, paths: %u\n",
499 GNUNET_i2s_full (peer),
506 * Method called to retrieve information about a specific peer
507 * known to the service.
509 * @param cls Closure.
510 * @param peer Peer ID.
511 * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO
512 * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO
513 * @param n_paths Number of paths known towards peer.
514 * @param paths Array of PEER_IDs representing all paths to reach the peer.
515 * Each path starts with the local peer.
516 * Each path ends with the destination peer (given in @c peer).
519 peer_callback (void *cls,
520 const struct GNUNET_PeerIdentity *peer,
523 unsigned int n_paths,
524 const struct GNUNET_PeerIdentity *paths)
527 const struct GNUNET_PeerIdentity *p;
530 "%s [TUNNEL: %s, NEIGHBOR: %s, PATHS: %u]\n",
531 GNUNET_i2s_full (peer),
533 neighbor ? "Y" : "N",
536 for (i = 0; i < n_paths && NULL != p;)
545 FPRINTF (stdout, "\n");
551 GNUNET_SCHEDULER_shutdown();
556 * Method called to retrieve information about all tunnels in CADET.
558 * @param cls Closure.
559 * @param peer Destination peer.
560 * @param channels Number of channels.
561 * @param connections Number of connections.
562 * @param estate Encryption state.
563 * @param cstate Connectivity state.
566 tunnels_callback (void *cls,
567 const struct GNUNET_PeerIdentity *peer,
568 unsigned int channels,
569 unsigned int connections,
575 GNUNET_SCHEDULER_shutdown();
579 "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n",
580 GNUNET_i2s_full (peer),
589 * Method called to retrieve information about a specific tunnel the cadet peer
590 * has established, o`r is trying to establish.
592 * @param cls Closure.
593 * @param peer Peer towards whom the tunnel is directed.
594 * @param n_channels Number of channels.
595 * @param n_connections Number of connections.
596 * @param channels Channels.
597 * @param connections Connections.
598 * @param estate Encryption status.
599 * @param cstate Connectivity status.
602 tunnel_callback (void *cls,
603 const struct GNUNET_PeerIdentity *peer,
604 unsigned int n_channels,
605 unsigned int n_connections,
606 const struct GNUNET_CADET_ChannelTunnelNumber *channels,
607 const struct GNUNET_CADET_ConnectionTunnelIdentifier *connections,
615 FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer));
616 FPRINTF (stdout, "\t%u channels\n", n_channels);
617 for (i = 0; i < n_channels; i++)
618 FPRINTF (stdout, "\t\t%X\n", ntohl (channels[i].cn));
619 FPRINTF (stdout, "\t%u connections\n", n_connections);
620 for (i = 0; i < n_connections; i++)
621 FPRINTF (stdout, "\t\t%s\n", GNUNET_sh2s (&connections[i].connection_of_tunnel));
622 FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate));
623 FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate));
625 GNUNET_SCHEDULER_shutdown ();
630 * Call CADET's meta API, get all peers known to a peer.
632 * @param cls Closure (unused).
635 get_peers (void *cls)
638 GNUNET_CADET_get_peers (mh, &peers_callback, NULL);
643 * Call CADET's monitor API, get info of one peer.
645 * @param cls Closure (unused).
648 show_peer (void *cls)
650 struct GNUNET_PeerIdentity pid;
654 GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
659 _("Invalid peer ID `%s'\n"),
661 GNUNET_SCHEDULER_shutdown();
664 GNUNET_CADET_get_peer (mh, &pid, peer_callback, NULL);
669 * Call CADET's meta API, get all tunnels known to a peer.
671 * @param cls Closure (unused).
674 get_tunnels (void *cls)
677 GNUNET_CADET_get_tunnels (mh, &tunnels_callback, NULL);
682 * Call CADET's monitor API, get info of one tunnel.
684 * @param cls Closure (unused).
687 show_tunnel (void *cls)
689 struct GNUNET_PeerIdentity pid;
693 GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id,
698 _("Invalid tunnel owner `%s'\n"),
700 GNUNET_SCHEDULER_shutdown ();
703 GNUNET_CADET_get_tunnel (mh,
711 * Call CADET's monitor API, get info of one channel.
713 * @param cls Closure (unused).
716 show_channel (void *cls)
724 * Call CADET's monitor API, get info of one connection.
726 * @param cls Closure (unused).
729 show_connection (void *cls)
737 * Main function that will be run by the scheduler.
740 * @param args remaining command-line arguments
741 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
742 * @param cfg configuration
748 const struct GNUNET_CONFIGURATION_Handle *cfg)
750 struct GNUNET_MQ_MessageHandler handlers[] = {
751 GNUNET_MQ_hd_var_size (data,
752 GNUNET_MESSAGE_TYPE_CADET_CLI,
753 struct GNUNET_MessageHeader,
755 GNUNET_MQ_handler_end ()
758 /* FIXME add option to monitor apps */
761 if (target_id && args[1])
762 target_port = args[1];
764 if ( (0 != (request_peers | request_tunnels)
767 || NULL != channel_id)
768 && target_id != NULL)
771 _("Extra arguments are not applicable "
772 "in combination with this option.\n"));
776 if (GNUNET_YES == dump)
778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
779 "Requesting debug dump\n");
780 job = GNUNET_SCHEDULER_add_now (&request_dump,
783 else if (NULL != peer_id)
785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
787 job = GNUNET_SCHEDULER_add_now (&show_peer,
790 else if (NULL != tunnel_id)
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
794 job = GNUNET_SCHEDULER_add_now (&show_tunnel,
797 else if (NULL != channel_id)
799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
801 job = GNUNET_SCHEDULER_add_now (&show_channel,
804 else if (NULL != conn_id)
806 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
807 "Show connection\n");
808 job = GNUNET_SCHEDULER_add_now (&show_connection,
811 else if (GNUNET_YES == request_peers)
813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815 job = GNUNET_SCHEDULER_add_now (&get_peers,
818 else if (GNUNET_YES == request_tunnels)
820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
821 "Show all tunnels\n");
822 job = GNUNET_SCHEDULER_add_now (&get_tunnels,
826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
827 "Connecting to CADET service\n");
828 mh = GNUNET_CADET_connect (cfg);
829 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
833 GNUNET_SCHEDULER_shutdown ();
836 if (NULL != listen_port)
838 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
839 "Opening CADET listen port\n");
840 GNUNET_CRYPTO_hash (listen_port,
841 strlen (listen_port),
843 lp = GNUNET_CADET_open_port (mh,
847 NULL /* window changes */,
851 if (NULL != target_id)
853 struct GNUNET_PeerIdentity pid;
854 enum GNUNET_CADET_ChannelOption opt;
857 GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
861 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
862 _("Invalid target `%s'\n"),
864 GNUNET_SCHEDULER_shutdown ();
867 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
868 "Connecting to `%s:%s'\n",
871 opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
872 GNUNET_CRYPTO_hash (target_port,
875 ch = GNUNET_CADET_channel_create (mh,
880 NULL /* window changes */,
883 if (GNUNET_YES == echo)
885 echo_task = GNUNET_SCHEDULER_add_now (&send_echo,
898 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
899 _("No action requested\n"));
900 GNUNET_SCHEDULER_shutdown ();
907 * The main function to obtain peer information.
909 * @param argc number of arguments from the command line
910 * @param argv command line arguments
911 * @return 0 ok, 1 on error
918 const char helpstr[] = "Create tunnels and retrieve info about CADET's status.";
919 struct GNUNET_GETOPT_CommandLineOption options[] = {
920 /* I would use the terminology 'circuit' here... --lynX */
921 GNUNET_GETOPT_option_string ('C',
924 gettext_noop ("Provide information about a particular connection"),
927 GNUNET_GETOPT_option_flag ('e',
929 gettext_noop ("Activate echo mode"),
932 GNUNET_GETOPT_option_flag ('d',
934 gettext_noop ("Dump debug information to STDERR"),
937 GNUNET_GETOPT_option_string ('o',
940 gettext_noop ("Listen for connections using a shared secret among sender and recipient"),
944 GNUNET_GETOPT_option_string ('p',
947 gettext_noop ("Provide information about a patricular peer"),
951 GNUNET_GETOPT_option_flag ('P',
953 gettext_noop ("Provide information about all peers"),
956 GNUNET_GETOPT_option_string ('t',
959 gettext_noop ("Provide information about a particular tunnel"),
963 GNUNET_GETOPT_option_flag ('T',
965 gettext_noop ("Provide information about all tunnels"),
968 GNUNET_GETOPT_OPTION_END
972 GNUNET_STRINGS_get_utf8_args (argc, argv,
976 res = GNUNET_PROGRAM_run (argc, argv,
977 "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)",
978 gettext_noop (helpstr),
979 options, &run, NULL);
981 GNUNET_free ((void *) argv);
983 if (GNUNET_OK == res)
988 /* end of gnunet-cadet.c */