From: Christian Grothoff Date: Sat, 26 Jan 2019 23:36:47 +0000 (+0100) Subject: more work on #5385 X-Git-Tag: v0.11.0~113 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=65b339b7ce68fcbaec9df6f66e8ed45e60b39ce1;p=oweals%2Fgnunet.git more work on #5385 --- diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am index bccaf2cd9..62eaad38c 100644 --- a/src/cadet/Makefile.am +++ b/src/cadet/Makefile.am @@ -34,6 +34,8 @@ lib_LTLIBRARIES = \ libgnunetcadet_la_SOURCES = \ cadet_api.c \ + cadet_api_get_peer.c \ + cadet_api_list_peers.c \ cadet_api_helper.c libgnunetcadet_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ diff --git a/src/cadet/cadet_api_get_channel.c b/src/cadet/cadet_api_get_channel.c index cd90f5b78..d41337522 100644 --- a/src/cadet/cadet_api_get_channel.c +++ b/src/cadet/cadet_api_get_channel.c @@ -31,9 +31,8 @@ #include "cadet_protocol.h" - /** - * Ugly legacy hack. + * Operation handle. */ struct GNUNET_CADET_ChannelMonitor { @@ -48,23 +47,81 @@ struct GNUNET_CADET_ChannelMonitor */ void *channel_cb_cls; + /** + * Configuration we use. + */ const struct GNUNET_CONFIGURATION_Handle *cfg; + /** + * Message queue to talk to CADET service. + */ struct GNUNET_MQ_Handle *mq; + /** + * Task to reconnect. + */ + struct GNUNET_SCHEDULER_Task *reconnect_task; + + /** + * Backoff for reconnect attempts. + */ + struct GNUNET_TIME_Relative backoff; + + /** + * Peer we want information about. + */ struct GNUNET_PeerIdentity peer; - + + /** + * Channel we want information about. + */ uint32_t /* UGH */ channel_number; }; +/** + * Reconnect to the service and try again. + * + * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation + */ +static void +reconnect (void *cls); + + +/** + * Function called on connection trouble. Reconnects. + * + * @param cls a `struct GNUNET_CADET_ChannelMonitor`` + * @param error error code from MQ + */ +static void +error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_CADET_ChannelMonitor *cm = cls; + + GNUNET_MQ_destroy (cm->mq); + cm->mq = NULL; + cm->backoff = GNUNET_TIME_randomized_backoff (cm->backoff, + GNUNET_TIME_UNIT_MINUTES); + cm->reconnect_task = GNUNET_SCHEDULER_add_delayed (cm->backoff, + &reconnect, + cm); +} + +/** + * Reconnect to the service and try again. + * + * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation + */ static void reconnect (void *cls) { struct GNUNET_CADET_ChannelMonitor *cm = cls; struct GNUNET_MQ_MessageHandler *handlers[] = { + FIXME } struct GNUNET_MessageHeader *msg; struct GNUNET_MQ_Envelope *env; @@ -100,10 +157,45 @@ GNUNET_CADET_get_channel (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CADET_ChannelCB callback, void *callback_cls) { + struct GNUNET_CADET_ChannelMonitor *cm; + + if (NULL == callback) + { + GNUNET_break (0); + return NULL; + } + cm = GNUNET_new (struct GNUNET_CADET_ChannelMonitor); + cm->peer_cb = callback; + cm->peer_cb_cls = callback_cls; + cm->cfg = cfg; + cm->id = *id; + reconnect (cm); + if (NULL == cm->mq) + { + GNUNET_free (cm); + return NULL; + } + return cm; } +/** + * Cancel a channel monitor request. The callback will not be called (anymore). + * + * @param h Cadet handle. + * @return Closure that was given to #GNUNET_CADET_get_channel(). + */ void * GNUNET_CADET_get_channel_cancel (struct GNUNET_CADET_ChannelMonitor *cm) { + void *ret = cm->peer_cb_cls; + + if (NULL != cm->mq) + GNUNET_MQ_destroy (cm->mq); + if (NULL != cm->reconnect_task) + GNUNET_SCHEDULER_cancel (cm->reconnect_task); + GNUNET_free (cm); + return ret; } + +/* end of cadet_api_get_channel.c */ diff --git a/src/cadet/cadet_api_get_peer.c b/src/cadet/cadet_api_get_peer.c index c7d6e324b..e86c1567c 100644 --- a/src/cadet/cadet_api_get_peer.c +++ b/src/cadet/cadet_api_get_peer.c @@ -32,7 +32,7 @@ /** - * + * Operation handle. */ struct GNUNET_CADET_GetPeer { @@ -43,15 +43,35 @@ struct GNUNET_CADET_GetPeer GNUNET_CADET_PeerCB peer_cb; /** - * Info callback closure for @c info_cb. + * Closure for @c peer_cb. */ void *peer_cb_cls; - struct GNUNET_PeerIdentity id; - + /** + * Message queue to talk to CADET service. + */ struct GNUNET_MQ_Handle *mq; + /** + * Configuration we use. + */ const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Task to reconnect. + */ + struct GNUNET_SCHEDULER_Task *reconnect_task; + + /** + * Backoff for reconnect attempts. + */ + struct GNUNET_TIME_Relative backoff; + + /** + * Peer we want information about. + */ + struct GNUNET_PeerIdentity id; + }; @@ -103,11 +123,6 @@ handle_get_peer (void *cls, int neighbor; unsigned int peers; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "number of paths %u\n", - ntohs (message->paths)); - paths = ntohs (message->paths); paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; peers = (ntohs (message->header.size) - sizeof (*message)) @@ -117,11 +132,9 @@ handle_get_peer (void *cls, for (unsigned int i = 0; i < peers; i++) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " %s\n", - GNUNET_i2s (&paths_array[i])); path_length++; - if (0 == memcmp (&paths_array[i], &message->destination, + if (0 == memcmp (&paths_array[i], + &message->destination, sizeof (struct GNUNET_PeerIdentity))) { if (1 == path_length) @@ -130,7 +143,7 @@ handle_get_peer (void *cls, } } - /* Call Callback with tunnel info. */ + /* Call Callback with tunnel info */ paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; gp->peer_cb (gp->peer_cb_cls, &message->destination, @@ -144,20 +157,57 @@ handle_get_peer (void *cls, } +/** + * Reconnect to the service and try again. + * + * @param cls a `struct GNUNET_CADET_GetPeer` operation + */ +static void +reconnect (void *cls); + + +/** + * Function called on connection trouble. Reconnects. + * + * @param cls a `struct GNUNET_CADET_GetPeer` + * @param error error code from MQ + */ +static void +error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_CADET_GetPeer *gp = cls; + + GNUNET_MQ_destroy (gp->mq); + gp->mq = NULL; + gp->backoff = GNUNET_TIME_randomized_backoff (gp->backoff, + GNUNET_TIME_UNIT_MINUTES); + gp->reconnect_task = GNUNET_SCHEDULER_add_delayed (gp->backoff, + &reconnect, + gp); +} + + +/** + * Reconnect to the service and try again. + * + * @param cls a `struct GNUNET_CADET_GetPeer` operation + */ static void reconnect (void *cls) { struct GNUNET_CADET_GetPeer *gp = cls; - struct GNUNET_MQ_MessageHandler *handlers[] = { + struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size (get_peer, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, struct GNUNET_CADET_LocalInfoPeer, - h), + gp), GNUNET_MQ_handler_end () - } + }; struct GNUNET_CADET_LocalInfo *msg; struct GNUNET_MQ_Envelope *env; + gp->reconnect_task = NULL; gp->mq = GNUNET_CLIENT_connect (gp->cfg, "cadet", handlers, @@ -168,7 +218,7 @@ reconnect (void *cls) env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); msg->peer = gp->id; - GNUNET_MQ_send (lt->mq, + GNUNET_MQ_send (gp->mq, env); } @@ -211,15 +261,24 @@ GNUNET_CADET_get_peer (const struct GNUNET_CONFIGURATION_Handle *cfg, } - +/** + * Cancel @a gp operation. + * + * @param gp operation to cancel + * @return closure from #GNUNET_CADET_get_peer(). + */ void * GNUNET_CADET_get_peer_cancel (struct GNUNET_CADET_GetPeer *gp) { void *ret = gp->peer_cb_cls; - - GNUNET_MQ_disconnect (gp->mq); + + if (NULL != gp->mq) + GNUNET_MQ_destroy (gp->mq); + if (NULL != gp->reconnect_task) + GNUNET_SCHEDULER_cancel (gp->reconnect_task); GNUNET_free (gp); return ret; } +/* end of cadet_api_get_peer.c */ diff --git a/src/cadet/cadet_api_list_peers.c b/src/cadet/cadet_api_list_peers.c index f6563a290..d53bcf65d 100644 --- a/src/cadet/cadet_api_list_peers.c +++ b/src/cadet/cadet_api_list_peers.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2011, 2017 GNUnet e.V. + Copyright (C) 2011, 2017, 2019 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 @@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL3.0-or-later */ /** - * @file cadet/cadet_api.c + * @file cadet/cadet_api_list_peers.c * @brief cadet api: client implementation of cadet service * @author Bartlomiej Polot * @author Christian Grothoff @@ -31,9 +31,8 @@ #include "cadet_protocol.h" - /** - * Ugly legacy hack. + * Operation handle. */ struct GNUNET_CADET_PeersLister { @@ -47,33 +46,34 @@ struct GNUNET_CADET_PeersLister * Info callback closure for @c info_cb. */ void *peers_cb_cls; -}; + /** + * Message queue to talk to CADET service. + */ + struct GNUNET_MQ_Handle *mq; -/** - * Send message of @a type to CADET service of @a h - * - * @param h handle to CADET service - * @param type message type of trivial information request to send - */ -static void -send_info_request (struct GNUNET_CADET_Handle *h, - uint16_t type) -{ - struct GNUNET_MessageHeader *msg; - struct GNUNET_MQ_Envelope *env; + /** + * Configuration we use. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; - env = GNUNET_MQ_msg (msg, - type); - GNUNET_MQ_send (h->mq, - env); -} + /** + * Task to reconnect. + */ + struct GNUNET_SCHEDULER_Task *reconnect_task; + + /** + * Backoff for reconnect attempts. + */ + struct GNUNET_TIME_Relative backoff; + +}; /** * Check that message received from CADET service is well-formed. * - * @param cls the `struct GNUNET_CADET_Handle` + * @param cls the `struct GNUNET_CADET_PeersLister` * @param message the message we got * @return #GNUNET_OK if the message is well-formed, * #GNUNET_SYSERR otherwise @@ -94,60 +94,97 @@ check_get_peers (void *cls, } +// FIXME: use two different message types instead of this mess! /** * Process a local reply about info on all tunnels, pass info to the user. * - * @param cls Closure (Cadet handle). + * @param cls a `struct GNUNET_CADET_PeersLister` * @param msg Message itself. */ static void handle_get_peers (void *cls, const struct GNUNET_MessageHeader *msg) { - struct GNUNET_CADET_Handle *h = cls; + struct GNUNET_CADET_PeersLister *pl = cls; const struct GNUNET_CADET_LocalInfoPeer *info = (const struct GNUNET_CADET_LocalInfoPeer *) msg; - if (NULL == h->info_cb.peers_cb) - return; if (sizeof (struct GNUNET_CADET_LocalInfoPeer) == ntohs (msg->size)) - h->info_cb.peers_cb (h->info_cls, - &info->destination, - (int) ntohs (info->tunnel), - (unsigned int) ntohs (info->paths), - 0); + pl->peers_cb (pl->peers_cb_cls, + &info->destination, + (int) ntohs (info->tunnel), + (unsigned int) ntohs (info->paths), + 0); else - h->info_cb.peers_cb (h->info_cls, - NULL, - 0, - 0, - 0); + { + pl->peers_cb (pl->peers_cb_cls, + NULL, + 0, + 0, + 0); + GNUNET_CADET_list_peers_cancel (pl); + } +} + + +/** + * Reconnect to the service and try again. + * + * @param cls a `struct GNUNET_CADET_PeersLister` operation + */ +static void +reconnect (void *cls); + + +/** + * Function called on connection trouble. Reconnects. + * + * @param cls a `struct GNUNET_CADET_PeersLister` + * @param error error code from MQ + */ +static void +error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_CADET_PeersLister *pl = cls; + + GNUNET_MQ_destroy (pl->mq); + pl->mq = NULL; + pl->backoff = GNUNET_TIME_randomized_backoff (pl->backoff, + GNUNET_TIME_UNIT_MINUTES); + pl->reconnect_task = GNUNET_SCHEDULER_add_delayed (pl->backoff, + &reconnect, + pl); } +/** + * Reconnect to the service and try again. + * + * @param cls a `struct GNUNET_CADET_PeersLister` operation + */ static void reconnect (void *cls) { - struct GNUNET_CADET_ListTunnels *lt = cls; - struct GNUNET_MQ_MessageHandler *handlers[] = { - GNUNET_MQ_hd_var_size (get_peers, + struct GNUNET_CADET_PeersLister *pl = cls; + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_var_size (get_peers, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, struct GNUNET_MessageHeader, - h), + pl), GNUNET_MQ_handler_end () - } + }; struct GNUNET_MessageHeader *msg; struct GNUNET_MQ_Envelope *env; - cm->mq = GNUNET_CLIENT_connect (cm->cfg, + pl->mq = GNUNET_CLIENT_connect (pl->cfg, "cadet", handlers, &error_handler, - cm); - + pl); env = GNUNET_MQ_msg (msg, - type); - GNUNET_MQ_send (cm->mq, + GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); + GNUNET_MQ_send (pl->mq, env); } @@ -157,50 +194,54 @@ reconnect (void *cls) * The callback will be called for every peer known to the service. * Only one info request (of any kind) can be active at once. * - * WARNING: unstable API, likely to change in the future! - * * @param h Handle to the cadet peer. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. - * @return #GNUNET_OK / #GNUNET_SYSERR + * @return NULL on error */ struct GNUNET_CADET_PeersLister * GNUNET_CADET_list_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CADET_PeersCB callback, void *callback_cls) { - if (NULL != h->info_cb.peers_cb) + struct GNUNET_CADET_PeersLister *pl; + + if (NULL == callback) { GNUNET_break (0); - return GNUNET_SYSERR; + return NULL; + } + pl = GNUNET_new (struct GNUNET_CADET_PeersLister); + pl->peers_cb = callback; + pl->peers_cb_cls = callback_cls; + pl->cfg = cfg; + reconnect (pl); + if (NULL == pl->mq) + { + GNUNET_free (pl); + return NULL; } - send_info_request (h, - GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); - h->info_cb.peers_cb = callback; - h->info_cls = callback_cls; - return GNUNET_OK; + return pl; } /** * Cancel a peer info request. The callback will not be called (anymore). * - * WARNING: unstable API, likely to change in the future! - * - * @param h Cadet handle. + * @param pl operation handle * @return Closure given to GNUNET_CADET_get_peers(). */ void * GNUNET_CADET_list_peers_cancel (struct GNUNET_CADET_PeersLister *pl) { - void *cls = h->info_cls; - - h->info_cb.peers_cb = NULL; - h->info_cls = NULL; - return cls; + void *ret = pl->peers_cb_cls; + + if (NULL != pl->mq) + GNUNET_MQ_destroy (pl->mq); + if (NULL != pl->reconnect_task) + GNUNET_SCHEDULER_cancel (pl->reconnect_task); + GNUNET_free (pl); + return ret; } - - - - +/* end of cadet_api_list_peers.c */ diff --git a/src/cadet/cadet_api_list_tunnels.c b/src/cadet/cadet_api_list_tunnels.c index 96343bf4d..7d0534e41 100644 --- a/src/cadet/cadet_api_list_tunnels.c +++ b/src/cadet/cadet_api_list_tunnels.c @@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL3.0-or-later */ /** - * @file cadet/cadet_api.c + * @file cadet/cadet_api_list_tunnels.c * @brief cadet api: client implementation of cadet service * @author Bartlomiej Polot * @author Christian Grothoff @@ -31,9 +31,8 @@ #include "cadet_protocol.h" - /** - * Ugly legacy hack. + * Operation handle. */ struct GNUNET_CADET_ListTunnels { @@ -47,6 +46,27 @@ struct GNUNET_CADET_ListTunnels * Info callback closure for @c tunnels_cb. */ void *tunnels_cb_cls; + + /** + * Message queue to talk to CADET service. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Configuration we use. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Task to reconnect. + */ + struct GNUNET_SCHEDULER_Task *reconnect_task; + + /** + * Backoff for reconnect attempts. + */ + struct GNUNET_TIME_Relative backoff; + }; diff --git a/src/include/gnunet_cadet_service.h b/src/include/gnunet_cadet_service.h index fb4499db0..2ac98e621 100644 --- a/src/include/gnunet_cadet_service.h +++ b/src/include/gnunet_cadet_service.h @@ -411,6 +411,12 @@ GNUNET_CADET_get_channel (const struct GNUNET_CONFIGURATION_Handle *cfg, void *callback_cls); +/** + * Cancel a channel monitor request. The callback will not be called (anymore). + * + * @param h Cadet handle. + * @return Closure that was given to #GNUNET_CADET_get_channel(). + */ void * GNUNET_CADET_get_channel_cancel (struct GNUNET_CADET_ChannelMonitor *cm); @@ -444,13 +450,10 @@ struct GNUNET_CADET_PeersLister; * The callback will be called for every peer known to the service. * Only one info request (of any kind) can be active at once. * - * WARNING: unstable API, likely to change in the future! - * * @param h Handle to the cadet peer. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. - * - * @return #GNUNET_OK / #GNUNET_SYSERR + * @return NULL on error */ struct GNUNET_CADET_PeersLister * GNUNET_CADET_list_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, @@ -461,14 +464,13 @@ GNUNET_CADET_list_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, /** * Cancel a peer info request. The callback will not be called (anymore). * - * @param h Cadet handle. + * @param pl operation handle * @return Closure that was given to #GNUNET_CADET_list_peers(). */ void * GNUNET_CADET_list_peers_cancel (struct GNUNET_CADET_PeersLister *pl); - /** * Method called to retrieve information about a specific peer * known to the service. @@ -493,6 +495,9 @@ typedef void int finished_with_paths); +/** + * Handle to cancel #GNUNET_CADET_get_peer() operation. + */ struct GNUNET_CADET_GetPeer; /** @@ -500,14 +505,11 @@ struct GNUNET_CADET_GetPeer; * The callback will be called for the tunnel once. * Only one info request (of any kind) can be active at once. * - * WARNING: unstable API, likely to change in the future! - * * @param h Handle to the cadet peer. * @param id Peer whose tunnel to examine. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. - * - * @return #GNUNET_OK / #GNUNET_SYSERR + * @return NULL on error */ struct GNUNET_CADET_GetPeer * GNUNET_CADET_get_peer (const struct GNUNET_CONFIGURATION_Handle *cfg, @@ -516,6 +518,12 @@ GNUNET_CADET_get_peer (const struct GNUNET_CONFIGURATION_Handle *cfg, void *callback_cls); +/** + * Cancel @a gp operation. + * + * @param gp operation to cancel + * @return closure from #GNUNET_CADET_get_peer(). + */ void * GNUNET_CADET_get_peer_cancel (struct GNUNET_CADET_GetPeer *gp);