commit 7ad3095903787984e79fc5c1ec4fe5a9877efddf
parent e7ae1d89c44ba1087a69f84535851791fc1877fc
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Fri, 31 Jul 2026 11:08:53 +0200
transport: fotgot file
Diffstat:
2 files changed, 335 insertions(+), 0 deletions(-)
diff --git a/src/cli/transport/gnunet-transport.c b/src/cli/transport/gnunet-transport.c
@@ -0,0 +1,326 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2026 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file cli/transport/gnunet-transport.c
+ * @brief Print the virtual links transport currently has, with the flow
+ * control state CORE rides on.
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_transport_monitor_service.h"
+
+/**
+ * Return code.
+ */
+static int ret;
+
+/**
+ * Option -a: also show links that are not established yet.
+ */
+static int include_unconfirmed;
+
+/**
+ * Option -V: show the full flow control state of every link.
+ */
+static int verbose;
+
+/**
+ * Option -p: restrict the listing to this peer.
+ */
+static char *peer_id;
+
+/**
+ * Handle to the running listing, NULL once it completed.
+ */
+static struct GNUNET_TRANSPORT_LinkListContext *llc;
+
+/**
+ * Number of links reported so far.
+ */
+static unsigned int num_links;
+
+
+/**
+ * Task run when the user aborts us or the listing finished.
+ *
+ * @param cls NULL
+ */
+static void
+shutdown_task (void *cls)
+{
+ (void) cls;
+ if (NULL != llc)
+ {
+ GNUNET_TRANSPORT_links_list_cancel (llc);
+ llc = NULL;
+ }
+}
+
+
+/**
+ * Render how a link is routed into @a buf.
+ *
+ * @param li link to describe
+ * @param[out] buf where to write the description
+ * @param buf_size number of bytes available in @a buf
+ * @return @a buf
+ */
+static const char *
+route_to_string (const struct GNUNET_TRANSPORT_LinkInformation *li,
+ char *buf,
+ size_t buf_size)
+{
+ if (GNUNET_TRANSPORT_LINK_ROUTE_DIRECT == li->route)
+ {
+ GNUNET_snprintf (buf, buf_size, "%s", _ ("direct"));
+ return buf;
+ }
+ /* `distance' counts neither the next hop nor the target, so the number
+ of hops a user would count is two more. */
+ GNUNET_snprintf (buf, buf_size, _ ("dv (%u hops)"), li->distance + 2);
+ return buf;
+}
+
+
+/**
+ * Print everything we know about @a li, one field per line.
+ *
+ * @param peer peer at the other end of the link
+ * @param li the link to print
+ */
+static void
+print_link_verbose (const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_TRANSPORT_LinkInformation *li)
+{
+ char route[64];
+ char *s1;
+ char *s2;
+
+ fprintf (stdout, "%s\n", GNUNET_i2s_full (peer));
+ fprintf (stdout,
+ _ (" routed: %s over %s (%u queue(s))\n"),
+ route_to_string (li, route, sizeof (route)),
+ ('\0' == li->communicators[0]) ? "-" : li->communicators,
+ li->num_queues);
+ fprintf (stdout,
+ _ (" established: %s\n"),
+ (GNUNET_YES == li->confirmed) ? _ ("yes") : _ ("no"));
+ fprintf (stdout,
+ _ (" CORE receive window: %d\n"),
+ li->core_recv_window);
+ fprintf (stdout,
+ _ (" stalled for CORE: %u message(s)\n"),
+ li->stalled);
+ fprintf (stdout,
+ _ (" pending transmission: %u message(s)\n"),
+ li->pending);
+ s1 = GNUNET_STRINGS_byte_size_fancy (li->incoming_fc_window_size_used);
+ s2 = GNUNET_STRINGS_byte_size_fancy (li->incoming_fc_window_size);
+ fprintf (stdout, _ (" inbound window used: %s of %s\n"), s1, s2);
+ GNUNET_free (s1);
+ GNUNET_free (s2);
+ s1 = GNUNET_STRINGS_byte_size_fancy (li->outbound_fc_window_size_used);
+ s2 = GNUNET_STRINGS_byte_size_fancy (li->outbound_fc_window_size);
+ fprintf (stdout, _ (" outbound window used: %s of %s\n"), s1, s2);
+ GNUNET_free (s1);
+ GNUNET_free (s2);
+ s1 = GNUNET_STRINGS_byte_size_fancy (li->incoming_fc_window_size_ram);
+ s2 = GNUNET_STRINGS_byte_size_fancy (li->available_fc_window_size);
+ fprintf (stdout, _ (" buffer used: %s of %s\n"), s1, s2);
+ GNUNET_free (s1);
+ GNUNET_free (s2);
+ fprintf (stdout,
+ _ (" estimated loss: %lld byte(s)\n"),
+ (long long) li->incoming_fc_window_size_loss);
+ fprintf (stdout,
+ _ (" flow control RTT: %s (peer reports %s)\n"),
+ GNUNET_STRINGS_relative_time_to_string (li->last_fc_rtt,
+ GNUNET_YES),
+ GNUNET_STRINGS_relative_time_to_string (li->other_rtt,
+ GNUNET_YES));
+ fprintf (stdout,
+ _ (" last flow control: %s ago (%u retransmission(s))\n"),
+ GNUNET_STRINGS_relative_time_to_string (
+ GNUNET_TIME_absolute_get_duration (li->last_fc_transmission),
+ GNUNET_YES),
+ li->fc_retransmit_count);
+ fprintf (stdout, "\n");
+}
+
+
+/**
+ * Function called once per virtual link, and a final time with both
+ * arguments NULL.
+ *
+ * @param cls NULL
+ * @param peer peer at the other end of the link, NULL when done
+ * @param li state of the link, NULL when done
+ */
+static void
+link_cb (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_TRANSPORT_LinkInformation *li)
+{
+ char route[64];
+
+ (void) cls;
+ if (NULL == peer)
+ {
+ /* The listing completed; the handle released itself. */
+ llc = NULL;
+ if (0 == num_links)
+ fprintf (stdout, "%s\n", _ ("No virtual links."));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (verbose)
+ {
+ print_link_verbose (peer, li);
+ num_links++;
+ return;
+ }
+ if (0 == num_links)
+ fprintf (stdout,
+ "%-10s %-14s %-12s %9s %8s %8s %10s\n",
+ _ ("PEER"),
+ _ ("ROUTE"),
+ _ ("VIA"),
+ _ ("CORE-WIN"),
+ _ ("STALLED"),
+ _ ("PENDING"),
+ _ ("RTT"));
+ num_links++;
+ fprintf (stdout,
+ "%-10s %-14s %-12s %9d %8u %8u %10s\n",
+ GNUNET_i2s (peer),
+ route_to_string (li, route, sizeof (route)),
+ ('\0' == li->communicators[0]) ? "-" : li->communicators,
+ li->core_recv_window,
+ li->stalled,
+ li->pending,
+ GNUNET_STRINGS_relative_time_to_string (li->last_fc_rtt,
+ GNUNET_YES));
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_PeerIdentity pid;
+ const struct GNUNET_PeerIdentity *pidp = NULL;
+
+ (void) cls;
+ (void) cfgfile;
+ if (NULL != args[0])
+ {
+ fprintf (stderr, _ ("Invalid command line argument `%s'\n"), args[0]);
+ ret = 1;
+ return;
+ }
+ if (NULL != peer_id)
+ {
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
+ strlen (peer_id),
+ &pid.public_key))
+ {
+ fprintf (stderr, _ ("Invalid peer ID `%s'\n"), peer_id);
+ ret = 1;
+ return;
+ }
+ pidp = &pid;
+ }
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+ llc = GNUNET_TRANSPORT_links_list (cfg,
+ pidp,
+ include_unconfirmed ? GNUNET_YES
+ : GNUNET_NO,
+ &link_cb,
+ NULL);
+ if (NULL == llc)
+ {
+ fprintf (stderr, "%s", _ ("Failed to connect to transport service!\n"));
+ ret = 1;
+ GNUNET_SCHEDULER_shutdown ();
+ }
+}
+
+
+/**
+ * The main function to list the virtual links of the transport service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+ int res;
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_flag (
+ 'a',
+ "all",
+ gettext_noop ("also show links that are not established yet"),
+ &include_unconfirmed),
+ GNUNET_GETOPT_option_string (
+ 'p',
+ "peer",
+ "PEERID",
+ gettext_noop ("only show the link to this peer"),
+ &peer_id),
+ GNUNET_GETOPT_option_flag (
+ 'V',
+ "verbose",
+ gettext_noop ("show the full flow control state of every link"),
+ &verbose),
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ res = GNUNET_PROGRAM_run (GNUNET_OS_project_data_gnunet (),
+ argc,
+ argv,
+ "gnunet-transport",
+ gettext_noop (
+ "Print information about the virtual links of "
+ "the transport service."),
+ options,
+ &run,
+ NULL);
+ if (GNUNET_OK == res)
+ return ret;
+ return 1;
+}
+
+
+/* end of gnunet-transport.c */
diff --git a/src/cli/transport/meson.build b/src/cli/transport/meson.build
@@ -0,0 +1,9 @@
+executable(
+ 'gnunet-transport',
+ ['gnunet-transport.c'],
+ install_rpath: rpath_option,
+ dependencies: [libgnunettransportmonitor_dep, libgnunetutil_dep],
+ include_directories: [incdir, configuration_inc],
+ install: true,
+ install_dir: get_option('bindir'),
+)