From 0ee1339afc5c5e1105e234b6840c87df58a01f2c Mon Sep 17 00:00:00 2001 From: Bart Polot Date: Fri, 2 Sep 2011 19:59:58 +0000 Subject: [PATCH] Changes in API, adapted code and testfiles, improved client reconnect, new documentation, small fixes --- src/include/gnunet_mesh_service_new.h | 46 ++++---- src/mesh/Makefile.am | 2 +- src/mesh/gnunet-service-mesh.c | 8 +- src/mesh/mesh.h | 3 +- src/mesh/mesh_api.c | 2 +- src/mesh/mesh_api_new.c | 144 ++++++++++++++++++-------- src/mesh/test_mesh_api.c | 4 +- src/mesh/test_mesh_small.c | 7 +- 8 files changed, 138 insertions(+), 78 deletions(-) diff --git a/src/include/gnunet_mesh_service_new.h b/src/include/gnunet_mesh_service_new.h index 7ca53b070..e85a4814f 100644 --- a/src/include/gnunet_mesh_service_new.h +++ b/src/include/gnunet_mesh_service_new.h @@ -105,6 +105,26 @@ struct GNUNET_MESH_MessageHandler }; +/** + * Method called whenever another peer has added us to a tunnel + * the other peer initiated. + * + * @param cls closure + * @param tunnel new handle to the tunnel + * @param initiator peer that started the tunnel + * @param atsi performance information for the tunnel + * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) + */ +typedef void* (GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls, + struct GNUNET_MESH_Tunnel * tunnel, + const struct + GNUNET_PeerIdentity * + initiator, + const struct + GNUNET_TRANSPORT_ATS_Information * + atsi); + + /** * Function called whenever an inbound tunnel is destroyed. Should clean up * any associated state. @@ -116,7 +136,7 @@ struct GNUNET_MESH_MessageHandler */ typedef void (GNUNET_MESH_TunnelEndHandler) (void *cls, const struct GNUNET_MESH_Tunnel * - tunnel, void **tunnel_ctx); + tunnel, void *tunnel_ctx); /** @@ -125,28 +145,6 @@ typedef void (GNUNET_MESH_TunnelEndHandler) (void *cls, typedef uint32_t GNUNET_MESH_ApplicationType; -/** - * Method called whenever another peer has added us to a tunnel - * the other peer initiated. - * - * @param cls closure - * @param tunnel new handle to the tunnel - * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel - * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) - */ -typedef void *(*GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls, - struct - GNUNET_MESH_Tunnel - * tunnel, - const struct - GNUNET_PeerIdentity - * initiator, - const struct - GNUNET_TRANSPORT_ATS_Information - * atsi); - - /** * Connect to the mesh service. * @@ -156,6 +154,7 @@ typedef void *(*GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls, * no matter what is the status of other tunnels) * @param cls closure for the various callbacks that follow * (including handlers in the handlers array) + * @param new_tunnel function called when an *inbound* tunnel is created * @param cleaner function called when an *inbound* tunnel is destroyed * @param handlers callbacks for messages we care about, NULL-terminated * note that the mesh is allowed to drop notifications about @@ -168,6 +167,7 @@ typedef void *(*GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls, struct GNUNET_MESH_Handle * GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int queue_size, void *cls, + GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, GNUNET_MESH_TunnelEndHandler cleaner, const struct GNUNET_MESH_MessageHandler *handlers, const GNUNET_MESH_ApplicationType *stypes); diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am index 1131c07c6..cea6152e2 100644 --- a/src/mesh/Makefile.am +++ b/src/mesh/Makefile.am @@ -69,7 +69,7 @@ test_mesh_small_DEPENDENCIES = \ libgnunetmeshnew.la if ENABLE_TEST_RUN -TESTS = test_mesh_small +TESTS = test_mesh_api endif EXTRA_DIST = \ diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index c396303a8..f5e8aa8e8 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -286,7 +286,7 @@ struct MESH_TunnelID /** * Tunnel number to differentiate all the tunnels owned by the node oid - * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK ) + * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI ) */ MESH_TunnelNumber tid; }; @@ -309,7 +309,7 @@ struct MeshTunnel struct MESH_TunnelID id; /** - * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 ) + * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 ) */ MESH_TunnelNumber local_tid; @@ -2187,7 +2187,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, t_msg = (struct GNUNET_MESH_TunnelMessage *) message; /* Sanity check for tunnel numbering */ - if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) + if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); @@ -2203,7 +2203,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, t = GNUNET_malloc (sizeof (struct MeshTunnel)); while (NULL != retrieve_tunnel_by_pi (myid, next_tid)) - next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK; + next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; t->id.tid = next_tid++; t->id.oid = myid; t->local_tid = ntohl (t_msg->tunnel_id); diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h index 874e29a91..41fc13110 100644 --- a/src/mesh/mesh.h +++ b/src/mesh/mesh.h @@ -67,7 +67,8 @@ /************************** CONSTANTS ******************************/ /******************************************************************************/ -#define GNUNET_MESH_LOCAL_TUNNEL_ID_MARK 0x80000000 +#define GNUNET_MESH_LOCAL_TUNNEL_ID_CLI 0x80000000 +#define GNUNET_MESH_LOCAL_TUNNEL_ID_SERV 0xB0000000 /******************************************************************************/ diff --git a/src/mesh/mesh_api.c b/src/mesh/mesh_api.c index 8476be396..615593621 100644 --- a/src/mesh/mesh_api.c +++ b/src/mesh/mesh_api.c @@ -921,4 +921,4 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) GNUNET_free (handle); } -/* end of mesh_api.c */ +/* end of mesh_api.c */ \ No newline at end of file diff --git a/src/mesh/mesh_api_new.c b/src/mesh/mesh_api_new.c index a2e05e822..fa2bd6682 100644 --- a/src/mesh/mesh_api_new.c +++ b/src/mesh/mesh_api_new.c @@ -1,4 +1,3 @@ - /* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) @@ -159,7 +158,12 @@ struct GNUNET_MESH_Handle struct GNUNET_MESH_Tunnel *tunnels_tail; /** - * Callback for tunnel disconnection + * Callback for inbound tunnel creation + */ + GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel; + + /** + * Callback for inbound tunnel disconnection */ GNUNET_MESH_TunnelEndHandler *cleaner; @@ -246,15 +250,10 @@ struct GNUNET_MESH_Tunnel GNUNET_MESH_TunnelConnectHandler connect_handler; /** - * Callback to execute when peers disconnect to the tunnel + * Callback to execute when peers disconnect from the tunnel */ GNUNET_MESH_TunnelDisconnectHandler disconnect_handler; - /** - * All peers added to the tunnel - */ - struct GNUNET_MESH_Peer **peers; - /** * Closure for the connect/disconnect handlers */ @@ -275,11 +274,21 @@ struct GNUNET_MESH_Tunnel */ GNUNET_PEER_Id owner; + /** + * All peers added to the tunnel + */ + struct GNUNET_MESH_Peer **peers; + /** * List of application types that have been requested for this tunnel */ GNUNET_MESH_ApplicationType *apps; + /** + * Any data the caller wants to put in here + */ + void *ctx; + /** * Number of peers added to the tunnel */ @@ -336,20 +345,22 @@ create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid) struct GNUNET_MESH_Tunnel *t; t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel)); + GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t); t->mesh = h; if (0 == tid) { - t->tid = h->next_tid++; + t->tid = h->next_tid; + while (NULL != retrieve_tunnel (h, h->next_tid)) + { + h->next_tid++; + h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; + h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; + } } else { - /* FIXME keep double numbering? - * client numbers from 0x8... anx service from 0xB... ? */ t->tid = tid; - h->next_tid = tid + 1; } - h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK; // keep in range - GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t); return t; } @@ -373,6 +384,29 @@ destroy_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid) GNUNET_break (0); return; } + /* TODO remove data packets from queue */ + GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t); + for (i = 0; i < t->npeers; i++) + { + if (NULL != t->disconnect_handler && t->peers[i]->connected) + { + GNUNET_PEER_resolve (t->peers[i]->id, &pi); + t->disconnect_handler (t->cls, &pi); + } + GNUNET_PEER_change_rc (t->peers[i]->id, -1); + GNUNET_free (t->peers[i]); + } + if (NULL != h->cleaner && 0 != t->owner) + h->cleaner (h->cls, t, t->ctx); + if (0 != t->owner) + GNUNET_PEER_change_rc (t->owner, -1); + if (0 != t->napps && t->apps) + GNUNET_free (t->apps); + if (t->npeers > 0) + GNUNET_free (t->peers); + GNUNET_free (t); + return; + } GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t); for (i = 0; i < t->npeers; i++) { @@ -518,7 +552,6 @@ send_packet (struct GNUNET_MESH_Handle *h, /** * Reconnect to the service, retransmit all infomation to try to restore the * original state. - * FIXME: notify user about it? (call all disconnect callbacks?) * * @param h handle to the mesh * @@ -549,25 +582,42 @@ reconnect (struct GNUNET_MESH_Handle *h) GNUNET_break (0); return GNUNET_NO; } + /* Rebuild all tunnels */ for (t = h->tunnels_head; NULL != t; t = t->next) { - struct GNUNET_MESH_TunnelMessage msg; + struct GNUNET_MESH_TunnelMessage tmsg; + struct GNUNET_MESH_PeerControl pmsg; - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); - msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - msg.tunnel_id = htonl (t->tid); - send_packet (h, &msg.header); + tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); + tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); + tmsg.tunnel_id = htonl (t->tid); + send_packet (h, &tmsg.header); + + pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); + pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); + pmsg.tunnel_id = htonl (t->tid); + + /* Reconnect all peers */ for (i = 0; i < t->npeers; i++) { - struct GNUNET_MESH_PeerControl msg; + GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer); + if (NULL != t->disconnect_handler && t->peers[i]->connected) + t->disconnect_handler (t->cls, &pmsg.peer); + /* If the tunnel was "by type", dont connect individual peers */ + if (0 == t->napps) + send_packet (t->mesh, &pmsg.header); + } + /* Reconnect all types, if any */ + for (i = 0; i < t->napps; i++) + { + struct GNUNET_MESH_ConnectPeerByType msg; - msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); + msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType)); + msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE); msg.tunnel_id = htonl (t->tid); - GNUNET_PEER_resolve (t->peers[i]->id, &msg.peer); + msg.type = htonl (t->apps[i]); send_packet (t->mesh, &msg.header); } - /* FIXME what about connects by type? */ } return GNUNET_YES; } @@ -591,13 +641,12 @@ process_tunnel_create (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid; tid = ntohl (msg->tunnel_id); - if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK) + if (tid <= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI) { GNUNET_break (0); return; } - t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel)); - t->cls = h->cls; + t = create_tunnel (h, tid); t->mesh = h; t->tid = tid; GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t); @@ -748,9 +797,8 @@ process_incoming_data (struct GNUNET_MESH_Handle *h, atsi.type = 0; atsi.value = 0; - /* FIXME ctx */ if (GNUNET_OK == - handler->callback (h->cls, t, NULL, peer, payload, &atsi)) + handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: callback completed successfully\n"); @@ -966,23 +1014,25 @@ send_packet (struct GNUNET_MESH_Handle *h, * Connect to the mesh service. * * @param cfg configuration to use - * @param cls closure for the various callbacks that follow - * (including handlers in the handlers array) * @param queue_size size of the data message queue, shared among all tunnels * (each tunnel is guaranteed to accept at least one message, * no matter what is the status of other tunnels) + * @param cls closure for the various callbacks that follow + * (including handlers in the handlers array) + * @param new_tunnel function called when an *inbound* tunnel is created * @param cleaner function called when an *inbound* tunnel is destroyed * @param handlers callbacks for messages we care about, NULL-terminated - * note that the mesh is allowed to drop notifications about - * inbound messages if the client does not process them fast - * enough (for this notification type, a bounded queue is used) - * @param stypes Application Types the client claims to offer - * @return handle to the mesh service - * NULL on error (in this case, init is never called) + * note that the mesh is allowed to drop notifications about + * inbound messages if the client does not process them fast + * enough (for this notification type, a bounded queue is used) + * @param stypes list of the applications that this client claims to provide + * @return handle to the mesh service NULL on error + * (in this case, init is never called) */ struct GNUNET_MESH_Handle * GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int queue_size, void *cls, + GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, GNUNET_MESH_TunnelEndHandler cleaner, const struct GNUNET_MESH_MessageHandler *handlers, const GNUNET_MESH_ApplicationType *stypes) @@ -999,6 +1049,7 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle)); h->cfg = cfg; h->max_queue_size = queue_size; + h->new_tunnel = new_tunnel; h->cleaner = cleaner; h->client = GNUNET_CLIENT_connect ("mesh", cfg); if (h->client == NULL) @@ -1010,7 +1061,7 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, h->cls = cls; h->message_handlers = handlers; h->applications = stypes; - h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_MARK; + h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; /* count handlers and apps, calculate size */ for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ; @@ -1052,6 +1103,12 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) { + struct GNUNET_MESH_Tunnel *t; + + for (t = handle->tunnels_head; NULL != t; t = t->next) + { + destroy_tunnel (handle, t->tid); + } if (NULL != handle->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); @@ -1069,12 +1126,13 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) * and to broadcast). * * @param h mesh handle + * @param tunnel_ctx client's tunnel context to associate with the tunnel * @param connect_handler function to call when peers are actually connected * @param disconnect_handler function to call when peers are disconnected * @param handler_cls closure for connect/disconnect handlers */ struct GNUNET_MESH_Tunnel * -GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, +GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx, GNUNET_MESH_TunnelConnectHandler connect_handler, GNUNET_MESH_TunnelDisconnectHandler disconnect_handler, void *handler_cls) @@ -1087,6 +1145,7 @@ GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, t->connect_handler = connect_handler; t->disconnect_handler = disconnect_handler; t->cls = handler_cls; + t->ctx = tunnel_ctx; msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); msg.tunnel_id = htonl (t->tid); @@ -1114,8 +1173,8 @@ GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tun) msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - msg.tunnel_id = htonl (tun->tid); - GNUNET_free (tun); + msg.tunnel_id = htonl (t->tid); + destroy_tunnel (h, t->tid); send_packet (h, &msg.header); } @@ -1219,7 +1278,6 @@ GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel, struct GNUNET_MESH_ConnectPeerByType msg; GNUNET_array_append (tunnel->apps, tunnel->napps, app_type); - /* FIXME: add a new api call disconnect by type? */ msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE); diff --git a/src/mesh/test_mesh_api.c b/src/mesh/test_mesh_api.c index 312e72375..060db9c8a 100644 --- a/src/mesh/test_mesh_api.c +++ b/src/mesh/test_mesh_api.c @@ -104,7 +104,7 @@ test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct GNUNET_MESH_Tunnel *t; test_task = (GNUNET_SCHEDULER_TaskIdentifier) 0; - mesh = GNUNET_MESH_connect (cfg, 10, NULL, NULL, handlers, app); + mesh = GNUNET_MESH_connect (cfg, 10, NULL, NULL, NULL, handlers, app); if (NULL == mesh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh :(\n"); @@ -115,7 +115,7 @@ test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO MESH :D\n"); } - t = GNUNET_MESH_tunnel_create (mesh, NULL, NULL, NULL); + t = GNUNET_MESH_tunnel_create (mesh, NULL, NULL, NULL, NULL); GNUNET_MESH_tunnel_destroy (t); diff --git a/src/mesh/test_mesh_small.c b/src/mesh/test_mesh_small.c index 53f00a24f..2cd74d6ef 100644 --- a/src/mesh/test_mesh_small.c +++ b/src/mesh/test_mesh_small.c @@ -204,7 +204,7 @@ static struct GNUNET_MESH_MessageHandler handlers[] = { */ static void tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, - void **tunnel_ctx) + void *tunnel_ctx) { #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel disconnected\n"); @@ -263,12 +263,13 @@ connect_mesh_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connecting to mesh service of peer %s\n", GNUNET_i2s (&d->id)); #endif - h = GNUNET_MESH_connect (d->cfg, 10, NULL, &tunnel_cleaner, handlers, &app); + h = GNUNET_MESH_connect (d->cfg, 10, NULL, NULL, &tunnel_cleaner, handlers, + &app); #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected to mesh service of peer %s\n", GNUNET_i2s (&d->id)); #endif - t = GNUNET_MESH_tunnel_create (h, &ch, &dh, NULL); + t = GNUNET_MESH_tunnel_create (h, NULL, &ch, &dh, NULL); GNUNET_MESH_tunnel_destroy (t); GNUNET_MESH_disconnect (h); } -- 2.25.1