gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r19454 - gnunet/src/mesh


From: gnunet
Subject: [GNUnet-SVN] r19454 - gnunet/src/mesh
Date: Thu, 26 Jan 2012 19:37:12 +0100

Author: bartpolot
Date: 2012-01-26 19:37:12 +0100 (Thu, 26 Jan 2012)
New Revision: 19454

Modified:
   gnunet/src/mesh/gnunet-service-mesh.c
Log:
- Implemented a full explicit list-of-ignored-clients per tunnel to fix #2107

Modified: gnunet/src/mesh/gnunet-service-mesh.c
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh.c       2012-01-26 18:30:56 UTC (rev 
19453)
+++ gnunet/src/mesh/gnunet-service-mesh.c       2012-01-26 18:37:12 UTC (rev 
19454)
@@ -325,6 +325,16 @@
   unsigned int nclients;
 
     /**
+     * Clients that have requested to leave the tunnel
+     */
+  struct MeshClient **ignore;
+
+    /**
+     * Number of elements in clients
+     */
+  unsigned int nignore;
+
+    /**
      * Messages ready to transmit
      */
   struct MeshQueue *queue_head;
@@ -412,6 +422,10 @@
      */
   struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
 
+   /**
+     * Tunnels this client has rejected, indexed by incoming local id
+     */
+  struct GNUNET_CONTAINER_MultiHashMap *ignore_tunnels;
     /**
      * Handle to communicate with the client
      */
@@ -713,6 +727,43 @@
 
/******************************************************************************/
 
 /**
+ * Search for a tunnel by global ID using full PeerIdentities
+ *
+ * @param oid owner of the tunnel
+ * @param tid global tunnel number
+ *
+ * @return tunnel handler, NULL if doesn't exist
+ */
+static struct MeshTunnel *
+tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
+
+
+/**
+ * Delete an active client from the tunnel.
+ * 
+ * @param t Tunnel.
+ * @param c Client.
+ */
+static void
+tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c);
+
+/**
+ * Notify a tunnel that a connection has broken that affects at least
+ * some of its peers.
+ *
+ * @param t Tunnel affected.
+ * @param p1 Peer that got disconnected from p2.
+ * @param p2 Peer that got disconnected from p1.
+ *
+ * @return Short ID of the peer disconnected (either p1 or p2).
+ *         0 if the tunnel remained unaffected.
+ */
+static GNUNET_PEER_Id
+tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
+                                 GNUNET_PEER_Id p2);
+
+
+/**
  * Check if client has registered with the service and has not disconnected
  *
  * @param client the client to check
@@ -782,46 +833,113 @@
 
 
 /**
- * Search for a tunnel by global ID using full PeerIdentities
+ * Check whether client wants traffic from a tunnel.
  *
- * @param oid owner of the tunnel
- * @param tid global tunnel number
+ * @param c Client to check.
+ * @param t Tunnel to be found.
  *
- * @return tunnel handler, NULL if doesn't exist
+ * @return GNUNET_YES if client knows tunnel.
+ * 
+ * TODO look in client hashmap
  */
-static struct MeshTunnel *
-tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
+static int
+client_wants_tunnel (struct MeshClient *c, struct MeshTunnel *t)
+{
+  unsigned int i;
 
+  for (i = 0; i < t->nclients; i++)
+    if (t->clients[i] == c)
+      return GNUNET_YES;
+  return GNUNET_NO;
+}
 
+
 /**
- * Gets the index in t->clients of the client.
+ * Check whether client has been informed about a tunnel.
  *
- * @param t Tunnel where to find client.
- * @param c Client to be found.
+ * @param c Client to check.
+ * @param t Tunnel to be found.
  *
- * @return Index of the client, -1 if not present
+ * @return GNUNET_YES if client knows tunnel.
+ * 
+ * TODO look in client hashmap
  */
 static int
-tunnel_get_client_index (struct MeshTunnel *t, struct MeshClient *c);
+client_knows_tunnel (struct MeshClient *c, struct MeshTunnel *t)
+{
+  unsigned int i;
 
+  for (i = 0; i < t->nignore; i++)
+    if (t->ignore[i] == c)
+      return GNUNET_YES;
+  return client_wants_tunnel(c, t);
+}
 
+
 /**
- * Notify a tunnel that a connection has broken that affects at least
- * some of its peers.
+ * Marks a client as uninterested in traffic from the tunnel, updating both
+ * client and tunnel to reflect this.
  *
- * @param t Tunnel affected.
- * @param p1 Peer that got disconnected from p2.
- * @param p2 Peer that got disconnected from p1.
+ * @param c Client that doesn't want traffic anymore.
+ * @param t Tunnel which should be ignored.
  *
- * @return Short ID of the peer disconnected (either p1 or p2).
- *         0 if the tunnel remained unaffected.
+ * FIXME when to delete an incoming tunnel?
  */
-static GNUNET_PEER_Id
-tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
-                                 GNUNET_PEER_Id p2);
+static void
+client_ignore_tunnel (struct MeshClient *c, struct MeshTunnel *t)
+{
+  GNUNET_HashCode hash;
 
+  GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
+  GNUNET_break (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
+                                                      &hash, t));
+  GNUNET_break (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_put (c->ignore_tunnels, &hash, t,
+                                                   
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+  tunnel_delete_active_client (t, c);
+  GNUNET_array_append (t->ignore, t->nignore, c);
+}
 
+
 /**
+ * Deletes a tunnel from a client (either owner or destination). To be used on
+ * tunnel destroy, otherwise, use client_ignore_tunnel.
+ *
+ * @param c Client whose tunnel to delete.
+ * @param t Tunnel which should be deleted.
+ */
+static void
+client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t)
+{
+  GNUNET_HashCode hash;
+
+  if (c == t->owner)
+  {
+    GNUNET_CRYPTO_hash(&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
+                                                         &hash,
+                                                         t));
+  }
+  else
+  {
+    GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
+    // FIXME XOR?
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
+                                                         &hash,
+                                                         t) ||
+                   GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels,
+                                                         &hash,
+                                                         t));
+  }
+    
+}
+
+
+/**
  * Send the message to all clients that have subscribed to its type
  *
  * @param msg Pointer to the message itself
@@ -836,7 +954,6 @@
   struct MeshClient *c;
   struct MeshTunnel *t;
   MESH_TunnelNumber *tid;
-  GNUNET_HashCode hash;
   unsigned int count;
   uint16_t type;
   char cbuf[htons (msg->size)];
@@ -895,7 +1012,7 @@
       }
       else
       {
-        if (-1 == tunnel_get_client_index (t, c))
+        if (GNUNET_NO == client_knows_tunnel (c, t))
         {
           /* This client doesn't know the tunnel */
           struct GNUNET_MESH_TunnelNotification tmsg;
@@ -918,9 +1035,7 @@
       }
 
       /* Check if the client wants to get traffic from the tunnel */
-      GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), 
&hash);
-      if (GNUNET_NO ==
-          GNUNET_CONTAINER_multihashmap_contains(c->incoming_tunnels, &hash))
+      if (GNUNET_NO == client_wants_tunnel(c, t))
         continue;
       count++;
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      sending\n");
@@ -999,6 +1114,7 @@
       GNUNET_SERVER_notification_context_unicast (nc, t->clients[i]->handle,
                                                   &msg.header, GNUNET_NO);
   }
+  // FIXME when to disconnect an incoming tunnel?
   else if (1 == t->nclients && NULL != t->owner)
   {
     struct GNUNET_MESH_PeerControl msg;
@@ -1974,6 +2090,67 @@
 
 
 /**
+ * Delete an active client from the tunnel.
+ * 
+ * @param t Tunnel.
+ * @param c Client.
+ */
+static void
+tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c)
+{
+  unsigned int i;
+
+  for (i = 0; i < t->nclients; i++)
+  {
+    if (t->clients[i] == c)
+    {
+      t->clients[i] = t->clients[t->nclients - 1];
+      GNUNET_array_grow (t->clients, t->nclients, t->nclients - 1);
+      break;
+    }
+  }
+}
+
+
+/**
+ * Delete an ignored client from the tunnel.
+ * 
+ * @param t Tunnel.
+ * @param c Client.
+ */
+static void
+tunnel_delete_ignored_client (struct MeshTunnel *t, const struct MeshClient *c)
+{
+  unsigned int i;
+
+  for (i = 0; i < t->nignore; i++)
+  {
+    if (t->ignore[i] == c)
+    {
+      t->ignore[i] = t->ignore[t->nignore - 1];
+      GNUNET_array_grow (t->ignore, t->nignore, t->nignore - 1);
+      break;
+    }
+  }
+}
+
+
+/**
+ * Delete a client from the tunnel. It should be only done on
+ * client disconnection, otherwise use client_ignore_tunnel.
+ * 
+ * @param t Tunnel.
+ * @param c Client.
+ */
+static void
+tunnel_delete_client (struct MeshTunnel *t, const struct MeshClient *c)
+{
+  tunnel_delete_ignored_client (t, c);
+  tunnel_delete_active_client (t, c);
+}
+
+
+/**
  * Callback used to notify a client owner of a tunnel that a peer has
  * disconnected, most likely because of a path change.
  *
@@ -2246,27 +2423,6 @@
 
 
 /**
- * Gets the index in t->clients of the client.
- *
- * @param t Tunnel where to find client.
- * @param c Client to be found.
- *
- * @return Index of the client, -1 if not present
- */
-static int
-tunnel_get_client_index (struct MeshTunnel *t, struct MeshClient *c)
-{
-  int i;
-
-  for (i = 0; i < t->nclients; i++)
-    if (t->clients[i] == c)
-      break;
-  if (i < t->nclients)
-    return i;
-  return -1;
-}
-
-/**
  * Send a message to all peers in this tunnel that the tunnel is no longer
  * valid.
  *
@@ -2343,6 +2499,15 @@
       r = GNUNET_SYSERR;
     }
   }
+  for (i = 0; i < t->nignore; i++)
+  {
+    c = t->ignore[i];
+    if (GNUNET_YES !=
+          GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, &hash, t))
+    {
+      r = GNUNET_SYSERR;
+    }
+  }
   if (t->nclients > 0)
   {
     if (GNUNET_YES !=
@@ -2397,26 +2562,6 @@
 
 
 /**
- * Removes a client from the tunnel.
- *
- * @param t Tunnel from which to remove the client.
- * @param c Client that should be removed.
- *
- * FIXME when to delete an incoming tunnel?
- */
-static void
-tunnel_delete_client (struct MeshTunnel *t, struct MeshClient *c)
-{
-  GNUNET_HashCode hash;
-
-  GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
-  GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
-                                                      &hash, t));
-
-}
-
-/**
  * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
  * client when the client disconnects. If the client is not the owner, the
  * owner will get notified if no more clients are in the tunnel and the client
@@ -2442,7 +2587,8 @@
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Client %u is destination, keeping the tunnel alive.\n", 
c->id);
 #endif
-    tunnel_delete_client (t, c);
+    tunnel_delete_client(t, c);
+    client_delete_tunnel(c, t);
     return GNUNET_OK;
   }
   tunnel_send_destroy(t);
@@ -3629,8 +3775,11 @@
                                            &tunnel_destroy_iterator, c);
     GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
                                            &tunnel_destroy_iterator, c);
+    GNUNET_CONTAINER_multihashmap_iterate (c->ignore_tunnels,
+                                           &tunnel_destroy_iterator, c);
     GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
     GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
+    GNUNET_CONTAINER_multihashmap_destroy (c->ignore_tunnels);
 
     /* deregister clients applications */
     if (NULL != c->apps)
@@ -3759,6 +3908,7 @@
   GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
   c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
   c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
+  c->ignore_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
   GNUNET_SERVER_notification_context_add (nc, client);
 
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -3876,7 +4026,6 @@
   struct MeshClient *c;
   struct MeshTunnel *t;
   MESH_TunnelNumber tid;
-  GNUNET_HashCode hash;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "MESH: Got a DESTROY TUNNEL from client!\n");
@@ -3902,20 +4051,20 @@
 
   /* Retrieve tunnel */
   tid = ntohl (tunnel_msg->tunnel_id);
-
-  /* Remove from local id hashmap */
-  GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
-  t = GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
+  t = tunnel_get_by_local_id(c, tid);
   if (NULL == t)
   {
     GNUNET_break (0);
+#if MESH_DEBUG
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MESH:   tunnel %X not found\n", tid);
+#endif
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
   send_client_tunnel_disconnect(t, c);
   if (c != t->owner)
   {
-    tunnel_delete_client (t, c);
+    client_ignore_tunnel (c, t);
 #if 0
     // TODO: when to destroy incoming tunnel?
     if (t->nclients == 0)
@@ -3932,10 +4081,7 @@
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
-                                                       &hash,
-                                                       t));
+  client_delete_tunnel(c, t);
 
   /* Don't try to ACK the client about the tunnel_destroy multicast packet */
   t->owner = NULL;
@@ -4334,7 +4480,7 @@
   }
 
   /*  It should be sent by someone who has this as incoming tunnel. */
-  if (-1 == tunnel_get_client_index (t, c))
+  if (-1 == client_knows_tunnel (c, t))
   {
     GNUNET_break (0);
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]