*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
*
*/
#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
*/
libexec_PROGRAMS = \
gnunet-service-mesh gnunet-service-mesh-new
+bin_PROGRAMS = \
+ gnunet-mesh
+
lib_LTLIBRARIES = \
libgnunetmesh.la \
libgnunetmeshblock.la
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 \
}
#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);
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. */
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
*/
{&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}
};
};
+/**
+ * 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
/******************************************************************************/
*/
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;
}
+/**
+ * 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
*
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,
{
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));
}
}
+/**
+ * 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
*/