#include "gnunet_statistics_service.h"
-#include "mesh_enc.h"
-#include "mesh_protocol_enc.h" // GNUNET_MESH_Data is shared
+#include "mesh.h"
+#include "mesh_protocol.h" /* GNUNET_MESH_Data is shared */
#include "gnunet-service-mesh_local.h"
+#include "gnunet-service-mesh_channel.h"
+
+/* INFO DEBUG */
+#include "gnunet-service-mesh_tunnel.h"
+#include "gnunet-service-mesh_peer.h"
#define LOG(level, ...) GNUNET_log_from(level,"mesh-loc",__VA_ARGS__)
{
struct MeshClient *c;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "client connected: %p\n", client);
if (NULL == client)
return;
c = GNUNET_new (struct MeshClient);
" Channel %s destroy, due to client %s shutdown.\n",
GMCH_2s (ch), GML_2s (c));
- GMCH_handle_local_destroy (ch, c);
+ GMCH_handle_local_destroy (ch, c, key < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV);
return GNUNET_OK;
}
uint32_t *p;
unsigned int i;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
/* Check data sanity */
{
struct MeshClient *c;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
/* Sanity check for client registration */
struct MeshChannel *ch;
MESH_ChannelNumber chid;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Got a DESTROY CHANNEL from client!\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n");
/* Sanity check for client registration */
if (NULL == (c = GML_client_get (client)))
/* Retrieve tunnel */
chid = ntohl (msg->channel_id);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " for channel %X\n", chid);
ch = GML_channel_get (c, chid);
if (NULL == ch)
{
- LOG (GNUNET_ERROR_TYPE_ERROR, " channel %X not found\n", chid);
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " channel %X not found\n", chid);
+ GNUNET_STATISTICS_update (stats,
+ "# client destroy messages on unknown channel",
+ 1, GNUNET_NO);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- GMCH_handle_local_destroy (ch, c);
+ GMCH_handle_local_destroy (ch, c, chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
size_t size;
int fwd;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Got data from a client!\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client!\n");
/* Sanity check for client registration */
if (NULL == (c = GML_client_get (client)))
/* Channel exists? */
chid = ntohl (msg->id);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid);
fwd = chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
ch = GML_channel_get (c, chid);
if (NULL == ch)
{
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ GNUNET_STATISTICS_update (stats,
+ "# client data messages on unknown channel",
+ 1, GNUNET_NO);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
MESH_ChannelNumber chid;
int fwd;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
/* Sanity check for client registration */
LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch);
if (NULL == ch)
{
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_WARNING, "Channel %X unknown.\n", chid);
- LOG (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X unknown.\n", chid);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id);
+ GNUNET_STATISTICS_update (stats,
+ "# client ack messages on unknown channel",
+ 1, GNUNET_NO);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- /* If client is root, the ACK is going FWD, therefore this is "BCK". */
- /* If client is dest, the ACK is going BCK, therefore this is "FWD" */
+ /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
+ /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
GMCH_handle_local_ack (ch, fwd);
}
-/*
+
+/**
+ * Iterator over all peers to send a monitoring client info about each peer.
+ *
+ * @param cls Closure ().
+ * @param peer Peer ID (tunnel remote peer).
+ * @param value Peer info.
+ *
+ * @return #GNUNET_YES, to keep iterating.
+ */
+static int
+get_all_peers_iterator (void *cls,
+ const struct GNUNET_PeerIdentity * peer,
+ void *value)
+{
+ struct GNUNET_SERVER_Client *client = cls;
+ struct MeshPeer *p = value;
+ struct GNUNET_MESH_LocalInfoPeer msg;
+
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS);
+ msg.destination = *peer;
+ msg.paths = htons (GMP_count_paths (p));
+ msg.tunnel = htons (NULL != GMP_get_tunnel (p));
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n",
+ GNUNET_i2s (peer));
+
+ GNUNET_SERVER_notification_context_unicast (nc, client,
+ &msg.header, GNUNET_NO);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's INFO PEERS request.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_get_peers (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct MeshClient *c;
+ struct GNUNET_MessageHeader reply;
+
+ /* Sanity check for client registration */
+ if (NULL == (c = GML_client_get (client)))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received get peers request from client %u (%p)\n",
+ c->id, client);
+
+ GMP_iterate_all (get_all_peers_iterator, client);
+ reply.size = htons (sizeof (reply));
+ reply.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS);
+ GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get peers request from client %u completed\n", c->id);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
* 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 cls Closure ().
+ * @param peer Peer ID (tunnel remote peer).
* @param value Tunnel info.
*
- * @return GNUNET_YES, to keep iterating.
+ * @return #GNUNET_YES, to keep iterating.
*/
-// static int
-// monitor_all_tunnels_iterator (void *cls,
-// const struct GNUNET_HashCode * key,
-// void *value)
-// {
-// struct GNUNET_SERVER_Client *client = cls;
-// struct MeshChannel *ch = value;
-// struct GNUNET_MESH_LocalMonitor *msg;
-//
-// msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
-// msg->channel_id = htonl (ch->gid);
-// msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
-// msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
-//
-// LOG (GNUNET_ERROR_TYPE_INFO,
-// "* sending info about tunnel %s\n",
-// GNUNET_i2s (&msg->owner));
-//
-// GNUNET_SERVER_notification_context_unicast (nc, client,
-// &msg->header, GNUNET_NO);
-// return GNUNET_YES;
-// }
+static int
+get_all_tunnels_iterator (void *cls,
+ const struct GNUNET_PeerIdentity * peer,
+ void *value)
+{
+ struct GNUNET_SERVER_Client *client = cls;
+ struct MeshTunnel3 *t = value;
+ struct GNUNET_MESH_LocalInfoTunnel msg;
+
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
+ msg.destination = *peer;
+ msg.channels = htonl (GMT_count_channels (t));
+ msg.connections = htonl (GMT_count_connections (t));
+ msg.cstate = htons ((uint16_t) GMT_get_cstate (t));
+ msg.estate = htons ((uint16_t) GMT_get_estate (t));
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n",
+ GNUNET_i2s (peer));
+
+ GNUNET_SERVER_notification_context_unicast (nc, client,
+ &msg.header, GNUNET_NO);
+ return GNUNET_YES;
+}
/**
- * Handler for client's MONITOR request.
+ * Handler for client's INFO TUNNELS request.
*
* @param cls Closure (unused).
* @param client Identification of the client.
const struct GNUNET_MessageHeader *message)
{
struct MeshClient *c;
+ struct GNUNET_MessageHeader reply;
/* Sanity check for client registration */
if (NULL == (c = GML_client_get (client)))
return;
}
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Received get tunnels request from client %u\n",
- c->id);
-// GNUNET_CONTAINER_multihashmap_iterate (tunnels,
-// monitor_all_tunnels_iterator,
-// client);
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Get tunnels request from client %u completed\n",
- c->id);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received get tunnels request from client %u (%p)\n",
+ c->id, client);
+
+ GMT_iterate_all (get_all_tunnels_iterator, client);
+ reply.size = htons (sizeof (reply));
+ reply.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
+ GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get tunnels request from client %u completed\n", c->id);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
+static void
+iter_connection (void *cls, struct MeshConnection *c)
+{
+ struct GNUNET_MESH_LocalInfoTunnel *msg = cls;
+ struct GNUNET_MeshHash *h = (struct GNUNET_MeshHash *) &msg[1];
+
+ h[msg->connections] = *(GMC_get_id (c));
+ msg->connections++;
+}
+
+static void
+iter_channel (void *cls, struct MeshChannel *ch)
+{
+ struct GNUNET_MESH_LocalInfoTunnel *msg = cls;
+ struct GNUNET_HashCode *h = (struct GNUNET_HashCode *) &msg[1];
+ MESH_ChannelNumber *chn = (MESH_ChannelNumber *) &h[msg->connections];
+
+ chn[msg->channels] = GMCH_get_id (ch);
+ msg->channels++;
+}
+
+
/**
- * Handler for client's MONITOR_TUNNEL request.
+ * Handler for client's SHOW_TUNNEL request.
*
* @param cls Closure (unused).
* @param client Identification of the client.
handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
- const struct GNUNET_MESH_LocalMonitor *msg;
- struct GNUNET_MESH_LocalMonitor *resp;
+ const struct GNUNET_MESH_LocalInfo *msg;
+ struct GNUNET_MESH_LocalInfoTunnel *resp;
struct MeshClient *c;
- struct MeshChannel *ch;
+ struct MeshTunnel3 *t;
+ unsigned int ch_n;
+ unsigned int c_n;
+ size_t size;
/* Sanity check for client registration */
if (NULL == (c = GML_client_get (client)))
return;
}
- msg = (struct GNUNET_MESH_LocalMonitor *) message;
+ msg = (struct GNUNET_MESH_LocalInfo *) message;
LOG (GNUNET_ERROR_TYPE_INFO,
- "Received tunnel info request from client %u for tunnel %s[%X]\n",
- c->id,
- &msg->owner,
- ntohl (msg->channel_id));
-// ch = channel_get (&msg->owner, ntohl (msg->channel_id));
- ch = NULL; // FIXME
- if (NULL == ch)
+ "Received tunnel info request from client %u for tunnel %s\n",
+ c->id, GNUNET_i2s_full(&msg->peer));
+
+ t = GMP_get_tunnel (GMP_get (&msg->peer));
+ if (NULL == t)
{
/* We don't know the tunnel */
- struct GNUNET_MESH_LocalMonitor warn;
+ struct GNUNET_MESH_LocalInfoTunnel warn;
+
+ LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n",
+ GNUNET_i2s_full(&msg->peer), sizeof (warn));
+ warn.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
+ warn.header.size = htons (sizeof (warn));
+ warn.destination = msg->peer;
+ warn.channels = htonl (0);
+ warn.connections = htonl (0);
+ warn.cstate = htons (0);
+ warn.estate = htons (0);
- warn = *msg;
GNUNET_SERVER_notification_context_unicast (nc, client,
&warn.header,
GNUNET_NO);
}
/* Initialize context */
- resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
- *resp = *msg;
- resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
+ ch_n = GMT_count_channels (t);
+ c_n = GMT_count_connections (t);
+
+ size = sizeof (struct GNUNET_MESH_LocalInfoTunnel);
+ size += c_n * sizeof (struct GNUNET_HashCode);
+ size += ch_n * sizeof (MESH_ChannelNumber);
+
+ resp = GNUNET_malloc (size);
+ resp->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
+ resp->header.size = htons (size);
+ GMT_iterate_connections (t, &iter_connection, resp);
+ GMT_iterate_channels (t, &iter_channel, resp);
+ /* Do not interleave with iterators, iter_channel needs conn in HBO */
+ resp->destination = msg->peer;
+ resp->connections = htonl (resp->connections);
+ resp->channels = htonl (resp->channels);
+ resp->cstate = htons (GMT_get_cstate (t));
+ resp->estate = htons (GMT_get_estate (t));
GNUNET_SERVER_notification_context_unicast (nc, c->handle,
&resp->header, GNUNET_NO);
GNUNET_free (resp);
LOG (GNUNET_ERROR_TYPE_INFO,
- "Monitor tunnel request from client %u completed\n",
- c->id);
+ "Show tunnel request from client %u completed. %u conn, %u ch\n",
+ c->id, c_n, ch_n);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
{&handle_data, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
{&handle_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
sizeof (struct GNUNET_MESH_LocalAck)},
+ {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS,
+ sizeof (struct GNUNET_MessageHeader)},
{&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
sizeof (struct GNUNET_MessageHeader)},
{&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
- sizeof (struct GNUNET_MESH_LocalMonitor)},
+ sizeof (struct GNUNET_MESH_LocalInfo)},
{NULL, NULL, 0, 0}
};
void
GML_init (struct GNUNET_SERVER_Handle *handle)
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
server_handle = handle;
GNUNET_SERVER_suspend (server_handle);
ports = GNUNET_CONTAINER_multihashmap32_create (32);
/**
- * Get a chennel from a client
+ * Get a channel from a client.
*
- * @param c the client to check
- * @param chid Channel ID, must be local (> 0x800...)
+ * @param c Client to check.
+ * @param chid Channel ID, must be local (> 0x800...).
*
* @return non-NULL if channel exists in the clients lists
*/
struct MeshChannel *
GML_channel_get (struct MeshClient *c, MESH_ChannelNumber chid)
{
+ struct GNUNET_CONTAINER_MultiHashMap32 *map;
+
if (0 == (chid & GNUNET_MESH_LOCAL_CHANNEL_ID_CLI))
{
GNUNET_break_op (0);
LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
return NULL;
}
+
if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
- return GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels, chid);
- return GNUNET_CONTAINER_multihashmap32_get (c->own_channels, chid);
+ map = c->incoming_channels;
+ else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)
+ map = c->own_channels;
+ else
+ {
+ GNUNET_break (0);
+ map = NULL;
+ }
+ if (NULL == map)
+ {
+ GNUNET_break (0);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Client %s does no t have a valid map for CHID %X\n",
+ GML_2s (c), chid);
+ return NULL;
+ }
+ return GNUNET_CONTAINER_multihashmap32_get (map, chid);
}
/**
- * Remove a channel from a client
+ * Remove a channel from a client.
*
* @param client Client.
* @param chid Channel ID.
struct MeshChannel *ch)
{
if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid)
- GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, chid, ch);
+ GNUNET_break (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels,
+ chid, ch));
else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= chid)
- GNUNET_CONTAINER_multihashmap32_remove (client->own_channels, chid, ch);
+ GNUNET_break (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
+ chid, ch));
else
GNUNET_break (0);
}
}
+
/**
* Notify the client that a new incoming channel was created.
*
- * @param ch Channel that was created.
+ * @param c Client to notify.
+ * @param id Channel ID.
+ * @param port Channel's destination port.
+ * @param opt Options (bit array).
+ * @param peer Origin peer.
*/
void
GML_send_channel_create (struct MeshClient *c,
struct GNUNET_MESH_ChannelMessage msg;
msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE);
msg.channel_id = htonl (id);
msg.port = htonl (port);
msg.opt = htonl (opt);
}
+/**
+ * Build a local channel NACK message and send it to a local client.
+ *
+ * @param c Client to whom send the NACK.
+ * @param id Channel ID to use
+ */
+void
+GML_send_channel_nack (struct MeshClient *c, MESH_ChannelNumber id)
+{
+ struct GNUNET_MESH_LocalAck msg;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "send local nack on %X towards %p\n",
+ id, c);
+
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK);
+ msg.channel_id = htonl (id);
+ GNUNET_SERVER_notification_context_unicast (nc,
+ c->handle,
+ &msg.header,
+ GNUNET_NO);
+
+}
+
/**
* Notify a client that a channel is no longer valid.
*
GNUNET_break (0);
return;
}
+ if (GNUNET_YES == c->shutting_down)
+ return;
msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY);
msg.channel_id = htonl (id);
msg.port = htonl (0);
memset (&msg.peer, 0, sizeof (msg.peer));