From: Christian Grothoff Date: Wed, 20 Jan 2010 13:51:20 +0000 (+0000) Subject: fixing core API issues X-Git-Tag: initial-import-from-subversion-38251~22921 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=7d9f187d106394b2451660294df9428eb50e82d7;p=oweals%2Fgnunet.git fixing core API issues --- diff --git a/BUGS b/BUGS index f5dd633a5..94623b45b 100644 --- a/BUGS +++ b/BUGS @@ -82,12 +82,7 @@ sane end-user should care about this codebase yet anyway. - better tracking of which config changes actually need to cause process restarts by ARM. - have way to specify dependencies between services (to manage ARM restarts better) * CORE: - - code currently notifies clients about "encrypted" connections being up well before - we get the encrypted PONG; sometimes this may be OK (for topology killing - unwanted connnections), but of course not in general. I suspect we want - to signal on PONG and have topology hook directly into transport to - kill plaintext connections before they have a chance to become encrypted - (may require minor hack in transport API) + - test case (test_core_api) hangs for a while (some timeout task not killed somewhere?) - [./core/gnunet-service-core.c:469]: (style) struct or union member 'Neighbour::message_queue_size' is never used - [./core/test_core_api_start_only.c:50]: (style) struct or union member 'PeerContext::id' is never used diff --git a/TODO b/TODO index 156910858..5f031772a 100644 --- a/TODO +++ b/TODO @@ -12,18 +12,16 @@ away), in order in which they will likely be done: * UPNP [Milan] Urgent items (before announcing ng.gnunet.org): +* CORE: + - test currently fails spectacularly + - request disconnect not implemented (needs better transport API) * topology - - considers peers 'connected' well before they actually are - (since core notifies about it too early?); - (forced) disconnect does not work (also CORE API issue) - needs testing (not sure the current testcase does much...) * hostlist - test fails (looks like it works, but that's because of a bad connectivity notification; somehow core is unable to send messages successfully via transport) -* CORE: - - core notifies about connects "too early" (when we have not yet - succeeded with the full key exchange) [see also: BUGS] * FS (basic anonymous FS only) - implement FS service (P2P operations) + how to send queries (soliciting is not there in core; do we @@ -51,6 +49,8 @@ Urgent items (before announcing ng.gnunet.org): [=> eliminate for need to tell ARM about service starts most of the time!] * HELLO: - need function to test "equivalency" of HELLOs; use in topology! +* CORE: + - outbound message monitoring not supported * Module features to implement: - advanced FS API parts + namespaces: fundamental namespace API diff --git a/src/core/core.h b/src/core/core.h index f9117ef4c..30130b84b 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -43,12 +43,13 @@ * transmitted to the client. */ #define GNUNET_CORE_OPTION_NOTHING 0 -#define GNUNET_CORE_OPTION_SEND_CONNECT 1 -#define GNUNET_CORE_OPTION_SEND_DISCONNECT 2 -#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 4 -#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 8 -#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 16 -#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 32 +#define GNUNET_CORE_OPTION_SEND_PRE_CONNECT 1 +#define GNUNET_CORE_OPTION_SEND_CONNECT 2 +#define GNUNET_CORE_OPTION_SEND_DISCONNECT 4 +#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 8 +#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 16 +#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32 +#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 64 /** @@ -278,4 +279,31 @@ struct SendMessage }; +/** + * Client asking core to transmit a particular message to a particular + * target. There is no response from the core to this type of request + * (however, if an actual connection is created or destroyed, be it + * because of this type request or not, the core generally needs to + * notify the clients). + */ +struct ConnectMessage +{ + /** + * Header with type GNUNET_MESSAGE_TYPE_REQUEST_CONNECT or + * GNUNET_MESSAGE_TYPE_REQUEST_DISCONNECT. + */ + struct GNUNET_MessageHeader header; + + /** + * For alignment. + */ + uint32_t reserved GNUNET_PACKED; + + /** + * Identity of the other peer. + */ + struct GNUNET_PeerIdentity peer; + +}; + /* end of core.h */ diff --git a/src/core/core_api.c b/src/core/core_api.c index b485b4181..a9cbd5856 100644 --- a/src/core/core_api.c +++ b/src/core/core_api.c @@ -55,6 +55,12 @@ struct GNUNET_CORE_Handle */ GNUNET_CORE_StartupCallback init; + /** + * Function to call whenever we're notified about a peer connecting + * (pre-connects, no session key exchange yet). + */ + GNUNET_CORE_ClientEventHandler pre_connects; + /** * Function to call whenever we're notified about a peer connecting. */ @@ -395,6 +401,21 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg) #endif switch (ntohs (msg->type)) { + case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT: + if (NULL == h->pre_connects) + { + GNUNET_break (0); + break; + } + if (msize != sizeof (struct ConnectNotifyMessage)) + { + GNUNET_break (0); + break; + } + cnm = (const struct ConnectNotifyMessage *) msg; + h->pre_connects (h->cls, + &cnm->peer); + break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT: if (NULL == h->connects) { @@ -655,6 +676,8 @@ transmit_start (void *cls, size_t size, void *buf) init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT); init->header.size = htons (msize); opt = GNUNET_CORE_OPTION_NOTHING; + if (h->pre_connects != NULL) + opt |= GNUNET_CORE_OPTION_SEND_PRE_CONNECT; if (h->connects != NULL) opt |= GNUNET_CORE_OPTION_SEND_CONNECT; if (h->disconnects != NULL) @@ -696,6 +719,7 @@ transmit_start (void *cls, size_t size, void *buf) * @param cls closure for the various callbacks that follow (including handlers in the handlers array) * @param init callback to call on timeout or once we have successfully * connected to the core service; note that timeout is only meaningful if init is not NULL + * @param pre_connects function to call on peer pre-connect (no session key yet), can be NULL * @param connects function to call on peer connect, can be NULL * @param disconnects function to call on peer disconnect / timeout, can be NULL * @param inbound_notify function to call for all inbound messages, can be NULL @@ -716,6 +740,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched, struct GNUNET_TIME_Relative timeout, void *cls, GNUNET_CORE_StartupCallback init, + GNUNET_CORE_ClientEventHandler pre_connects, GNUNET_CORE_ClientEventHandler connects, GNUNET_CORE_ClientEventHandler disconnects, GNUNET_CORE_MessageCallback inbound_notify, @@ -731,6 +756,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched, h->cfg = cfg; h->cls = cls; h->init = init; + h->pre_connects = pre_connects; h->connects = connects; h->disconnects = disconnects; h->inbound_notify = inbound_notify; diff --git a/src/core/core_api_peer_request.c b/src/core/core_api_peer_request.c index e873a5a9d..58837c773 100644 --- a/src/core/core_api_peer_request.c +++ b/src/core/core_api_peer_request.c @@ -28,7 +28,201 @@ #include "core.h" +/** + * Handle for a request to the core to connect or disconnect + * from a particular peer. Can be used to cancel the request + * (before the 'cont'inuation is called). + */ +struct GNUNET_CORE_PeerRequestHandle +{ + + /** + * Our connection to the service. + */ + struct GNUNET_CLIENT_Connection *client; + + /** + * Scheduler. + */ + struct GNUNET_SCHEDULER_Handle *sched; + + /** + * Function to call once done. + */ + GNUNET_SCHEDULER_Task cont; + + /** + * Closure for 'cont'. + */ + void *cont_cls; + + /** + * Identity of the peer to connect/disconnect. + */ + struct GNUNET_PeerIdentity peer; + + /** + * Message type to use. + */ + uint16_t type; +}; + + +/** + * Transmit the request to the core service. + * + * @param cls our 'struct GNUNET_CORE_PeerRequestHandle' + * @param size number of bytes available in buf + * @param buf where the callee should write the message + * @return number of bytes written to buf + */ +static size_t +send_request (void *cls, + size_t size, + void *buf) +{ + struct GNUNET_CORE_PeerRequestHandle * prh = cls; + struct ConnectMessage msg; + + if (buf == NULL) + { + GNUNET_SCHEDULER_add_continuation (prh->sched, + prh->cont, + prh->cont_cls, + GNUNET_SCHEDULER_REASON_TIMEOUT); + GNUNET_CLIENT_disconnect (prh->client); + GNUNET_free (prh); + return 0; + } + GNUNET_assert (size >= sizeof (struct ConnectMessage)); + msg.header.type = htons (prh->type); + msg.header.size = htons (sizeof (struct ConnectMessage)); + msg.reserved = htonl (0); + msg.peer = prh->peer; + memcpy (buf, &msg, sizeof (msg)); + GNUNET_SCHEDULER_add_continuation (prh->sched, + prh->cont, + prh->cont_cls, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + GNUNET_CLIENT_disconnect (prh->client); + GNUNET_free (prh); + return sizeof (msg); +} + +/** + * Request that the core should try to connect to a particular peer. + * Once the request has been transmitted to the core, the continuation + * function will be called. Note that this does NOT mean that a + * connection was successfully established -- it only means that the + * core will now try. Successful establishment of the connection + * will be signalled to the 'connects' callback argument of + * 'GNUNET_CORE_connect' only. If the core service does not respond + * to our connection attempt within the given time frame, 'cont' will + * be called with the TIMEOUT reason code. + * + * @param sched scheduler to use + * @param cfg configuration to use + * @param timeout how long to try to talk to core + * @param cont function to call once the request has been completed (or timed out) + * @param cont_cls closure for cont + * @return NULL on error (cont will not be called), otherwise handle for cancellation + */ +struct GNUNET_CORE_PeerRequestHandle * +GNUNET_CORE_peer_request_connect (struct GNUNET_SCHEDULER_Handle *sched, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_PeerIdentity * peer, + GNUNET_SCHEDULER_Task cont, + void *cont_cls) +{ + struct GNUNET_CORE_PeerRequestHandle *ret; + struct GNUNET_CLIENT_Connection *client; + + client = GNUNET_CLIENT_connect (sched, "core", cfg); + if (client == NULL) + return NULL; + ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle)); + ret->client = client; + ret->sched = sched; + ret->cont = cont; + ret->cont_cls = cont_cls; + ret->peer = *peer; + ret->type = GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT; + GNUNET_CLIENT_notify_transmit_ready (client, + sizeof (struct ConnectMessage), + timeout, + GNUNET_YES, + &send_request, + ret); + return ret; +} + + +/** + * Request that the core should try to disconnect from a particular + * peer. Once the request has been transmitted to the core, the + * continuation function will be called. Note that this does NOT mean + * that a connection was successfully cut -- it only means that the + * core will now try. Typically this will work pretty much + * immediately, but it is at least in theory also possible that a + * reconnect is also triggered rather quickly. Successful creation + * and destruction of connections will be signalled to the 'connects' + * and 'disconnects' callback arguments of 'GNUNET_CORE_connect' only. + * If the core service does not respond to our connection attempt + * within the given time frame, 'cont' will be called with the TIMEOUT + * reason code. + * + * @param sched scheduler to use + * @param cfg configuration to use + * @param timeout how long to try to talk to core + * @param cont function to call once the request has been completed (or timed out) + * @param cont_cls closure for cont + * @return NULL on error (cont will not be called), otherwise handle for cancellation + */ +struct GNUNET_CORE_PeerRequestHandle * +GNUNET_CORE_peer_request_disconnect (struct GNUNET_SCHEDULER_Handle *sched, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_PeerIdentity * peer, + GNUNET_SCHEDULER_Task cont, + void *cont_cls) +{ + struct GNUNET_CORE_PeerRequestHandle *ret; + struct GNUNET_CLIENT_Connection *client; + + client = GNUNET_CLIENT_connect (sched, "core", cfg); + if (client == NULL) + return NULL; + ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle)); + ret->client = client; + ret->sched = sched; + ret->cont = cont; + ret->cont_cls = cont_cls; + ret->peer = *peer; + ret->type = GNUNET_MESSAGE_TYPE_CORE_REQUEST_DISCONNECT; + GNUNET_CLIENT_notify_transmit_ready (client, + sizeof (struct ConnectMessage), + timeout, + GNUNET_YES, + &send_request, + ret); + return ret; +} + + +/** + * Cancel a pending request to connect or disconnect from/to a particular + * peer. Must not be called after the 'cont' function was invoked. + * + * @param req request handle that was returned for the original request + */ +void +GNUNET_CORE_peer_request_cancel (struct GNUNET_CORE_PeerRequestHandle *req) +{ + GNUNET_CLIENT_disconnect (req->client); + GNUNET_free (req); +} /* end of core_api_peer_request.c */ diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c index 557a3f8ea..71771905e 100644 --- a/src/core/gnunet-service-core.c +++ b/src/core/gnunet-service-core.c @@ -23,6 +23,11 @@ * @brief high-level P2P messaging * @author Christian Grothoff * + * TODO: + * - not all GNUNET_CORE_OPTION_SEND_* flags are fully supported yet + * (i.e. no SEND_XXX_OUTBOUND). + * - 'REQUEST_DISCONNECT' is not implemented (transport API is lacking!) + * * Considerations for later: * - check that hostkey used by transport (for HELLOs) is the * same as the hostkey that we are using! @@ -911,14 +916,17 @@ send_to_client (struct Client *client, * Send a message to all of our current clients. */ static void -send_to_all_clients (const struct GNUNET_MessageHeader *msg, int can_drop) +send_to_all_clients (const struct GNUNET_MessageHeader *msg, + int can_drop, + int options) { struct Client *c; c = clients; while (c != NULL) { - send_to_client (c, msg, can_drop); + if (0 != (c->options & options)) + send_to_client (c, msg, can_drop); c = c->next; } } @@ -1984,6 +1992,66 @@ handle_client_send (void *cls, } +/** + * Handle CORE_REQUEST_CONNECT request. + * + * @param cls unused + * @param client the client issuing the request + * @param message the "struct ConnectMessage" + */ +static void +handle_client_request_connect (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + const struct ConnectMessage *cm = (const struct ConnectMessage*) message; + struct Neighbour *n; + + GNUNET_SERVER_receive_done (client, GNUNET_OK); + n = find_neighbour (&cm->peer); + if (n != NULL) + return; /* already connected, or at least trying */ +#if DEBUG_CORE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Core received `%s' request for `%4s', will try to establish connection\n", + "REQUEST_CONNECT", + GNUNET_i2s (&cm->peer)); +#endif + /* ask transport to connect to the peer */ + /* FIXME: timeout zero OK? need for cancellation? */ + GNUNET_TRANSPORT_notify_transmit_ready (transport, + &cm->peer, + 0, 0, + GNUNET_TIME_UNIT_ZERO, + NULL, + NULL); +} + + +/** + * Handle CORE_REQUEST_DISCONNECT request. + * + * @param cls unused + * @param client the client issuing the request + * @param message the "struct ConnectMessage" + */ +static void +handle_client_request_disconnect (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + const struct ConnectMessage *cm = (const struct ConnectMessage*) message; + struct Neighbour *n; + + GNUNET_SERVER_receive_done (client, GNUNET_OK); + n = find_neighbour (&cm->peer); + if (n == NULL) + return; /* done */ + /* FIXME: implement disconnect! */ +} + + + /** * List of handlers for the messages understood by this * service. @@ -1996,15 +2064,20 @@ static struct GNUNET_SERVER_MessageHandler handlers[] = { sizeof (struct RequestInfoMessage)}, {&handle_client_send, NULL, GNUNET_MESSAGE_TYPE_CORE_SEND, 0}, + {&handle_client_request_connect, NULL, + GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT, + sizeof (struct ConnectMessage)}, + {&handle_client_request_disconnect, NULL, + GNUNET_MESSAGE_TYPE_CORE_REQUEST_DISCONNECT, + sizeof (struct ConnectMessage)}, {NULL, NULL, 0, 0} }; /** - * PEERINFO is giving us a HELLO for a peer. Add the - * public key to the neighbour's struct and retry - * send_key. Or, if we did not get a HELLO, just do - * nothing. + * PEERINFO is giving us a HELLO for a peer. Add the public key to + * the neighbour's struct and retry send_key. Or, if we did not get a + * HELLO, just do nothing. * * @param cls NULL * @param peer the peer for which this is the HELLO @@ -2073,6 +2146,9 @@ send_key (struct Neighbour *n) struct PingMessage pp; struct PingMessage *pm; + if ( (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK) || + (n->pitr != NULL) ) + return; /* already in progress */ #if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to perform key exchange with `%4s'.\n", @@ -2481,6 +2557,7 @@ static void handle_pong (struct Neighbour *n, const struct PingMessage *m) { struct PingMessage t; + struct ConnectNotifyMessage cnm; #if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -2533,7 +2610,12 @@ handle_pong (struct Neighbour *n, const struct PingMessage *m) { GNUNET_SCHEDULER_cancel (sched, n->retry_set_key_task); n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; - } + } + cnm.header.size = htons (sizeof (struct ConnectNotifyMessage)); + cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); + cnm.reserved = htonl (0); + cnm.peer = n->peer; + send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_CONNECT); process_encrypted_neighbour_queue (n); break; case PEER_STATE_KEY_CONFIRMED: @@ -2599,7 +2681,7 @@ deliver_message (struct Neighbour *sender, while (cpos != NULL) { deliver_full = GNUNET_NO; - if (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND) + if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) deliver_full = GNUNET_YES; else { @@ -3033,10 +3115,11 @@ handle_transport_notify_connect (void *cls, #endif schedule_quota_update (n); cnm.header.size = htons (sizeof (struct ConnectNotifyMessage)); - cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); + cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT); cnm.reserved = htonl (0); cnm.peer = *peer; - send_to_all_clients (&cnm.header, GNUNET_YES); + send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_PRE_CONNECT); + send_key (n); } @@ -3127,7 +3210,7 @@ handle_transport_notify_disconnect (void *cls, cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT); cnm.reserved = htonl (0); cnm.peer = *peer; - send_to_all_clients (&cnm.header, GNUNET_YES); + send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_DISCONNECT); free_neighbour (n); } diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c index 3de162a82..acece6545 100644 --- a/src/core/test_core_api.c +++ b/src/core/test_core_api.c @@ -215,6 +215,7 @@ init_notify (void *cls, TIMEOUT, &p2, &init_notify, + NULL, &connect_notify, &disconnect_notify, &inbound_notify, @@ -305,6 +306,7 @@ run (void *cls, TIMEOUT, &p1, &init_notify, + NULL, &connect_notify, &disconnect_notify, &inbound_notify, diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c index bf5db63c0..8b5e867bc 100644 --- a/src/core/test_core_api_start_only.c +++ b/src/core/test_core_api_start_only.c @@ -125,6 +125,7 @@ init_notify (void *cls, TIMEOUT, &p2, &init_notify, + NULL, &connect_notify, &disconnect_notify, &inbound_notify, @@ -178,6 +179,7 @@ run (void *cls, TIMEOUT, &p1, &init_notify, + NULL, &connect_notify, &disconnect_notify, &inbound_notify, diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index 71e59f115..4ce618bf7 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c @@ -3325,6 +3325,7 @@ run (void *cls, GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL, + NULL, &peer_connect_handler, &peer_disconnect_handler, NULL, GNUNET_NO, diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c index fd1068839..b8cf93d5a 100644 --- a/src/hostlist/gnunet-daemon-hostlist.c +++ b/src/hostlist/gnunet-daemon-hostlist.c @@ -191,7 +191,7 @@ run (void *cls, GNUNET_TIME_UNIT_FOREVER_REL, NULL, &core_init, - ch, dh, + NULL, ch, dh, NULL, GNUNET_NO, NULL, GNUNET_NO, handlers); diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h index 94656b916..cffdf0a14 100644 --- a/src/include/gnunet_core_service.h +++ b/src/include/gnunet_core_service.h @@ -138,6 +138,7 @@ typedef void * @param cls closure for the various callbacks that follow (including handlers in the handlers array) * @param init callback to call on timeout or once we have successfully * connected to the core service; note that timeout is only meaningful if init is not NULL + * @param pre_connects function to call on peer pre-connect (no session key yet), can be NULL * @param connects function to call on peer connect, can be NULL * @param disconnects function to call on peer disconnect / timeout, can be NULL * @param inbound_notify function to call for all inbound messages, can be NULL @@ -158,6 +159,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched, struct GNUNET_TIME_Relative timeout, void *cls, GNUNET_CORE_StartupCallback init, + GNUNET_CORE_ClientEventHandler pre_connects, GNUNET_CORE_ClientEventHandler connects, GNUNET_CORE_ClientEventHandler disconnects, GNUNET_CORE_MessageCallback inbound_notify, @@ -175,27 +177,77 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched, void GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle); -// FIXME +/** + * Handle for a request to the core to connect or disconnect + * from a particular peer. Can be used to cancel the request + * (before the 'cont'inuation is called). + */ struct GNUNET_CORE_PeerRequestHandle; -// FIXME + +/** + * Request that the core should try to connect to a particular peer. + * Once the request has been transmitted to the core, the continuation + * function will be called. Note that this does NOT mean that a + * connection was successfully established -- it only means that the + * core will now try. Successful establishment of the connection + * will be signalled to the 'connects' callback argument of + * 'GNUNET_CORE_connect' only. If the core service does not respond + * to our connection attempt within the given time frame, 'cont' will + * be called with the TIMEOUT reason code. + * + * @param sched scheduler to use + * @param cfg configuration to use + * @param timeout how long to try to talk to core + * @param cont function to call once the request has been completed (or timed out) + * @param cont_cls closure for cont + * @return NULL on error (cont will not be called), otherwise handle for cancellation + */ struct GNUNET_CORE_PeerRequestHandle * GNUNET_CORE_peer_request_connect (struct GNUNET_SCHEDULER_Handle *sched, - const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_PeerIdentity * peer, - GNUNET_SCHEDULER_Task cont, - void *cont_cls); + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_PeerIdentity * peer, + GNUNET_SCHEDULER_Task cont, + void *cont_cls); -// FIXME +/** + * Request that the core should try to disconnect from a particular + * peer. Once the request has been transmitted to the core, the + * continuation function will be called. Note that this does NOT mean + * that a connection was successfully cut -- it only means that the + * core will now try. Typically this will work pretty much + * immediately, but it is at least in theory also possible that a + * reconnect is also triggered rather quickly. Successful creation + * and destruction of connections will be signalled to the 'connects' + * and 'disconnects' callback arguments of 'GNUNET_CORE_connect' only. + * If the core service does not respond to our connection attempt + * within the given time frame, 'cont' will be called with the TIMEOUT + * reason code. + * + * @param sched scheduler to use + * @param cfg configuration to use + * @param timeout how long to try to talk to core + * @param cont function to call once the request has been completed (or timed out) + * @param cont_cls closure for cont + * @return NULL on error (cont will not be called), otherwise handle for cancellation + */ struct GNUNET_CORE_PeerRequestHandle * GNUNET_CORE_peer_request_disconnect (struct GNUNET_SCHEDULER_Handle *sched, - const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_PeerIdentity * peer, - GNUNET_SCHEDULER_Task cont, - void *cont_cls); + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_PeerIdentity * peer, + GNUNET_SCHEDULER_Task cont, + void *cont_cls); -// FIXME + +/** + * Cancel a pending request to connect or disconnect from/to a particular + * peer. Must not be called after the 'cont' function was invoked. + * + * @param req request handle that was returned for the original request + */ void GNUNET_CORE_peer_request_cancel (struct GNUNET_CORE_PeerRequestHandle *req); diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index cdf5d0df3..28535587d 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -263,40 +263,57 @@ extern "C" #define GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY 65 /** - * Notify clients about new peer-to-peer connections. + * Notify clients about new peer-to-peer connections (before + * key exchange and authentication). */ -#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT 66 +#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT 66 + +/** + * Notify clients about new peer-to-peer connections (triggered + * after key exchange). + */ +#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT 67 /** * Notify clients about peer disconnecting. */ -#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 67 +#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 68 /** * Notify clients about incoming P2P messages. */ -#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 68 +#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 69 /** * Notify clients about outgoing P2P transmissions. */ -#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 69 +#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 70 /** * Request from client to "configure" P2P connection. */ -#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 70 +#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 71 /** * Response from server about (possibly updated) P2P * connection configuration. */ -#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 71 +#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 72 /** * Request from client with message to transmit. */ -#define GNUNET_MESSAGE_TYPE_CORE_SEND 72 +#define GNUNET_MESSAGE_TYPE_CORE_SEND 73 + +/** + * Request from client asking to connect to a peer. + */ +#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 74 + +/** + * Request from client asking to disconnect from a peer. + */ +#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_DISCONNECT 75 /** diff --git a/src/include/gnunet_transport_service.h b/src/include/gnunet_transport_service.h index 726e03a95..344de582f 100644 --- a/src/include/gnunet_transport_service.h +++ b/src/include/gnunet_transport_service.h @@ -138,10 +138,8 @@ void GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle); * * @param handle connection to transport service * @param target who's bandwidth quota is being changed - * @param quota_in incoming bandwidth quota in bytes per ms; 0 can - * be used to force all traffic to be discarded - * @param quota_out outgoing bandwidth quota in bytes per ms; 0 can - * be used to force all traffic to be discarded + * @param quota_in incoming bandwidth quota in bytes per ms + * @param quota_out outgoing bandwidth quota in bytes per ms * @param timeout how long to wait until signaling failure if * we can not communicate the quota change * @param cont continuation to call when done, will be called @@ -195,8 +193,9 @@ struct GNUNET_TRANSPORT_TransmitHandle /** - * Cancel the specified transmission-ready - * notification. + * Cancel the specified transmission-ready notification. + * + * @param h handle of the transmission notification request to cancel */ void GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct diff --git a/src/testing/testing.c b/src/testing/testing.c index cc584e74a..489252411 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c @@ -434,7 +434,7 @@ start_fsm (void *cls, ARM_START_WAIT, d, &testing_init, - NULL, NULL, + NULL, NULL, NULL, NULL, GNUNET_NO, NULL, GNUNET_NO, no_handlers); diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c index bc2f3ec7f..9f23fdc50 100644 --- a/src/topology/gnunet-daemon-topology.c +++ b/src/topology/gnunet-daemon-topology.c @@ -1289,6 +1289,7 @@ run (void *cls, GNUNET_TIME_UNIT_FOREVER_REL, NULL, &core_init, + NULL, &connect_notify, &disconnect_notify, NULL, GNUNET_NO, diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c index 155347bf0..e17ba742e 100644 --- a/src/transport/transport_api.c +++ b/src/transport/transport_api.c @@ -22,10 +22,6 @@ * @file transport/transport_api.c * @brief library to access the low-level P2P IO service * @author Christian Grothoff - * - * TODO: - * - set_quota with low bandwidth should cause peer - * disconnects (currently never does that) (MINOR) */ #include "platform.h" #include "gnunet_client_lib.h" @@ -395,7 +391,8 @@ transport_notify_ready (void *cls, size_t size, void *buf) GNUNET_SCHEDULER_cancel (h->sched, th->notify_delay_task); th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; } - GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); + if (NULL != th->notify) + GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); if (h->connect_ready_head != NULL) schedule_transmission (h); /* FIXME: is this ok? */ @@ -427,7 +424,8 @@ transport_notify_ready (void *cls, size_t size, void *buf) GNUNET_assert (n->transmit_handle == th); n->transmit_handle = NULL; } - ret += th->notify (th->notify_cls, size, &cbuf[ret]); + if (NULL != th->notify) + ret += th->notify (th->notify_cls, size, &cbuf[ret]); GNUNET_free (th); if (n != NULL) n->last_sent += ret; @@ -585,7 +583,8 @@ peer_transmit_timeout (void *cls, GNUNET_i2s (&th->target)); #endif remove_from_any_list (th); - th->notify (th->notify_cls, 0, NULL); + if (NULL != th->notify) + th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); } @@ -735,10 +734,8 @@ send_set_quota (void *cls, size_t size, void *buf) * * @param handle connection to transport service * @param target who's bandwidth quota is being changed - * @param quota_in incoming bandwidth quota in bytes per ms; 0 can - * be used to force all traffic to be discarded - * @param quota_out outgoing bandwidth quota in bytes per ms; 0 can - * be used to force all traffic to be discarded + * @param quota_in incoming bandwidth quota in bytes per ms + * @param quota_out outgoing bandwidth quota in bytes per ms * @param timeout how long to wait until signaling failure if * we can not communicate the quota change * @param cont continuation to call when done, will be called @@ -992,7 +989,8 @@ request_connect (void *cls, size_t size, void *buf) GNUNET_SCHEDULER_cancel (h->sched, th->notify_delay_task); th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; } - th->notify (th->notify_cls, 0, NULL); + if (NULL != th->notify) + GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); return 0; } @@ -1288,7 +1286,8 @@ schedule_request (struct GNUNET_TRANSPORT_TransmitHandle *th) duration.value, GNUNET_i2s (&th->target)); #endif remove_from_wait_list (th); - th->notify (th->notify_cls, 0, NULL); + if (NULL != th->notify) + GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); return; } @@ -1472,7 +1471,8 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) GNUNET_SCHEDULER_cancel (handle->sched, th->notify_delay_task); th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; } - th->notify (th->notify_cls, 0, NULL); + if (NULL != th->notify) + GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); } while (NULL != (th = handle->connect_wait_head)) @@ -1483,7 +1483,8 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) GNUNET_SCHEDULER_cancel (handle->sched, th->notify_delay_task); th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; } - th->notify (th->notify_cls, 0, NULL); + if (NULL != th->notify) + GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); } while (NULL != (n = handle->neighbours)) @@ -1496,7 +1497,8 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) GNUNET_SCHEDULER_cancel (handle->sched, th->notify_delay_task); th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; } - th->notify (th->notify_cls, 0, NULL); + if (NULL != th->notify) + GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); } GNUNET_free (n); @@ -1788,16 +1790,19 @@ client_notify_wrapper (void *cls, size_t size, void *buf) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission request could not be satisfied.\n"); #endif - ret = ctw->notify (ctw->notify_cls, 0, NULL); - GNUNET_assert (ret == 0); + if (NULL != ctw->notify) + GNUNET_assert (0 == ctw->notify (ctw->notify_cls, 0, NULL)); GNUNET_free (ctw); return 0; } GNUNET_assert (size >= sizeof (struct OutboundMessage)); obm = buf; - ret = ctw->notify (ctw->notify_cls, - size - sizeof (struct OutboundMessage), - (void *) &obm[1]); + if (ctw->notify != NULL) + ret = ctw->notify (ctw->notify_cls, + size - sizeof (struct OutboundMessage), + (void *) &obm[1]); + else + ret = 0; if (ret == 0) { /* Need to reset flag, no SEND means no SEND_OK! */