From 24712c94e185b72c30da25ea1b3a1784bde0defa Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 11 Apr 2014 11:49:51 +0000 Subject: towards fixing #3363: replacing old iteration API with new monitoring API for core (needs testing, gnunet-core incomplete) --- src/core/core_api_iterate_peers.c | 242 ++++++++++++++++++++++++-------------- 1 file changed, 155 insertions(+), 87 deletions(-) (limited to 'src/core/core_api_iterate_peers.c') diff --git a/src/core/core_api_iterate_peers.c b/src/core/core_api_iterate_peers.c index 4889e638a..425d3579c 100644 --- a/src/core/core_api_iterate_peers.c +++ b/src/core/core_api_iterate_peers.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2009-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -19,7 +19,7 @@ */ /** - * @file core/core_api_iterate_peers.c + * @file core/core_api_monitor_peers.c * @brief implementation of the peer_iterate function * @author Christian Grothoff * @author Nathan Evans @@ -29,15 +29,23 @@ #include "core.h" -struct GNUNET_CORE_RequestContext +/** + * Handle to a CORE monitoring operation. + */ +struct GNUNET_CORE_MonitorHandle { + + /** + * Our configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + /** * Our connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** - * Handle for transmitting a request. */ struct GNUNET_CLIENT_TransmitHandle *th; @@ -45,140 +53,200 @@ struct GNUNET_CORE_RequestContext /** * Function called with the peer. */ - GNUNET_CORE_ConnectEventHandler peer_cb; + GNUNET_CORE_MonitorCallback peer_cb; /** - * Peer to check for. + * Closure for @e peer_cb. */ - struct GNUNET_PeerIdentity *peer; - - /** - * Closure for peer_cb. - */ - void *cb_cls; + void *peer_cb_cls; }; /** - * Receive reply from core service with information about a peer. + * Transmits the monitor request to the CORE service. + * + * Function is called to notify a client about the socket begin ready + * to queue more data. @a buf will be NULL and @a size zero if the + * socket was closed for writing in the meantime. + * + * @param cls closure, our `struct GNUNET_CORE_MonitorHandle *` + * @param size number of bytes available in @a buf + * @param buf where the callee should write the message + * @return number of bytes written to @a buf + */ +static size_t +transmit_monitor_request (void *cls, + size_t size, + void *buf); + + +/** + * Protocol error, reconnect to CORE service and notify + * client. + * + * @param mh monitoring session to reconnect to CORE + */ +static void +reconnect (struct GNUNET_CORE_MonitorHandle *mh) +{ + GNUNET_CLIENT_disconnect (mh->client); + /* FIXME: use backoff? */ + mh->client = GNUNET_CLIENT_connect ("core", mh->cfg); + GNUNET_assert (NULL != mh->client); + mh->th = + GNUNET_CLIENT_notify_transmit_ready (mh->client, + sizeof (struct GNUNET_MessageHeader), + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, + &transmit_monitor_request, mh); + /* notify callback about reconnect */ + mh->peer_cb (mh->peer_cb_cls, + NULL, + GNUNET_CORE_KX_CORE_DISCONNECT, + GNUNET_TIME_UNIT_FOREVER_ABS); +} + + +/** + * Receive reply from CORE service with information about a peer. * - * @param cls our 'struct GNUNET_CORE_RequestContext *' + * @param cls our `struct GNUNET_CORE_MonitorHandle *` * @param msg NULL on error or last entry */ static void -receive_info (void *cls, const struct GNUNET_MessageHeader *msg) +receive_info (void *cls, + const struct GNUNET_MessageHeader *msg) { - struct GNUNET_CORE_RequestContext *request_context = cls; - const struct ConnectNotifyMessage *connect_message; + struct GNUNET_CORE_MonitorHandle *mh = cls; + const struct MonitorNotifyMessage *mon_message; uint16_t msize; - /* Handle last message or error case, disconnect and clean up */ - if ((msg == NULL) || - ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END) && - (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader)))) + if (NULL == msg) { - if (request_context->peer_cb != NULL) - request_context->peer_cb (request_context->cb_cls, NULL); - GNUNET_CLIENT_disconnect (request_context->client); - GNUNET_free (request_context); + reconnect (mh); return; } - msize = ntohs (msg->size); /* Handle incorrect message type or size, disconnect and clean up */ - if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) || - (msize < sizeof (struct ConnectNotifyMessage))) + if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY) || + (sizeof (struct MonitorNotifyMessage) != msize)) { GNUNET_break (0); - if (request_context->peer_cb != NULL) - request_context->peer_cb (request_context->cb_cls, NULL); - GNUNET_CLIENT_disconnect (request_context->client); - GNUNET_free (request_context); + reconnect (mh); return; } - connect_message = (const struct ConnectNotifyMessage *) msg; - if (msize != sizeof (struct ConnectNotifyMessage)) - { - GNUNET_break (0); - if (request_context->peer_cb != NULL) - request_context->peer_cb (request_context->cb_cls, NULL); - GNUNET_CLIENT_disconnect (request_context->client); - GNUNET_free (request_context); - return; - } - /* Normal case */ - if (request_context->peer_cb != NULL) - request_context->peer_cb (request_context->cb_cls, &connect_message->peer); - GNUNET_CLIENT_receive (request_context->client, &receive_info, - request_context, GNUNET_TIME_UNIT_FOREVER_REL); + mon_message = (const struct MonitorNotifyMessage *) msg; + GNUNET_CLIENT_receive (mh->client, + &receive_info, mh, + GNUNET_TIME_UNIT_FOREVER_REL); + mh->peer_cb (mh->peer_cb_cls, + &mon_message->peer, + (enum GNUNET_CORE_KxState) ntohl (mon_message->state), + GNUNET_TIME_absolute_ntoh (mon_message->timeout)); } /** - * Function called to notify a client about the socket - * begin ready to queue more data. "buf" will be - * NULL and "size" zero if the socket was closed for - * writing in the meantime. + * Transmits the monitor request to the CORE service. * - * @param cls closure, always NULL - * @param size number of bytes available in buf + * Function is called to notify a client about the socket begin ready + * to queue more data. @a buf will be NULL and @a size zero if the + * socket was closed for writing in the meantime. + * + * @param cls closure, our `struct GNUNET_CORE_MonitorHandle *` + * @param size number of bytes available in @a buf * @param buf where the callee should write the message - * @return number of bytes written to buf + * @return number of bytes written to @a buf */ static size_t -transmit_request (void *cls, size_t size, void *buf) +transmit_monitor_request (void *cls, + size_t size, + void *buf) { + struct GNUNET_CORE_MonitorHandle *mh = cls; struct GNUNET_MessageHeader *msg; int msize; msize = sizeof (struct GNUNET_MessageHeader); - if ((size < msize) || (buf == NULL)) + if ((size < msize) || (NULL == buf)) + { + reconnect (mh); return 0; + } msg = (struct GNUNET_MessageHeader *) buf; msg->size = htons (msize); - msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS); - + msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS); + GNUNET_CLIENT_receive (mh->client, + &receive_info, mh, + GNUNET_TIME_UNIT_FOREVER_REL); return msize; } /** - * Iterate over all currently connected peers. - * Calls peer_cb with each connected peer, and then - * once with NULL to indicate that all peers have - * been handled. + * Monitor connectivity and KX status of all peers known to CORE. + * Calls @a peer_cb with the current status for each connected peer, + * and then once with NULL to indicate that all peers that are + * currently active have been handled. After that, the iteration + * continues until it is cancelled. Normal users of the CORE API are + * not expected to use this function. It is different in that it + * truly lists all connections (including those where the KX is in + * progress), not just those relevant to the application. This + * function is used by special applications for diagnostics. * - * @param cfg configuration to use + * @param cfg configuration handle * @param peer_cb function to call with the peer information - * @param cb_cls closure for @a peer_cb - * @return #GNUNET_OK if iterating, #GNUNET_SYSERR on error + * @param peer_cb_cls closure for @a peer_cb + * @return NULL on error */ -int -GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_CORE_ConnectEventHandler peer_cb, - void *cb_cls) +struct GNUNET_CORE_MonitorHandle * +GNUNET_CORE_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg, + GNUNET_CORE_MonitorCallback peer_cb, + void *peer_cb_cls) { - struct GNUNET_CORE_RequestContext *request_context; + struct GNUNET_CORE_MonitorHandle *mh; struct GNUNET_CLIENT_Connection *client; + GNUNET_assert (NULL != peer_cb); client = GNUNET_CLIENT_connect ("core", cfg); - if (client == NULL) - return GNUNET_SYSERR; - request_context = GNUNET_new (struct GNUNET_CORE_RequestContext); - request_context->client = client; - request_context->peer_cb = peer_cb; - request_context->cb_cls = cb_cls; - - request_context->th = - GNUNET_CLIENT_notify_transmit_ready (client, - sizeof (struct GNUNET_MessageHeader), - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, &transmit_request, NULL); - - GNUNET_CLIENT_receive (client, &receive_info, request_context, - GNUNET_TIME_UNIT_FOREVER_REL); - return GNUNET_OK; + if (NULL == client) + return NULL; + mh = GNUNET_new (struct GNUNET_CORE_MonitorHandle); + mh->cfg = cfg; + mh->client = client; + mh->peer_cb = peer_cb; + mh->peer_cb_cls = peer_cb_cls; + mh->th = + GNUNET_CLIENT_notify_transmit_ready (client, + sizeof (struct GNUNET_MessageHeader), + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, + &transmit_monitor_request, mh); + return mh; } -/* end of core_api_iterate_peers.c */ + +/** + * Stop monitoring CORE activity. + * + * @param mh monitor to stop + */ +void +GNUNET_CORE_monitor_stop (struct GNUNET_CORE_MonitorHandle *mh) +{ + if (NULL != mh->th) + { + GNUNET_CLIENT_notify_transmit_ready_cancel (mh->th); + mh->th = NULL; + } + if (NULL != mh->client) + { + GNUNET_CLIENT_disconnect (mh->client); + mh->client = NULL; + } + GNUNET_free (mh); +} + + +/* end of core_api_monitor_peers.c */ -- cgit v1.2.3