- fix
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_local.c
index 8fc01f929607266edd32eb104eea7a77d74d53ef..84adb7d0e6692405c84b430704be6d9b30733b17 100644 (file)
@@ -32,6 +32,7 @@
 
 /* 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__)
 
@@ -298,7 +299,8 @@ handle_new_client (void *cls, struct GNUNET_SERVER_Client *client,
   uint32_t *p;
   unsigned int i;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\nnew client connected %p\n", client);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
 
   /* Check data sanity */
   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
@@ -409,7 +411,7 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
   struct MeshChannel *ch;
   MESH_ChannelNumber chid;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\nGot 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)))
@@ -469,7 +471,7 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client,
   size_t size;
   int fwd;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\nGot 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)))
@@ -578,19 +580,90 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
 }
 
 
+
+/**
+ * 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 cls Closure ().
  * @param peer Peer ID (tunnel remote peer).
  * @param value Tunnel info.
  *
  * @return #GNUNET_YES, to keep iterating.
  */
 static int
-monitor_all_tunnels_iterator (void *cls,
-                              const struct GNUNET_PeerIdentity * peer,
-                              void *value)
+get_all_tunnels_iterator (void *cls,
+                          const struct GNUNET_PeerIdentity * peer,
+                          void *value)
 {
   struct GNUNET_SERVER_Client *client = cls;
   struct MeshTunnel3 *t = value;
@@ -599,10 +672,10 @@ monitor_all_tunnels_iterator (void *cls,
   msg.header.size = htons (sizeof (msg));
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
   msg.destination = *peer;
-  msg.channels = htons (42);
-  msg.connections = htons (42);
-  msg.cstate = htons (GMT_get_cstate (t));
-  msg.estate = htons (42);
+  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));
@@ -625,8 +698,7 @@ handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
                     const struct GNUNET_MessageHeader *message)
 {
   struct MeshClient *c;
-  size_t size;
-  struct GNUNET_MessageHeader *reply;
+  struct GNUNET_MessageHeader reply;
 
   /* Sanity check for client registration */
   if (NULL == (c = GML_client_get (client)))
@@ -636,27 +708,45 @@ handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
     return;
   }
 
-  LOG (GNUNET_ERROR_TYPE_INFO, "Received get tunnels request from client %u\n",
-       c->id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received get tunnels request from client %u (%p)\n",
+       c->id, client);
 
-  size = GMT_count_all () + 1; /* Last one is all \0 to mark 'end' */
-  size *= sizeof (struct GNUNET_PeerIdentity);
-  size += sizeof (*reply);
-  reply = GNUNET_malloc (size);
-  GMT_iterate_all (reply, monitor_all_tunnels_iterator);
-  reply->size = htons (size);
-  reply->type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
-  GNUNET_SERVER_notification_context_unicast (nc, client, reply, GNUNET_NO);
+  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_INFO,
-              "Get tunnels request from client %u completed\n",
-              c->id);
+  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.
@@ -667,9 +757,12 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
                     const struct GNUNET_MessageHeader *message)
 {
   const struct GNUNET_MESH_LocalInfo *msg;
-  struct GNUNET_MESH_LocalInfo *resp;
+  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)))
@@ -681,18 +774,25 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
 
   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_LocalInfo 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);
@@ -701,16 +801,31 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
   }
 
   /* Initialize context */
-  resp = GNUNET_new (struct GNUNET_MESH_LocalInfo);
-  *resp = *msg;
-  resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalInfo));
+  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);
 }
 
@@ -727,6 +842,8 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
   {&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,