X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcadet%2Fgnunet-cadet.c;h=f5cf86211e06853a6e5cc74b8237c30f964a8a4e;hb=d41ed82a4ea0cc8e1674b6d5d2c49fd6462610bb;hp=840c6d0aca360c0d3f648100112e6680e4853ee0;hpb=41716952f1d0508fb621cb5fec31406d3bd96192;p=oweals%2Fgnunet.git diff --git a/src/cadet/gnunet-cadet.c b/src/cadet/gnunet-cadet.c index 840c6d0ac..f5cf86211 100644 --- a/src/cadet/gnunet-cadet.c +++ b/src/cadet/gnunet-cadet.c @@ -1,38 +1,35 @@ /* This file is part of GNUnet. - (C) 2012 Christian Grothoff (and other contributing authors) + Copyright (C) 2012, 2017, 2019 GNUnet e.V. - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. + 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 - General Public License for more details. + Affero General Public License for more details. - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later + */ /** * @file cadet/gnunet-cadet.c * @brief Print information about cadet tunnels and peers. * @author Bartlomiej Polot + * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_cadet_service.h" #include "cadet.h" - -/** - * Option -m. - */ -static int monitor_connections; +#define STREAM_BUFFER_SIZE 1024 // Pakets /** * Option -P. @@ -49,11 +46,6 @@ static char *peer_id; */ static int request_tunnels; -/** - * Option --tunnel - */ -static char *tunnel_id; - /** * Option --connection */ @@ -65,24 +57,24 @@ static char *conn_id; static char *channel_id; /** - * Port to listen on (-p). + * Port to listen on (-o). */ -static uint32_t listen_port; +static char *listen_port; /** * Request echo service */ -int echo; +static int echo; /** * Time of last echo request. */ -struct GNUNET_TIME_Absolute echo_time; +static struct GNUNET_TIME_Absolute echo_time; /** * Task for next echo request. */ -GNUNET_SCHEDULER_TaskIdentifier echo_task; +static struct GNUNET_SCHEDULER_Task *echo_task; /** * Peer to connect to. @@ -92,18 +84,32 @@ static char *target_id; /** * Port to connect to */ -static uint32_t target_port; +static char *target_port = "default"; /** - * Data pending in netcat mode. + * Cadet handle. */ -size_t data_size; +static struct GNUNET_CADET_Handle *mh; +/** + * Our configuration. + */ +static const struct GNUNET_CONFIGURATION_Handle *my_cfg; /** - * Cadet handle. + * Active get path operation. */ -static struct GNUNET_CADET_Handle *mh; +static struct GNUNET_CADET_GetPath *gpo; + +/** + * Active peer listing operation. + */ +static struct GNUNET_CADET_PeersLister *plo; + +/** + * Active tunnel listing operation. + */ +static struct GNUNET_CADET_ListTunnels *tio; /** * Channel handle. @@ -111,136 +117,231 @@ static struct GNUNET_CADET_Handle *mh; static struct GNUNET_CADET_Channel *ch; /** - * Shutdown task handle. + * HashCode of the given port string */ -GNUNET_SCHEDULER_TaskIdentifier sd; +static struct GNUNET_HashCode porthash; +/** + * Data structure for ongoing reception of incoming virtual circuits. + */ +struct GNUNET_CADET_Port *lp; +/** + * Task for reading from stdin. + */ +static struct GNUNET_SCHEDULER_Task *rd_task; -static void -listen_stdio (void); +/** + * Task for main job. + */ +static struct GNUNET_SCHEDULER_Task *job; +static unsigned int sent_pkt; /** - * Task run in monitor mode when the user presses CTRL-C to abort. - * Stops monitoring activity. - * - * @param cls Closure (unused). - * @param tc scheduler context + * Wait for input on STDIO and send it out over the #ch. */ static void -shutdown_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +listen_stdio(void); + + +/** + * Convert encryption status to human readable string. + * + * @param status Encryption status. + * + * @return Human readable string. + */ +static const char * +enc_2s(uint16_t status) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); - if (NULL != ch) - { - GNUNET_CADET_channel_destroy (ch); - ch = NULL; - } - if (NULL != mh) - { - GNUNET_CADET_disconnect (mh); - mh = NULL; - } + switch (status) + { + case 0: + return "NULL "; + + case 1: + return "KSENT"; + + case 2: + return "KRECV"; + + case 3: + return "READY"; + + default: + return ""; + } } /** - * Function called to notify a client about the connection - * begin ready to queue more data. "buf" will be - * NULL and "size" zero if the connection was closed for - * writing in the meantime. + * Convert connection status to human readable string. * - * FIXME + * @param status Connection status. * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf + * @return Human readable string. */ -size_t -data_ready (void *cls, size_t size, void *buf) +static const char * +conn_2s(uint16_t status) { - struct GNUNET_MessageHeader *msg; - size_t total_size; + switch (status) + { + case 0: + return "NEW "; - if (NULL == buf || 0 == size) - { - GNUNET_SCHEDULER_shutdown(); - return 0; - } + case 1: + return "SRCH "; - total_size = data_size + sizeof (struct GNUNET_MessageHeader); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending %u bytes\n", data_size); - GNUNET_assert (size >= total_size); + case 2: + return "WAIT "; - msg = buf; - msg->size = htons (total_size); - msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_CLI); - memcpy (&msg[1], cls, data_size); - if (GNUNET_NO == echo) - { - listen_stdio (); - } - else - { - echo_time = GNUNET_TIME_absolute_get (); - } + case 3: + return "READY"; + + case 4: + return "SHUTD"; - return total_size; + default: + return ""; + } } /** - * Task run in monitor mode when the user presses CTRL-C to abort. - * Stops monitoring activity. + * Task to shut down this application. * * @param cls Closure (unused). - * @param tc scheduler context */ static void -read_stdio (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +shutdown_task(void *cls) { - static char buf[60000]; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); + if (NULL != lp) + { + GNUNET_CADET_close_port(lp); + lp = NULL; + } + if (NULL != ch) + { + GNUNET_CADET_channel_destroy(ch); + ch = NULL; + } + if (NULL != gpo) + { + GNUNET_CADET_get_path_cancel(gpo); + gpo = NULL; + } + if (NULL != plo) + { + GNUNET_CADET_list_peers_cancel(plo); + plo = NULL; + } + if (NULL != tio) + { + GNUNET_CADET_list_tunnels_cancel(tio); + tio = NULL; + } + if (NULL != mh) + { + GNUNET_CADET_disconnect(mh); + mh = NULL; + } + if (NULL != rd_task) + { + GNUNET_SCHEDULER_cancel(rd_task); + rd_task = NULL; + } + if (NULL != echo_task) + { + GNUNET_SCHEDULER_cancel(echo_task); + echo_task = NULL; + } + if (NULL != job) + { + GNUNET_SCHEDULER_cancel(job); + job = NULL; + } +} + +void +mq_cb(void *cls) +{ + listen_stdio(); +} - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - return; - } - data_size = read (0, buf, 60000); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stdio read %u bytes\n", data_size); +/** + * Task run in stdio mode, after some data is available at stdin. + * + * @param cls Closure (unused). + */ +static void +read_stdio(void *cls) +{ + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MessageHeader *msg; + char buf[60000]; + ssize_t data_size; + + rd_task = NULL; + data_size = read(0, buf, 60000); if (data_size < 1) - { - GNUNET_SCHEDULER_shutdown(); - return; - } - GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - data_size - + sizeof (struct GNUNET_MessageHeader), - &data_ready, buf); + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "read() returned %s\n", + strerror(errno)); + GNUNET_SCHEDULER_shutdown(); + return; + } + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Read %u bytes from stdio\n", + (unsigned int)data_size); + env = GNUNET_MQ_msg_extra(msg, data_size, GNUNET_MESSAGE_TYPE_CADET_CLI); + GNUNET_memcpy(&msg[1], buf, data_size); + GNUNET_MQ_send(GNUNET_CADET_get_mq(ch), env); + + sent_pkt++; + + if (GNUNET_NO == echo) + { + // Use MQ's notification if too much data of stdin is pooring in too fast. + if (STREAM_BUFFER_SIZE < sent_pkt) + { + GNUNET_MQ_notify_sent(env, mq_cb, cls); + sent_pkt = 0; + } + else + { + listen_stdio(); + } + } + else + { + echo_time = GNUNET_TIME_absolute_get(); + } } /** - * Start listening to stdin + * Wait for input on STDIO and send it out over the #ch. */ static void -listen_stdio (void) +listen_stdio() { struct GNUNET_NETWORK_FDSet *rs; - rs = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_set_native (rs, 0); - GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, - GNUNET_TIME_UNIT_FOREVER_REL, - rs, NULL, - &read_stdio, NULL); - GNUNET_NETWORK_fdset_destroy (rs); + /* FIXME: why use 'rs' here, seems overly complicated... */ + rs = GNUNET_NETWORK_fdset_create(); + GNUNET_NETWORK_fdset_set_native(rs, 0); /* STDIN */ + rd_task = GNUNET_SCHEDULER_add_select(GNUNET_SCHEDULER_PRIORITY_DEFAULT, + GNUNET_TIME_UNIT_FOREVER_REL, + rs, + NULL, + &read_stdio, + NULL); + GNUNET_NETWORK_fdset_destroy(rs); } @@ -250,20 +351,16 @@ listen_stdio (void) * * It must NOT call #GNUNET_CADET_channel_destroy on the channel. * - * @param cls closure (set from #GNUNET_CADET_connect) + * @param cls closure * @param channel connection to the other end (henceforth invalid) - * @param channel_ctx place where local state associated - * with the channel is stored */ static void -channel_ended (void *cls, - const struct GNUNET_CADET_Channel *channel, - void *channel_ctx) +channel_ended(void *cls, const struct GNUNET_CADET_Channel *channel) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n"); - GNUNET_break (channel == ch); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n"); + GNUNET_assert(channel == ch); ch = NULL; - GNUNET_SCHEDULER_shutdown (); + GNUNET_SCHEDULER_shutdown(); } @@ -273,99 +370,64 @@ channel_ended (void *cls, * Only called (once) upon reception of data with a message type which was * subscribed to in #GNUNET_CADET_connect. * - * A call to #GNUNET_CADET_channel_destroy causes te channel to be ignored. In - * this case the handler MUST return NULL. + * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored. + * In this case the handler MUST return NULL. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel - * @param port Port this channel is for. - * @param options CadetOption flag field, with all active option bits set to 1. - * - * @return initial channel context for the channel - * (can be NULL -- that's not an error) + * @return initial channel context for the channel, we use @a channel */ static void * -channel_incoming (void *cls, - struct GNUNET_CADET_Channel * channel, - const struct GNUNET_PeerIdentity * initiator, - uint32_t port, enum GNUNET_CADET_ChannelOption options) +channel_incoming(void *cls, + struct GNUNET_CADET_Channel *channel, + const struct GNUNET_PeerIdentity *initiator) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Incoming channel %p on port %u\n", - channel, port); - if (NULL != ch) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A channel already exists\n"); - return NULL; - } - if (0 == listen_port) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not listening to channels\n"); - return NULL; - } + GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, + "Incoming connection from %s\n", + GNUNET_i2s_full(initiator)); + GNUNET_assert(NULL == ch); + GNUNET_assert(NULL != lp); + GNUNET_CADET_close_port(lp); + lp = NULL; ch = channel; if (GNUNET_NO == echo) - { - listen_stdio (); - return NULL; - } - data_size = 0; - return NULL; + listen_stdio(); + return channel; } + /** * @brief Send an echo request to the remote peer. * * @param cls Closure (NULL). - * @param tc Task context. */ static void -send_echo (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +send_echo(void *cls) { - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || NULL == ch) - return; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MessageHeader *msg; - GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - sizeof (struct GNUNET_MessageHeader), - &data_ready, NULL); + echo_task = NULL; + if (NULL == ch) + return; + env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_CADET_CLI); + GNUNET_MQ_send(GNUNET_CADET_get_mq(ch), env); } - /** - * Call CADET's monitor API, get info of one connection. + * Check data message sanity. Does nothing so far (all messages are OK). * * @param cls Closure (unused). - * @param tc TaskContext + * @param message The message to check. + * @return #GNUNET_OK to keep the channel open, + * #GNUNET_SYSERR to close it (signal serious error). */ -static void -create_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +static int +check_data(void *cls, const struct GNUNET_MessageHeader *message) { - struct GNUNET_PeerIdentity pid; - enum GNUNET_CADET_ChannelOption opt; - - GNUNET_assert (NULL == ch); - - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_public_key_from_string (target_id, - strlen (target_id), - &pid.public_key)) - { - FPRINTF (stderr, - _("Invalid target `%s'\n"), - target_id); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id); - opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE; - ch = GNUNET_CADET_channel_create (mh, NULL, &pid, target_port, opt); - if (GNUNET_NO == echo) - listen_stdio (); - else - GNUNET_SCHEDULER_add_now (send_echo, NULL); + return GNUNET_OK; /* all is well-formed */ } @@ -376,66 +438,63 @@ create_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * in order to receive the next message. This doesn't need to be immediate: * can be delayed if some processing is done on the message. * - * @param cls Closure (set from #GNUNET_CADET_connect). - * @param channel Connection to the other end. - * @param channel_ctx Place to store local state associated with the channel. + * @param cls NULL * @param message The actual message. - * @return #GNUNET_OK to keep the channel open, - * #GNUNET_SYSERR to close it (signal serious error). */ -static int -data_callback (void *cls, - struct GNUNET_CADET_Channel *channel, - void **channel_ctx, - const struct GNUNET_MessageHeader *message) +static void +handle_data(void *cls, const struct GNUNET_MessageHeader *message) { + size_t payload_size = ntohs(message->size) - sizeof(*message); uint16_t len; ssize_t done; uint16_t off; const char *buf; - GNUNET_break (ch == channel); + GNUNET_CADET_receive_done(ch); if (GNUNET_YES == echo) - { - if (0 != listen_port) { - /* Just listening to echo incoming messages*/ - GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - sizeof (struct GNUNET_MessageHeader), - &data_ready, NULL); - return GNUNET_OK; - } - else - { - struct GNUNET_TIME_Relative latency; - - latency = GNUNET_TIME_absolute_get_duration (echo_time); - echo_time = GNUNET_TIME_UNIT_FOREVER_ABS; - FPRINTF (stdout, "time: %s\n", - GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); - echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - &send_echo, NULL); + if (NULL != listen_port) + { + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MessageHeader *msg; + + env = + GNUNET_MQ_msg_extra(msg, payload_size, GNUNET_MESSAGE_TYPE_CADET_CLI); + GNUNET_memcpy(&msg[1], &message[1], payload_size); + GNUNET_MQ_send(GNUNET_CADET_get_mq(ch), env); + return; + } + else + { + struct GNUNET_TIME_Relative latency; + + latency = GNUNET_TIME_absolute_get_duration(echo_time); + echo_time = GNUNET_TIME_UNIT_FOREVER_ABS; + GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, + "time: %s\n", + GNUNET_STRINGS_relative_time_to_string(latency, GNUNET_NO)); + echo_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, + &send_echo, + NULL); + } } - } - len = ntohs (message->size) - sizeof (*message); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len); - buf = (const char *) &message[1]; + len = ntohs(message->size) - sizeof(*message); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len); + buf = (const char *)&message[1]; off = 0; while (off < len) - { - done = write (1, &buf[off], len - off); - if (done <= 0) { - if (-1 == done) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, - "write"); - return GNUNET_SYSERR; + done = write(1, &buf[off], len - off); + if (done <= 0) + { + if (-1 == done) + GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "write"); + GNUNET_SCHEDULER_shutdown(); + return; + } + off += done; } - off += done; - } - return GNUNET_OK; } @@ -446,49 +505,47 @@ data_callback (void *cls, * After last peer has been reported, an additional call with NULL is done. * * @param cls Closure. - * @param peer Peer, or NULL on "EOF". - * @param tunnel Do we have a tunnel towards this peer? - * @param n_paths Number of known paths towards this peer. - * @param best_path How long is the best path? - * (0 = unknown, 1 = ourselves, 2 = neighbor) + * @param ple information about peer, or NULL on "EOF". */ static void -peers_callback (void *cls, const struct GNUNET_PeerIdentity *peer, - int tunnel, unsigned int n_paths, unsigned int best_path) +peers_callback(void *cls, const struct GNUNET_CADET_PeerListEntry *ple) { - if (NULL == peer) - { - if (GNUNET_YES != monitor_connections) + if (NULL == ple) { + plo = NULL; GNUNET_SCHEDULER_shutdown(); + return; } - return; - } - FPRINTF (stdout, "%s tunnel: %c, paths: %u\n", - GNUNET_i2s_full (peer), tunnel ? 'Y' : 'N', n_paths); + fprintf(stdout, + "%s tunnel: %c, paths: %u\n", + GNUNET_i2s_full(&ple->peer), + ple->have_tunnel ? 'Y' : 'N', + ple->n_paths); } + /** - * Method called to retrieve information about a specific peer + * Method called to retrieve information about paths to a specific peer * known to the service. * * @param cls Closure. - * @param peer Peer ID. - * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO - * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO - * @param n_paths Number of paths known towards peer. - * @param paths Array of PEER_IDs representing all paths to reach the peer. - * Each path starts with the local peer. - * Each path ends with the destination peer (given in @c peer). + * @param ppd path detail */ -void -peer_callback (void *cls, - const struct GNUNET_PeerIdentity *peer, - int tunnel, - int neighbor, - unsigned int n_paths, - struct GNUNET_PeerIdentity *paths) +static void +path_callback(void *cls, const struct GNUNET_CADET_PeerPathDetail *ppd) { + if (NULL == ppd) + { + gpo = NULL; + GNUNET_SCHEDULER_shutdown(); + return; + } + fprintf(stdout, "Path of length %u: ", ppd->path_length); + for (unsigned int i = 0; i < ppd->path_length; i++) + fprintf(stdout, + (i == ppd->target_offset) ? "*%s* " : "%s ", + GNUNET_i2s(&ppd->path[i])); + fprintf(stdout, "\n"); } @@ -496,76 +553,24 @@ peer_callback (void *cls, * Method called to retrieve information about all tunnels in CADET. * * @param cls Closure. - * @param peer Destination peer. - * @param channels Number of channels. - * @param connections Number of connections. - * @param estate Encryption state. - * @param cstate Connectivity state. + * @param td tunnel details */ -void -tunnels_callback (void *cls, - const struct GNUNET_PeerIdentity *peer, - unsigned int channels, - unsigned int connections, - uint16_t estate, - uint16_t cstate) +static void +tunnels_callback(void *cls, const struct GNUNET_CADET_TunnelDetails *td) { - if (NULL == peer) - { - if (GNUNET_YES != monitor_connections) + if (NULL == td) { + tio = NULL; GNUNET_SCHEDULER_shutdown(); + return; } - return; - } - FPRINTF (stdout, "%s [ENC: %u, CON: %u] CHs: %u, CONNs: %u\n", - GNUNET_i2s_full (peer), estate, cstate, channels, connections); -} - - -/** - * Method called to retrieve information about a specific tunnel the cadet peer - * has established, o`r is trying to establish. - * - * @param cls Closure. - * @param peer Peer towards whom the tunnel is directed. - * @param n_channels Number of channels. - * @param n_connections Number of connections. - * @param channels Channels. - * @param connections Connections. - * @param estate Encryption status. - * @param cstate Connectivity status. - */ -void -tunnel_callback (void *cls, - const struct GNUNET_PeerIdentity *peer, - unsigned int n_channels, - unsigned int n_connections, - uint32_t *channels, - struct GNUNET_CADET_Hash *connections, - unsigned int estate, - unsigned int cstate) -{ - unsigned int i; - - if (NULL != peer) - { - FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer)); - FPRINTF (stdout, "- %u channels\n", n_channels); - for (i = 0; i < n_channels; i++) - FPRINTF (stdout, " %u\n", channels[i]); - FPRINTF (stdout, "- %u connections\n", n_connections); - for (i = 0; i < n_connections; i++) - FPRINTF (stdout, " %s\n", GM_h2s (&connections[i])); - FPRINTF (stdout, "- enc state: %u\n", estate); - FPRINTF (stdout, "- con state: %u\n", cstate); - } - if (GNUNET_YES != monitor_connections) - { - GNUNET_SCHEDULER_shutdown(); - } - return; - + fprintf(stdout, + "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n", + GNUNET_i2s_full(&td->peer), + enc_2s(td->estate), + conn_2s(td->cstate), + td->channels, + td->connections); } @@ -573,17 +578,12 @@ tunnel_callback (void *cls, * Call CADET's meta API, get all peers known to a peer. * * @param cls Closure (unused). - * @param tc TaskContext */ static void -get_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +get_peers(void *cls) { - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); - return; - } - GNUNET_CADET_get_peers (mh, &peers_callback, NULL); + job = NULL; + plo = GNUNET_CADET_list_peers(my_cfg, &peers_callback, NULL); } @@ -591,68 +591,35 @@ get_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * Call CADET's monitor API, get info of one peer. * * @param cls Closure (unused). - * @param tc TaskContext */ static void -show_peer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +show_peer(void *cls) { struct GNUNET_PeerIdentity pid; - 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); - GNUNET_SCHEDULER_shutdown(); - return; - } - GNUNET_CADET_get_peer (mh, &pid, peer_callback, NULL); -} - -/** - * Call CADET's meta API, get all tunnels known to a peer. - * - * @param cls Closure (unused). - * @param tc TaskContext - */ -static void -get_tunnels (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); - return; - } - GNUNET_CADET_get_tunnels (mh, &tunnels_callback, NULL); + job = NULL; + 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); + GNUNET_SCHEDULER_shutdown(); + return; + } + gpo = GNUNET_CADET_get_path(my_cfg, &pid, &path_callback, NULL); } /** - * Call CADET's monitor API, get info of one tunnel. + * Call CADET's meta API, get all tunnels known to a peer. * * @param cls Closure (unused). - * @param tc TaskContext */ static void -show_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +get_tunnels(void *cls) { - struct GNUNET_PeerIdentity pid; - - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id, - strlen (tunnel_id), - &pid.public_key)) - { - fprintf (stderr, - _("Invalid tunnel owner `%s'\n"), - tunnel_id); - GNUNET_SCHEDULER_shutdown(); - return; - } - GNUNET_CADET_get_tunnel (mh, &pid, tunnel_callback, NULL); + job = NULL; + tio = GNUNET_CADET_list_tunnels(my_cfg, &tunnels_callback, NULL); } @@ -660,12 +627,12 @@ show_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * Call CADET's monitor API, get info of one channel. * * @param cls Closure (unused). - * @param tc TaskContext */ static void -show_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +show_channel(void *cls) { - + job = NULL; + GNUNET_break(0); } @@ -673,12 +640,12 @@ show_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * Call CADET's monitor API, get info of one connection. * * @param cls Closure (unused). - * @param tc TaskContext */ static void -show_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +show_connection(void *cls) { - + job = NULL; + GNUNET_break(0); } @@ -691,99 +658,123 @@ show_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param cfg configuration */ static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) +run(void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) { - GNUNET_CADET_InboundChannelNotificationHandler *newch = NULL; - GNUNET_CADET_ChannelEndHandler *endch = NULL; - static const struct GNUNET_CADET_MessageHandler handlers[] = { - {&data_callback, GNUNET_MESSAGE_TYPE_CADET_CLI, 0}, - {NULL, 0, 0} /* FIXME add option to monitor msg types */ - }; - static uint32_t *ports = NULL; - /* FIXME add option to monitor apps */ + struct GNUNET_MQ_MessageHandler handlers[] = + { GNUNET_MQ_hd_var_size(data, + GNUNET_MESSAGE_TYPE_CADET_CLI, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_handler_end() }; + /* FIXME add option to monitor apps */ + my_cfg = cfg; target_id = args[0]; - target_port = args[0] && args[1] ? atoi(args[1]) : 0; - if ( (0 != (request_peers | request_tunnels) - || 0 != monitor_connections - || NULL != tunnel_id - || NULL != conn_id - || NULL != channel_id) - && target_id != NULL) - { - FPRINTF (stderr, - _("You must NOT give a TARGET" - "when using 'request all' options\n")); - return; - } + if (target_id && args[1]) + target_port = args[1]; - if (NULL != target_id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating channel to %s\n", - target_id); - GNUNET_SCHEDULER_add_now (&create_channel, NULL); - endch = &channel_ended; - } - else if (0 != listen_port) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Listen\n"); - newch = &channel_incoming; - endch = &channel_ended; - ports = GNUNET_malloc (sizeof (uint32_t) * 2); - ports[0] = listen_port; - } - else if (NULL != peer_id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n"); - GNUNET_SCHEDULER_add_now (&show_peer, NULL); - } - else if (NULL != tunnel_id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show tunnel\n"); - GNUNET_SCHEDULER_add_now (&show_tunnel, NULL); - } + if ((0 != (request_peers | request_tunnels) || NULL != conn_id || + NULL != channel_id) && + target_id != NULL) + { + fprintf(stderr, + _("Extra arguments are not applicable " + "in combination with this option.\n")); + return; + } + + if (NULL != peer_id) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show peer\n"); + job = GNUNET_SCHEDULER_add_now(&show_peer, NULL); + } else if (NULL != channel_id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n"); - GNUNET_SCHEDULER_add_now (&show_channel, NULL); - } + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show channel\n"); + job = GNUNET_SCHEDULER_add_now(&show_channel, NULL); + } else if (NULL != conn_id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n"); - GNUNET_SCHEDULER_add_now (&show_connection, NULL); - } + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show connection\n"); + job = GNUNET_SCHEDULER_add_now(&show_connection, NULL); + } else if (GNUNET_YES == request_peers) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n"); - GNUNET_SCHEDULER_add_now (&get_peers, NULL); - } + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n"); + job = GNUNET_SCHEDULER_add_now(&get_peers, NULL); + } else if (GNUNET_YES == request_tunnels) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n"); - GNUNET_SCHEDULER_add_now (&get_tunnels, NULL); - } - else - { - FPRINTF (stderr, "No action requested\n"); - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to cadet\n"); - mh = GNUNET_CADET_connect (cfg, - NULL, /* cls */ - newch, /* new channel */ - endch, /* cleaner */ - handlers, - ports); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done\n"); + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n"); + job = GNUNET_SCHEDULER_add_now(&get_tunnels, NULL); + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET service\n"); + mh = GNUNET_CADET_connect(cfg); + GNUNET_SCHEDULER_add_shutdown(&shutdown_task, NULL); if (NULL == mh) - GNUNET_SCHEDULER_add_now (shutdown_task, NULL); - else - sd = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - shutdown_task, NULL); + { + GNUNET_SCHEDULER_shutdown(); + return; + } + if (NULL != listen_port) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening CADET listen port\n"); + GNUNET_CRYPTO_hash(listen_port, strlen(listen_port), &porthash); + lp = GNUNET_CADET_open_port(mh, + &porthash, + &channel_incoming, + NULL, + NULL /* window changes */, + &channel_ended, + handlers); + } + if (NULL != target_id) + { + struct GNUNET_PeerIdentity pid; + + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_public_key_from_string(target_id, + strlen(target_id), + &pid.public_key)) + { + GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, + _("Invalid target `%s'\n"), + target_id); + GNUNET_SCHEDULER_shutdown(); + return; + } + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Connecting to `%s:%s'\n", + target_id, + target_port); + GNUNET_CRYPTO_hash(target_port, strlen(target_port), &porthash); + ch = GNUNET_CADET_channel_create(mh, + NULL, + &pid, + &porthash, + NULL /* window changes */, + &channel_ended, + handlers); + if (GNUNET_YES == echo) + { + echo_task = GNUNET_SCHEDULER_add_now(&send_echo, NULL); + } + else + { + listen_stdio(); + } + } + if ((NULL == lp) && (NULL == job) && (NULL == ch)) + { + GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, _("No action requested\n")); + GNUNET_SCHEDULER_shutdown(); + return; + } } @@ -795,57 +786,65 @@ run (void *cls, char *const *args, const char *cfgfile, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main(int argc, char *const *argv) { int res; - const char helpstr[] = "Create channels and retreive info about cadets status."; - static const struct GNUNET_GETOPT_CommandLineOption options[] = { -// {'a', "channel", "TUNNEL_ID:CHANNEL_ID", -// gettext_noop ("provide information about a particular channel"), -// GNUNET_YES, &GNUNET_GETOPT_set_string, &channel_id}, - {'C', "connection", "CONNECTION_ID", - gettext_noop ("provide information about a particular connection"), - GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id}, - {'e', "echo", NULL, - gettext_noop ("activate echo mode"), - GNUNET_NO, &GNUNET_GETOPT_set_one, &echo}, -// {'m', "monitor", NULL, -// gettext_noop ("provide information about all events (continuously)"), -// GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor_mode}, - {'o', "open-port", NULL, - gettext_noop ("port to listen to (default; 0)"), - GNUNET_YES, &GNUNET_GETOPT_set_uint, &listen_port}, - {'p', "peer", "PEER_ID", - gettext_noop ("provide information about a patricular peer"), - GNUNET_YES, &GNUNET_GETOPT_set_string, &peer_id}, - {'P', "peers", NULL, - gettext_noop ("provide information about all peers"), - GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers}, - {'t', "tunnel", "TUNNEL_ID", - gettext_noop ("provide information about a particular tunnel"), - GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id}, - {'T', "tunnels", NULL, - gettext_noop ("provide information about all tunnels"), - GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels}, - + const char helpstr[] = + "Create tunnels and retrieve info about CADET's status."; + struct GNUNET_GETOPT_CommandLineOption options[] = + { /* I would use the terminology 'circuit' here... --lynX */ + GNUNET_GETOPT_option_string( + 'C', + "connection", + "CONNECTION_ID", + gettext_noop("Provide information about a particular connection"), + &conn_id), + GNUNET_GETOPT_option_flag('e', + "echo", + gettext_noop("Activate echo mode"), + &echo), + GNUNET_GETOPT_option_string( + 'o', + "open-port", + "SHARED_SECRET", + gettext_noop( + "Listen for connections using a shared secret among sender and recipient"), + &listen_port), + GNUNET_GETOPT_option_string('p', + "peer", + "PEER_ID", + gettext_noop( + "Provide information about a patricular peer"), + &peer_id), + GNUNET_GETOPT_option_flag('P', + "peers", + gettext_noop( + "Provide information about all peers"), + &request_peers), + GNUNET_GETOPT_option_flag('T', + "tunnels", + gettext_noop( + "Provide information about all tunnels"), + &request_tunnels), GNUNET_GETOPT_OPTION_END }; - monitor_connections = GNUNET_NO; - - if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv)) return 2; - res = GNUNET_PROGRAM_run (argc, argv, "gnunet-cadet (OPTIONS | TARGET PORT)", - gettext_noop (helpstr), - options, &run, NULL); + res = GNUNET_PROGRAM_run(argc, + argv, + "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)", + gettext_noop(helpstr), + options, + &run, + NULL); - GNUNET_free ((void *) argv); + GNUNET_free((void *)argv); if (GNUNET_OK == res) return 0; - else - return 1; + return 1; } /* end of gnunet-cadet.c */