From 1c6c5702158056edb47afb066a9068d168909ba8 Mon Sep 17 00:00:00 2001 From: Bart Polot Date: Sat, 17 Nov 2012 22:21:18 +0000 Subject: [PATCH] Added mesh CLI with basic tunnel listing --- src/include/gnunet_mesh_service.h | 41 ++++++++++ src/include/gnunet_protocols.h | 5 ++ src/mesh/Makefile.am | 11 +++ src/mesh/gnunet-service-mesh.c | 125 +++++++++++++++++++++++++++++- src/mesh/mesh.h | 34 ++++++++ src/mesh/mesh_api.c | 103 +++++++++++++++++++++++- 6 files changed, 316 insertions(+), 3 deletions(-) diff --git a/src/include/gnunet_mesh_service.h b/src/include/gnunet_mesh_service.h index b9f0e49c6..43cbd9af4 100644 --- a/src/include/gnunet_mesh_service.h +++ b/src/include/gnunet_mesh_service.h @@ -426,6 +426,47 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th); +/** + * Method called to retrieve information about each tunnel the mesh peer + * is aware of. + * + * @param cls Closure. + * @param initiator Peer that started the tunnel (owner). + * @param tunnel_number Tunnel number. + * @param peers Array of peer identities that participate in the tunnel. + * @param npeers Number of peers in peers. + */ +typedef void (*GNUNET_MESH_MonitorCB) (void *cls, + const struct GNUNET_PeerIdentity *initiator, + unsigned int tunnel_number, + const struct GNUNET_PeerIdentity *peers, + unsigned int npeers); + + +/** + * Request information about the running mesh peer. + * + * @param h Handle to the mesh peer. + * @param callback Function to call with the requested data. + * @param monitor_cls Closure for @c callback. + */ +void +GNUNET_MESH_monitor (struct GNUNET_MESH_Handle *h, + GNUNET_MESH_MonitorCB callback, + void *monitor_cls); + + +/** + * Cancel a monitor request. The monitor callback will not be called. + * + * @param h Mesh handle. + * + * @return Closure given to GNUNET_MESH_monitor, if any. + */ +void * +GNUNET_MESH_monitor_cancel (struct GNUNET_MESH_Handle *h); + + /** * Transition API for tunnel ctx management * diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 8abaf35b4..7b0b46055 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -880,6 +880,11 @@ extern "C" */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK 286 +/** + * Local monitoring of service. + */ +#define GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR 287 + /** * 640kb should be enough for everybody */ diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am index c1c84ae7d..d1afc0589 100644 --- a/src/mesh/Makefile.am +++ b/src/mesh/Makefile.am @@ -23,6 +23,9 @@ AM_CLFAGS = -g libexec_PROGRAMS = \ gnunet-service-mesh gnunet-service-mesh-new +bin_PROGRAMS = \ + gnunet-mesh + lib_LTLIBRARIES = \ libgnunetmesh.la \ libgnunetmeshblock.la @@ -88,6 +91,14 @@ if LINUX gnunet_service_mesh_LDFLAGS = -lrt endif +gnunet_mesh_SOURCES = \ + gnunet-mesh.c +gnunet_mesh_LDADD = \ + $(top_builddir)/src/mesh/libgnunetmesh.la \ + $(top_builddir)/src/util/libgnunetutil.la +gnunet_mesh_DEPENDENCIES = \ + libgnunetmesh.la + gnunet_service_mesh_new_SOURCES = \ gnunet-service-mesh-new.c \ mesh_tunnel_tree.c \ diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 9a5b33d35..097eca3b6 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -2516,6 +2516,9 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message, } #endif GNUNET_break (0); // FIXME sometimes fails (testing disconnect?) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + " no direct connection to %s\n", + GNUNET_i2s (peer)); GNUNET_free (info->mesh_data->data); GNUNET_free (info->mesh_data); GNUNET_free (info); @@ -8013,7 +8016,7 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, ack = ntohl (msg->max_pid); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); - /* Does client own tunnel? I.E: Is this and ACK for BCK traffic? */ + /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */ if (NULL != t->owner && t->owner->handle == client) { /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ @@ -8027,12 +8030,127 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); } - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } +/** + * Iterator over all peers to send a monitoring client info about a tunnel. + * + * @param cls Closure (message being built). + * @param key Key (hashed tunnel ID, unused). + * @param value Peer info. + * + * @return GNUNET_YES, to keep iterating. + */ +static int +monitor_peers_iterator (void *cls, + const struct GNUNET_HashCode * key, + void *value) +{ + struct GNUNET_MESH_LocalMonitor *msg = cls; + struct GNUNET_PeerIdentity *id; + struct MeshPeerInfo *info = value; + + id = (struct GNUNET_PeerIdentity *) &msg[1]; + GNUNET_PEER_resolve (info->id, &id[msg->npeers]); + msg->npeers++; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "* sending info about peer %s [%u]\n", + GNUNET_i2s (&id[msg->npeers - 1]), msg->npeers); + + return GNUNET_YES; +} + + +/** + * Iterator over all tunnels to send a monitoring client info about each tunnel. + * + * @param cls Closure (client handle). + * @param key Key (hashed tunnel ID, unused). + * @param value Tunnel info. + * + * @return GNUNET_YES, to keep iterating. + */ +static int +monitor_tunnel_iterator (void *cls, + const struct GNUNET_HashCode * key, + void *value) +{ + struct GNUNET_SERVER_Client *client = cls; + struct MeshTunnel *t = value; + struct GNUNET_MESH_LocalMonitor *msg; + uint32_t npeers; + + npeers = GNUNET_CONTAINER_multihashmap_size (t->peers); + msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor) + + npeers * sizeof (struct GNUNET_PeerIdentity)); + GNUNET_PEER_resolve(t->id.oid, &msg->owner); + msg->tunnel_id = htonl (t->id.tid); + msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor) + + npeers * sizeof (struct GNUNET_PeerIdentity)); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR); + msg->npeers = 0; + (void) GNUNET_CONTAINER_multihashmap_iterate (t->peers, + monitor_peers_iterator, + msg); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "* sending info about tunnel %s [%u] (%u peers)\n", + GNUNET_i2s (&msg->owner), t->id.tid, npeers); + + if (msg->npeers != npeers) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Monitor fail: size %u - iter %u\n", + npeers, msg->npeers); + } + + msg->npeers = htonl (npeers); + GNUNET_SERVER_notification_context_unicast (nc, client, + &msg->header, + GNUNET_NO); + return GNUNET_YES; +} + + +/** + * Handler for client's MONITOR request. + * + * @param cls Closure (unused). + * @param client Identification of the client. + * @param message The actual message. + */ +static void +handle_local_monitor (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + struct MeshClient *c; + + /* Sanity check for client registration */ + if (NULL == (c = client_get (client))) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received monitor request from client %u\n", + c->id); + GNUNET_CONTAINER_multihashmap_iterate (tunnels, + monitor_tunnel_iterator, + client); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Monitor request from client %u completed\n", + c->id); + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + + /** * Functions to handle messages from clients */ @@ -8085,6 +8203,9 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = { {&handle_local_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK, sizeof (struct GNUNET_MESH_LocalAck)}, + {&handle_local_monitor, NULL, + GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR, + sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h index b85a8d158..68f163fa5 100644 --- a/src/mesh/mesh.h +++ b/src/mesh/mesh.h @@ -299,6 +299,40 @@ struct GNUNET_MESH_LocalAck }; +/** + * Message to inform the client about tunnels in the service. + */ +struct GNUNET_MESH_LocalMonitor +{ + /** + * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR + */ + struct GNUNET_MessageHeader header; + + /** + * ID of the tunnel allowed to send more data. + */ + MESH_TunnelNumber tunnel_id GNUNET_PACKED; + + /** + * Number of peers in the tunnel. + */ + uint32_t npeers GNUNET_PACKED; + + /** + * Alignment. + */ + uint32_t reserved GNUNET_PACKED; + + /** + * ID of the owner of the tunnel (can be local peer). + */ + struct GNUNET_PeerIdentity owner; + + /* struct GNUNET_PeerIdentity peers[npeers] */ +}; + + GNUNET_NETWORK_STRUCT_END /******************************************************************************/ diff --git a/src/mesh/mesh_api.c b/src/mesh/mesh_api.c index 43c2d9a8b..f7aa6b9b1 100644 --- a/src/mesh/mesh_api.c +++ b/src/mesh/mesh_api.c @@ -207,6 +207,16 @@ struct GNUNET_MESH_Handle */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + /** + * Monitor callback + */ + GNUNET_MESH_MonitorCB monitor_cb; + + /** + * Monitor callback closure. + */ + void *monitor_cls; + #if DEBUG_ACK unsigned int acks_sent; unsigned int acks_recv; @@ -1241,6 +1251,50 @@ process_ack (struct GNUNET_MESH_Handle *h, } +/** + * Process a local monitor reply, pass info to the user. + * + * @param h Mesh handle. + * @param message Message itself. + */ +static void +process_monitor (struct GNUNET_MESH_Handle *h, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_LocalMonitor *msg; + uint32_t npeers; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Monitor messasge received\n"); + + if (NULL == h->monitor_cb) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); + return; + } + + msg = (struct GNUNET_MESH_LocalMonitor *) message; + npeers = ntohl (msg->npeers); + if (ntohs (message->size) != + (sizeof (struct GNUNET_MESH_LocalMonitor) + + npeers * sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_break_op (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Monitor message: size %hu - expected %u (%u peers)\n", + ntohs (message->size), + sizeof (struct GNUNET_MESH_LocalMonitor) + + npeers * sizeof (struct GNUNET_PeerIdentity), + npeers); + return; + } + h->monitor_cb (h->monitor_cls, + &msg->owner, + ntohl (msg->tunnel_id), + (struct GNUNET_PeerIdentity *) &msg[1], + npeers); +} + + /** * Function to process all messages received from the service * @@ -1288,6 +1342,9 @@ msg_received (void *cls, const struct GNUNET_MessageHeader *msg) case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: process_ack (h, msg); break; + case GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR: + process_monitor (h, msg); + break; default: /* We shouldn't get any other packages, log and ignore */ LOG (GNUNET_ERROR_TYPE_WARNING, @@ -1629,10 +1686,11 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) { case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY: + case GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR: break; default: GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_DEBUG, "unexpected msg %u\n", + LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n", ntohs(msg->type)); } @@ -2142,6 +2200,49 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) } +/** + * Request information about the running mesh peer. + * + * @param h Handle to the mesh peer. + * @param callback Function to call with the requested data. + * @param monitor_cls Closure for @c callback. + */ +void +GNUNET_MESH_monitor (struct GNUNET_MESH_Handle *h, + GNUNET_MESH_MonitorCB callback, + void *monitor_cls) +{ + struct GNUNET_MessageHeader msg; + + msg.size = htons (sizeof (msg)); + msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR); + send_packet (h, &msg, NULL); + h->monitor_cb = callback; + h->monitor_cls = monitor_cls; + + return; +} + + +/** + * Cancel a monitor request. The monitor callback will not be called. + * + * @param h Mesh handle. + * + * @return Closure given to GNUNET_MESH_monitor, if any. + */ +void * +GNUNET_MESH_monitor_cancel (struct GNUNET_MESH_Handle *h) +{ + void *cls; + + cls = h->monitor_cls; + h->monitor_cb = NULL; + h->monitor_cls = NULL; + return cls; +} + + /** * Transition API for tunnel ctx management */ -- 2.25.1