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.
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/>.
20 * @file cadet/gnunet-cadet.c
21 * @brief Print information about cadet tunnels and peers.
22 * @author Bartlomiej Polot
23 * @author Christian Grothoff
26 #include "gnunet_util_lib.h"
27 #include "gnunet_cadet_service.h"
34 static int request_peers;
44 static int request_tunnels;
49 static char *tunnel_id;
59 static char *channel_id;
62 * Port to listen on (-o).
64 static char *listen_port;
67 * Request echo service
72 * Request a debug dump
77 * Time of last echo request.
79 static struct GNUNET_TIME_Absolute echo_time;
82 * Task for next echo request.
84 static struct GNUNET_SCHEDULER_Task *echo_task;
89 static char *target_id;
94 static char *target_port = "default";
99 static struct GNUNET_CADET_Handle *mh;
104 static struct GNUNET_CADET_Channel *ch;
107 * HashCode of the given port string
109 static struct GNUNET_HashCode porthash;
112 * Data structure for ongoing reception of incoming virtual circuits.
114 struct GNUNET_CADET_Port *lp;
117 * Task for reading from stdin.
119 static struct GNUNET_SCHEDULER_Task *rd_task;
124 static struct GNUNET_SCHEDULER_Task *job;
128 * Wait for input on STDIO and send it out over the #ch.
135 * Convert encryption status to human readable string.
137 * @param status Encryption status.
139 * @return Human readable string.
142 enc_2s (uint16_t status)
161 * Convert connection status to human readable string.
163 * @param status Connection status.
165 * @return Human readable string.
168 conn_2s (uint16_t status)
190 * Task to shut down this application.
192 * @param cls Closure (unused).
195 shutdown_task (void *cls)
197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201 GNUNET_CADET_channel_destroy (ch);
206 GNUNET_CADET_disconnect (mh);
211 GNUNET_SCHEDULER_cancel (rd_task);
214 if (NULL != echo_task)
216 GNUNET_SCHEDULER_cancel (echo_task);
221 GNUNET_SCHEDULER_cancel (job);
228 * Task run in stdio mode, after some data is available at stdin.
230 * @param cls Closure (unused).
233 read_stdio (void *cls)
235 struct GNUNET_MQ_Envelope *env;
236 struct GNUNET_MessageHeader *msg;
246 GNUNET_SCHEDULER_shutdown();
249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
250 "Read %u bytes from stdio\n",
251 (unsigned int) data_size);
252 env = GNUNET_MQ_msg_extra (msg,
254 GNUNET_MESSAGE_TYPE_CADET_CLI);
255 GNUNET_memcpy (&msg[1],
258 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
260 if (GNUNET_NO == echo)
266 echo_time = GNUNET_TIME_absolute_get ();
272 * Wait for input on STDIO and send it out over the #ch.
277 struct GNUNET_NETWORK_FDSet *rs;
279 /* FIXME: why use 'rs' here, seems overly complicated... */
280 rs = GNUNET_NETWORK_fdset_create ();
281 GNUNET_NETWORK_fdset_set_native (rs,
283 rd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
284 GNUNET_TIME_UNIT_FOREVER_REL,
289 GNUNET_NETWORK_fdset_destroy (rs);
294 * Function called whenever a channel is destroyed. Should clean up
295 * any associated state.
297 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
300 * @param channel connection to the other end (henceforth invalid)
303 channel_ended (void *cls,
304 const struct GNUNET_CADET_Channel *channel)
306 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
308 GNUNET_assert (channel == ch);
310 GNUNET_SCHEDULER_shutdown ();
315 * Method called whenever another peer has added us to a channel
316 * the other peer initiated.
317 * Only called (once) upon reception of data with a message type which was
318 * subscribed to in #GNUNET_CADET_connect.
320 * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored.
321 * In this case the handler MUST return NULL.
324 * @param channel new handle to the channel
325 * @param initiator peer that started the channel
326 * @return initial channel context for the channel, we use @a channel
329 channel_incoming (void *cls,
330 struct GNUNET_CADET_Channel *channel,
331 const struct GNUNET_PeerIdentity *initiator)
333 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
334 "Incoming connection from %s\n",
335 GNUNET_i2s_full (initiator));
336 GNUNET_assert (NULL == ch);
337 GNUNET_assert (NULL != lp);
338 GNUNET_CADET_close_port (lp);
341 if (GNUNET_NO == echo)
348 * @brief Send an echo request to the remote peer.
350 * @param cls Closure (NULL).
353 send_echo (void *cls)
355 struct GNUNET_MQ_Envelope *env;
356 struct GNUNET_MessageHeader *msg;
361 env = GNUNET_MQ_msg (msg,
362 GNUNET_MESSAGE_TYPE_CADET_CLI);
363 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
369 * Call CADET's monitor API, request debug dump on the service.
371 * @param cls Closure (unused).
374 request_dump (void *cls)
377 GNUNET_CADET_request_dump (mh);
378 GNUNET_SCHEDULER_shutdown ();
383 * Check data message sanity. Does nothing so far (all messages are OK).
385 * @param cls Closure (unused).
386 * @param message The message to check.
387 * @return #GNUNET_OK to keep the channel open,
388 * #GNUNET_SYSERR to close it (signal serious error).
391 check_data (void *cls,
392 const struct GNUNET_MessageHeader *message)
394 return GNUNET_OK; /* all is well-formed */
399 * Function called whenever a message is received.
401 * Each time the function must call #GNUNET_CADET_receive_done on the channel
402 * in order to receive the next message. This doesn't need to be immediate:
403 * can be delayed if some processing is done on the message.
406 * @param message The actual message.
409 handle_data (void *cls,
410 const struct GNUNET_MessageHeader *message)
412 size_t payload_size = ntohs (message->size) - sizeof (*message);
418 GNUNET_CADET_receive_done (ch);
419 if (GNUNET_YES == echo)
421 if (NULL != listen_port)
423 struct GNUNET_MQ_Envelope *env;
424 struct GNUNET_MessageHeader *msg;
426 env = GNUNET_MQ_msg_extra (msg,
428 GNUNET_MESSAGE_TYPE_CADET_CLI);
429 GNUNET_memcpy (&msg[1],
432 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
438 struct GNUNET_TIME_Relative latency;
440 latency = GNUNET_TIME_absolute_get_duration (echo_time);
441 echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
442 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
444 GNUNET_STRINGS_relative_time_to_string (latency,
446 echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
452 len = ntohs (message->size) - sizeof (*message);
453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
456 buf = (const char *) &message[1];
466 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
468 GNUNET_SCHEDULER_shutdown ();
477 * Method called to retrieve information about all peers in CADET, called
480 * After last peer has been reported, an additional call with NULL is done.
482 * @param cls Closure.
483 * @param peer Peer, or NULL on "EOF".
484 * @param tunnel Do we have a tunnel towards this peer?
485 * @param n_paths Number of known paths towards this peer.
486 * @param best_path How long is the best path?
487 * (0 = unknown, 1 = ourselves, 2 = neighbor)
490 peers_callback (void *cls,
491 const struct GNUNET_PeerIdentity *peer,
493 unsigned int n_paths,
494 unsigned int best_path)
498 GNUNET_SCHEDULER_shutdown();
502 "%s tunnel: %c, paths: %u\n",
503 GNUNET_i2s_full (peer),
510 * Method called to retrieve information about a specific peer
511 * known to the service.
513 * @param cls Closure.
514 * @param peer Peer ID.
515 * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO
516 * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO
517 * @param n_paths Number of paths known towards peer.
518 * @param paths Array of PEER_IDs representing all paths to reach the peer.
519 * Each path starts with the local peer.
520 * Each path ends with the destination peer (given in @c peer).
523 peer_callback (void *cls,
524 const struct GNUNET_PeerIdentity *peer,
527 unsigned int n_paths,
528 const struct GNUNET_PeerIdentity *paths)
531 const struct GNUNET_PeerIdentity *p;
534 "%s [TUNNEL: %s, NEIGHBOR: %s, PATHS: %u]\n",
535 GNUNET_i2s_full (peer),
537 neighbor ? "Y" : "N",
540 for (i = 0; i < n_paths && NULL != p;)
549 FPRINTF (stdout, "\n");
555 GNUNET_SCHEDULER_shutdown();
560 * Method called to retrieve information about all tunnels in CADET.
562 * @param cls Closure.
563 * @param peer Destination peer.
564 * @param channels Number of channels.
565 * @param connections Number of connections.
566 * @param estate Encryption state.
567 * @param cstate Connectivity state.
570 tunnels_callback (void *cls,
571 const struct GNUNET_PeerIdentity *peer,
572 unsigned int channels,
573 unsigned int connections,
579 GNUNET_SCHEDULER_shutdown();
583 "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n",
584 GNUNET_i2s_full (peer),
593 * Method called to retrieve information about a specific tunnel the cadet peer
594 * has established, o`r is trying to establish.
596 * @param cls Closure.
597 * @param peer Peer towards whom the tunnel is directed.
598 * @param n_channels Number of channels.
599 * @param n_connections Number of connections.
600 * @param channels Channels.
601 * @param connections Connections.
602 * @param estate Encryption status.
603 * @param cstate Connectivity status.
606 tunnel_callback (void *cls,
607 const struct GNUNET_PeerIdentity *peer,
608 unsigned int n_channels,
609 unsigned int n_connections,
610 const struct GNUNET_CADET_ChannelTunnelNumber *channels,
611 const struct GNUNET_CADET_ConnectionTunnelIdentifier *connections,
619 FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer));
620 FPRINTF (stdout, "\t%u channels\n", n_channels);
621 for (i = 0; i < n_channels; i++)
622 FPRINTF (stdout, "\t\t%X\n", ntohl (channels[i].cn));
623 FPRINTF (stdout, "\t%u connections\n", n_connections);
624 for (i = 0; i < n_connections; i++)
625 FPRINTF (stdout, "\t\t%s\n", GNUNET_sh2s (&connections[i].connection_of_tunnel));
626 FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate));
627 FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate));
629 GNUNET_SCHEDULER_shutdown ();
634 * Call CADET's meta API, get all peers known to a peer.
636 * @param cls Closure (unused).
639 get_peers (void *cls)
642 GNUNET_CADET_get_peers (mh, &peers_callback, NULL);
647 * Call CADET's monitor API, get info of one peer.
649 * @param cls Closure (unused).
652 show_peer (void *cls)
654 struct GNUNET_PeerIdentity pid;
658 GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
663 _("Invalid peer ID `%s'\n"),
665 GNUNET_SCHEDULER_shutdown();
668 GNUNET_CADET_get_peer (mh, &pid, peer_callback, NULL);
673 * Call CADET's meta API, get all tunnels known to a peer.
675 * @param cls Closure (unused).
678 get_tunnels (void *cls)
681 GNUNET_CADET_get_tunnels (mh, &tunnels_callback, NULL);
686 * Call CADET's monitor API, get info of one tunnel.
688 * @param cls Closure (unused).
691 show_tunnel (void *cls)
693 struct GNUNET_PeerIdentity pid;
697 GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id,
702 _("Invalid tunnel owner `%s'\n"),
704 GNUNET_SCHEDULER_shutdown ();
707 GNUNET_CADET_get_tunnel (mh,
715 * Call CADET's monitor API, get info of one channel.
717 * @param cls Closure (unused).
720 show_channel (void *cls)
728 * Call CADET's monitor API, get info of one connection.
730 * @param cls Closure (unused).
733 show_connection (void *cls)
741 * Main function that will be run by the scheduler.
744 * @param args remaining command-line arguments
745 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
746 * @param cfg configuration
752 const struct GNUNET_CONFIGURATION_Handle *cfg)
754 struct GNUNET_MQ_MessageHandler handlers[] = {
755 GNUNET_MQ_hd_var_size (data,
756 GNUNET_MESSAGE_TYPE_CADET_CLI,
757 struct GNUNET_MessageHeader,
759 GNUNET_MQ_handler_end ()
762 /* FIXME add option to monitor apps */
765 if (target_id && args[1])
766 target_port = args[1];
768 if ( (0 != (request_peers | request_tunnels)
771 || NULL != channel_id)
772 && target_id != NULL)
775 _("Extra arguments are not applicable "
776 "in combination with this option.\n"));
780 if (GNUNET_YES == dump)
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
783 "Requesting debug dump\n");
784 job = GNUNET_SCHEDULER_add_now (&request_dump,
787 else if (NULL != peer_id)
789 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
791 job = GNUNET_SCHEDULER_add_now (&show_peer,
794 else if (NULL != tunnel_id)
796 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
798 job = GNUNET_SCHEDULER_add_now (&show_tunnel,
801 else if (NULL != channel_id)
803 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
805 job = GNUNET_SCHEDULER_add_now (&show_channel,
808 else if (NULL != conn_id)
810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
811 "Show connection\n");
812 job = GNUNET_SCHEDULER_add_now (&show_connection,
815 else if (GNUNET_YES == request_peers)
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
819 job = GNUNET_SCHEDULER_add_now (&get_peers,
822 else if (GNUNET_YES == request_tunnels)
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825 "Show all tunnels\n");
826 job = GNUNET_SCHEDULER_add_now (&get_tunnels,
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "Connecting to CADET service\n");
832 mh = GNUNET_CADET_connect (cfg);
833 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
837 GNUNET_SCHEDULER_shutdown ();
840 if (NULL != listen_port)
842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
843 "Opening CADET listen port\n");
844 GNUNET_CRYPTO_hash (listen_port,
845 strlen (listen_port),
847 lp = GNUNET_CADET_open_port (mh,
851 NULL /* window changes */,
855 if (NULL != target_id)
857 struct GNUNET_PeerIdentity pid;
858 enum GNUNET_CADET_ChannelOption opt;
861 GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
865 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
866 _("Invalid target `%s'\n"),
868 GNUNET_SCHEDULER_shutdown ();
871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
872 "Connecting to `%s:%s'\n",
875 opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
876 GNUNET_CRYPTO_hash (target_port,
879 ch = GNUNET_CADET_channel_create (mh,
884 NULL /* window changes */,
887 if (GNUNET_YES == echo)
889 echo_task = GNUNET_SCHEDULER_add_now (&send_echo,
902 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
903 _("No action requested\n"));
904 GNUNET_SCHEDULER_shutdown ();
911 * The main function to obtain peer information.
913 * @param argc number of arguments from the command line
914 * @param argv command line arguments
915 * @return 0 ok, 1 on error
922 const char helpstr[] = "Create tunnels and retrieve info about CADET's status.";
923 struct GNUNET_GETOPT_CommandLineOption options[] = {
924 /* I would use the terminology 'circuit' here... --lynX */
925 GNUNET_GETOPT_option_string ('C',
928 gettext_noop ("Provide information about a particular connection"),
931 GNUNET_GETOPT_option_flag ('e',
933 gettext_noop ("Activate echo mode"),
936 GNUNET_GETOPT_option_flag ('d',
938 gettext_noop ("Dump debug information to STDERR"),
941 GNUNET_GETOPT_option_string ('o',
944 gettext_noop ("Listen for connections using a shared secret among sender and recipient"),
948 GNUNET_GETOPT_option_string ('p',
951 gettext_noop ("Provide information about a patricular peer"),
955 GNUNET_GETOPT_option_flag ('P',
957 gettext_noop ("Provide information about all peers"),
960 GNUNET_GETOPT_option_string ('t',
963 gettext_noop ("Provide information about a particular tunnel"),
967 GNUNET_GETOPT_option_flag ('T',
969 gettext_noop ("Provide information about all tunnels"),
972 GNUNET_GETOPT_OPTION_END
976 GNUNET_STRINGS_get_utf8_args (argc, argv,
980 res = GNUNET_PROGRAM_run (argc, argv,
981 "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)",
982 gettext_noop (helpstr),
983 options, &run, NULL);
985 GNUNET_free ((void *) argv);
987 if (GNUNET_OK == res)
992 /* end of gnunet-cadet.c */