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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file cadet/gnunet-cadet.c
23 * @brief Print information about cadet tunnels and peers.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
29 #include "gnunet_cadet_service.h"
36 static int request_peers;
46 static int request_tunnels;
51 static char *tunnel_id;
61 static char *channel_id;
64 * Port to listen on (-o).
66 static char *listen_port;
69 * Request echo service
74 * Request a debug dump
79 * Time of last echo request.
81 static struct GNUNET_TIME_Absolute echo_time;
84 * Task for next echo request.
86 static struct GNUNET_SCHEDULER_Task *echo_task;
91 static char *target_id;
96 static char *target_port = "default";
101 static struct GNUNET_CADET_Handle *mh;
106 static struct GNUNET_CADET_Channel *ch;
109 * HashCode of the given port string
111 static struct GNUNET_HashCode porthash;
114 * Data structure for ongoing reception of incoming virtual circuits.
116 struct GNUNET_CADET_Port *lp;
119 * Task for reading from stdin.
121 static struct GNUNET_SCHEDULER_Task *rd_task;
126 static struct GNUNET_SCHEDULER_Task *job;
130 * Wait for input on STDIO and send it out over the #ch.
137 * Convert encryption status to human readable string.
139 * @param status Encryption status.
141 * @return Human readable string.
144 enc_2s (uint16_t status)
163 * Convert connection status to human readable string.
165 * @param status Connection status.
167 * @return Human readable string.
170 conn_2s (uint16_t status)
192 * Task to shut down this application.
194 * @param cls Closure (unused).
197 shutdown_task (void *cls)
199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
203 GNUNET_CADET_channel_destroy (ch);
208 GNUNET_CADET_disconnect (mh);
213 GNUNET_SCHEDULER_cancel (rd_task);
216 if (NULL != echo_task)
218 GNUNET_SCHEDULER_cancel (echo_task);
223 GNUNET_SCHEDULER_cancel (job);
230 * Task run in stdio mode, after some data is available at stdin.
232 * @param cls Closure (unused).
235 read_stdio (void *cls)
237 struct GNUNET_MQ_Envelope *env;
238 struct GNUNET_MessageHeader *msg;
248 GNUNET_SCHEDULER_shutdown();
251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
252 "Read %u bytes from stdio\n",
253 (unsigned int) data_size);
254 env = GNUNET_MQ_msg_extra (msg,
256 GNUNET_MESSAGE_TYPE_CADET_CLI);
257 GNUNET_memcpy (&msg[1],
260 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
262 if (GNUNET_NO == echo)
268 echo_time = GNUNET_TIME_absolute_get ();
274 * Wait for input on STDIO and send it out over the #ch.
279 struct GNUNET_NETWORK_FDSet *rs;
281 /* FIXME: why use 'rs' here, seems overly complicated... */
282 rs = GNUNET_NETWORK_fdset_create ();
283 GNUNET_NETWORK_fdset_set_native (rs,
285 rd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
286 GNUNET_TIME_UNIT_FOREVER_REL,
291 GNUNET_NETWORK_fdset_destroy (rs);
296 * Function called whenever a channel is destroyed. Should clean up
297 * any associated state.
299 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
302 * @param channel connection to the other end (henceforth invalid)
305 channel_ended (void *cls,
306 const struct GNUNET_CADET_Channel *channel)
308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
310 GNUNET_assert (channel == ch);
312 GNUNET_SCHEDULER_shutdown ();
317 * Method called whenever another peer has added us to a channel
318 * the other peer initiated.
319 * Only called (once) upon reception of data with a message type which was
320 * subscribed to in #GNUNET_CADET_connect.
322 * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored.
323 * In this case the handler MUST return NULL.
326 * @param channel new handle to the channel
327 * @param initiator peer that started the channel
328 * @return initial channel context for the channel, we use @a channel
331 channel_incoming (void *cls,
332 struct GNUNET_CADET_Channel *channel,
333 const struct GNUNET_PeerIdentity *initiator)
335 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
336 "Incoming connection from %s\n",
337 GNUNET_i2s_full (initiator));
338 GNUNET_assert (NULL == ch);
339 GNUNET_assert (NULL != lp);
340 GNUNET_CADET_close_port (lp);
343 if (GNUNET_NO == echo)
350 * @brief Send an echo request to the remote peer.
352 * @param cls Closure (NULL).
355 send_echo (void *cls)
357 struct GNUNET_MQ_Envelope *env;
358 struct GNUNET_MessageHeader *msg;
363 env = GNUNET_MQ_msg (msg,
364 GNUNET_MESSAGE_TYPE_CADET_CLI);
365 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
371 * Call CADET's monitor API, request debug dump on the service.
373 * @param cls Closure (unused).
376 request_dump (void *cls)
378 GNUNET_CADET_request_dump (mh);
379 GNUNET_SCHEDULER_shutdown ();
384 * Function called whenever a message is received.
386 * Each time the function must call #GNUNET_CADET_receive_done on the channel
387 * in order to receive the next message. This doesn't need to be immediate:
388 * can be delayed if some processing is done on the message.
390 * @param cls should match #ch
391 * @param message The actual message.
392 * @return #GNUNET_OK to keep the channel open,
393 * #GNUNET_SYSERR to close it (signal serious error).
396 check_data (void *cls,
397 const struct GNUNET_MessageHeader *message)
399 return GNUNET_OK; /* all is well-formed */
404 * Function called whenever a message is received.
406 * Each time the function must call #GNUNET_CADET_receive_done on the channel
407 * in order to receive the next message. This doesn't need to be immediate:
408 * can be delayed if some processing is done on the message.
411 * @param message The actual message.
414 handle_data (void *cls,
415 const struct GNUNET_MessageHeader *message)
417 size_t payload_size = ntohs (message->size) - sizeof (*message);
423 GNUNET_CADET_receive_done (ch);
424 if (GNUNET_YES == echo)
426 if (NULL != listen_port)
428 struct GNUNET_MQ_Envelope *env;
429 struct GNUNET_MessageHeader *msg;
431 env = GNUNET_MQ_msg_extra (msg,
433 GNUNET_MESSAGE_TYPE_CADET_CLI);
434 GNUNET_memcpy (&msg[1],
437 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
443 struct GNUNET_TIME_Relative latency;
445 latency = GNUNET_TIME_absolute_get_duration (echo_time);
446 echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
447 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
449 GNUNET_STRINGS_relative_time_to_string (latency,
451 echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
457 len = ntohs (message->size) - sizeof (*message);
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
461 buf = (const char *) &message[1];
471 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
473 GNUNET_SCHEDULER_shutdown ();
482 * Method called to retrieve information about all peers in CADET, called
485 * After last peer has been reported, an additional call with NULL is done.
487 * @param cls Closure.
488 * @param peer Peer, or NULL on "EOF".
489 * @param tunnel Do we have a tunnel towards this peer?
490 * @param n_paths Number of known paths towards this peer.
491 * @param best_path How long is the best path?
492 * (0 = unknown, 1 = ourselves, 2 = neighbor)
495 peers_callback (void *cls,
496 const struct GNUNET_PeerIdentity *peer,
498 unsigned int n_paths,
499 unsigned int best_path)
503 GNUNET_SCHEDULER_shutdown();
507 "%s tunnel: %c, paths: %u\n",
508 GNUNET_i2s_full (peer),
515 * Method called to retrieve information about a specific peer
516 * known to the service.
518 * @param cls Closure.
519 * @param peer Peer ID.
520 * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO
521 * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO
522 * @param n_paths Number of paths known towards peer.
523 * @param paths Array of PEER_IDs representing all paths to reach the peer.
524 * Each path starts with the local peer.
525 * Each path ends with the destination peer (given in @c peer).
528 peer_callback (void *cls,
529 const struct GNUNET_PeerIdentity *peer,
532 unsigned int n_paths,
533 const struct GNUNET_PeerIdentity *paths)
536 const struct GNUNET_PeerIdentity *p;
539 "%s [TUNNEL: %s, NEIGHBOR: %s, PATHS: %u]\n",
540 GNUNET_i2s_full (peer),
542 neighbor ? "Y" : "N",
545 for (i = 0; i < n_paths && NULL != p;)
554 FPRINTF (stdout, "\n");
560 GNUNET_SCHEDULER_shutdown();
565 * Method called to retrieve information about all tunnels in CADET.
567 * @param cls Closure.
568 * @param peer Destination peer.
569 * @param channels Number of channels.
570 * @param connections Number of connections.
571 * @param estate Encryption state.
572 * @param cstate Connectivity state.
575 tunnels_callback (void *cls,
576 const struct GNUNET_PeerIdentity *peer,
577 unsigned int channels,
578 unsigned int connections,
584 GNUNET_SCHEDULER_shutdown();
588 "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n",
589 GNUNET_i2s_full (peer),
598 * Method called to retrieve information about a specific tunnel the cadet peer
599 * has established, o`r is trying to establish.
601 * @param cls Closure.
602 * @param peer Peer towards whom the tunnel is directed.
603 * @param n_channels Number of channels.
604 * @param n_connections Number of connections.
605 * @param channels Channels.
606 * @param connections Connections.
607 * @param estate Encryption status.
608 * @param cstate Connectivity status.
611 tunnel_callback (void *cls,
612 const struct GNUNET_PeerIdentity *peer,
613 unsigned int n_channels,
614 unsigned int n_connections,
615 const struct GNUNET_CADET_ChannelTunnelNumber *channels,
616 const struct GNUNET_CADET_ConnectionTunnelIdentifier *connections,
624 FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer));
625 FPRINTF (stdout, "\t%u channels\n", n_channels);
626 for (i = 0; i < n_channels; i++)
627 FPRINTF (stdout, "\t\t%X\n", ntohl (channels[i].cn));
628 FPRINTF (stdout, "\t%u connections\n", n_connections);
629 for (i = 0; i < n_connections; i++)
630 FPRINTF (stdout, "\t\t%s\n", GNUNET_sh2s (&connections[i].connection_of_tunnel));
631 FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate));
632 FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate));
634 GNUNET_SCHEDULER_shutdown ();
639 * Call CADET's meta API, get all peers known to a peer.
641 * @param cls Closure (unused).
644 get_peers (void *cls)
647 GNUNET_CADET_get_peers (mh, &peers_callback, NULL);
652 * Call CADET's monitor API, get info of one peer.
654 * @param cls Closure (unused).
657 show_peer (void *cls)
659 struct GNUNET_PeerIdentity pid;
663 GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
668 _("Invalid peer ID `%s'\n"),
670 GNUNET_SCHEDULER_shutdown();
673 GNUNET_CADET_get_peer (mh, &pid, peer_callback, NULL);
678 * Call CADET's meta API, get all tunnels known to a peer.
680 * @param cls Closure (unused).
683 get_tunnels (void *cls)
686 GNUNET_CADET_get_tunnels (mh, &tunnels_callback, NULL);
691 * Call CADET's monitor API, get info of one tunnel.
693 * @param cls Closure (unused).
696 show_tunnel (void *cls)
698 struct GNUNET_PeerIdentity pid;
701 GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id,
706 _("Invalid tunnel owner `%s'\n"),
708 GNUNET_SCHEDULER_shutdown ();
711 GNUNET_CADET_get_tunnel (mh,
719 * Call CADET's monitor API, get info of one channel.
721 * @param cls Closure (unused).
724 show_channel (void *cls)
732 * Call CADET's monitor API, get info of one connection.
734 * @param cls Closure (unused).
737 show_connection (void *cls)
745 * Main function that will be run by the scheduler.
748 * @param args remaining command-line arguments
749 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
750 * @param cfg configuration
756 const struct GNUNET_CONFIGURATION_Handle *cfg)
758 struct GNUNET_MQ_MessageHandler handlers[] = {
759 GNUNET_MQ_hd_var_size (data,
760 GNUNET_MESSAGE_TYPE_CADET_CLI,
761 struct GNUNET_MessageHeader,
763 GNUNET_MQ_handler_end ()
766 /* FIXME add option to monitor apps */
769 if (target_id && args[1])
770 target_port = args[1];
772 if ( (0 != (request_peers | request_tunnels)
775 || NULL != channel_id)
776 && target_id != NULL)
779 _("You must NOT give a TARGET "
780 "when using 'request all' options\n"));
784 if (GNUNET_YES == dump)
786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
787 "requesting debug dump\n");
788 job = GNUNET_SCHEDULER_add_now (&request_dump,
791 else if (NULL != peer_id)
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
795 job = GNUNET_SCHEDULER_add_now (&show_peer,
798 else if (NULL != tunnel_id)
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
802 job = GNUNET_SCHEDULER_add_now (&show_tunnel,
805 else if (NULL != channel_id)
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
809 job = GNUNET_SCHEDULER_add_now (&show_channel,
812 else if (NULL != conn_id)
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815 "Show connection\n");
816 job = GNUNET_SCHEDULER_add_now (&show_connection,
819 else if (GNUNET_YES == request_peers)
821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
823 job = GNUNET_SCHEDULER_add_now (&get_peers,
826 else if (GNUNET_YES == request_tunnels)
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Show all tunnels\n");
830 job = GNUNET_SCHEDULER_add_now (&get_tunnels,
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Connecting to CADET service\n");
836 mh = GNUNET_CADET_connecT (cfg);
837 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
841 GNUNET_SCHEDULER_shutdown ();
844 if (NULL != listen_port)
846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
847 "Opening CADET listen port\n");
848 GNUNET_CRYPTO_hash (listen_port,
849 strlen (listen_port),
851 lp = GNUNET_CADET_open_porT (mh,
855 NULL /* window changes */,
859 if (NULL != target_id)
861 struct GNUNET_PeerIdentity pid;
862 enum GNUNET_CADET_ChannelOption opt;
865 GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
869 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
870 _("Invalid target `%s'\n"),
872 GNUNET_SCHEDULER_shutdown ();
875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
876 "Connecting to `%s:%s'\n",
879 opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
880 GNUNET_CRYPTO_hash (target_port,
883 ch = GNUNET_CADET_channel_creatE (mh,
888 NULL /* window changes */,
891 if (GNUNET_YES == echo)
893 echo_task = GNUNET_SCHEDULER_add_now (&send_echo,
906 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
907 _("No action requested\n"));
908 GNUNET_SCHEDULER_shutdown ();
915 * The main function to obtain peer information.
917 * @param argc number of arguments from the command line
918 * @param argv command line arguments
919 * @return 0 ok, 1 on error
926 const char helpstr[] = "Create channels and retreive info about cadets status.";
927 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
928 {'C', "connection", "CONNECTION_ID",
929 gettext_noop ("provide information about a particular connection"),
930 GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id},
932 gettext_noop ("activate echo mode"),
933 GNUNET_NO, &GNUNET_GETOPT_set_one, &echo},
935 gettext_noop ("dump debug information to STDERR"),
936 GNUNET_NO, &GNUNET_GETOPT_set_one, &dump},
937 {'o', "open-port", "PORT",
938 gettext_noop ("port to listen to"),
939 GNUNET_YES, &GNUNET_GETOPT_set_string, &listen_port},
940 {'p', "peer", "PEER_ID",
941 gettext_noop ("provide information about a patricular peer"),
942 GNUNET_YES, &GNUNET_GETOPT_set_string, &peer_id},
944 gettext_noop ("provide information about all peers"),
945 GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers},
946 {'t', "tunnel", "TUNNEL_ID",
947 gettext_noop ("provide information about a particular tunnel"),
948 GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id},
949 {'T', "tunnels", NULL,
950 gettext_noop ("provide information about all tunnels"),
951 GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels},
953 GNUNET_GETOPT_OPTION_END
957 GNUNET_STRINGS_get_utf8_args (argc, argv,
961 res = GNUNET_PROGRAM_run (argc, argv,
962 "gnunet-cadet (OPTIONS | TARGET PORT)",
963 gettext_noop (helpstr),
964 options, &run, NULL);
966 GNUNET_free ((void *) argv);
968 if (GNUNET_OK == res)
973 /* end of gnunet-cadet.c */