gnunet-svn
[Top][All Lists]
Advanced

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

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


From: gnunet
Subject: [GNUnet-SVN] r29839 - gnunet/src/mesh
Date: Fri, 4 Oct 2013 11:13:35 +0200

Author: bartpolot
Date: 2013-10-04 11:13:35 +0200 (Fri, 04 Oct 2013)
New Revision: 29839

Modified:
   gnunet/src/mesh/gnunet-service-mesh-enc.c
   gnunet/src/mesh/gnunet-service-mesh_dht.c
   gnunet/src/mesh/gnunet-service-mesh_dht.h
   gnunet/src/mesh/gnunet-service-mesh_peer.c
Log:
- sync


Modified: gnunet/src/mesh/gnunet-service-mesh-enc.c
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh-enc.c   2013-10-04 07:43:50 UTC (rev 
29838)
+++ gnunet/src/mesh/gnunet-service-mesh-enc.c   2013-10-04 09:13:35 UTC (rev 
29839)
@@ -913,463 +913,7 @@
   return sizeof (struct GNUNET_MESH_ConnectionACK);
 }
 
-
 /**
- * Destroy the peer_info and free any allocated resources linked to it
- *
- * @param peer The peer_info to destroy.
- *
- * @return GNUNET_OK on success
- */
-static int
-peer_destroy (struct MeshPeer *peer)
-{
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerPath *p;
-  struct MeshPeerPath *nextp;
-
-  GNUNET_PEER_resolve (peer->id, &id);
-  GNUNET_PEER_change_rc (peer->id, -1);
-
-  if (GNUNET_YES !=
-      GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "removing peer %s, not in peermap\n", GNUNET_i2s (&id));
-  }
-  if (NULL != peer->dhtget)
-  {
-    GNUNET_DHT_get_stop (peer->dhtget);
-  }
-  p = peer->path_head;
-  while (NULL != p)
-  {
-    nextp = p->next;
-    GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
-    path_destroy (p);
-    p = nextp;
-  }
-  tunnel_destroy_empty (peer->tunnel);
-  GNUNET_free (peer);
-  return GNUNET_OK;
-}
-
-
-/**
- * Returns if peer is used (has a tunnel, is neighbor).
- *
- * @peer Peer to check.
- *
- * @return GNUNET_YES if peer is in use.
- */
-static int
-peer_is_used (struct MeshPeer *peer)
-{
-  struct MeshPeerPath *p;
-
-  if (NULL != peer->tunnel)
-    return GNUNET_YES;
-
-  for (p = peer->path_head; NULL != p; p = p->next)
-  {
-    if (p->length < 3)
-      return GNUNET_YES;
-  }
-  return GNUNET_NO;
-}
-
-
-/**
- * Iterator over all the peers to get the oldest timestamp.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- */
-static int
-peer_get_oldest (void *cls,
-                 const struct GNUNET_PeerIdentity *key,
-                 void *value)
-{
-  struct MeshPeer *p = value;
-  struct GNUNET_TIME_Absolute *abs = cls;
-
-  /* Don't count active peers */
-  if (GNUNET_YES == peer_is_used (p))
-    return GNUNET_YES;
-
-  if (abs->abs_value_us < p->last_contact.abs_value_us)
-    abs->abs_value_us = p->last_contact.abs_value_us;
-
-  return GNUNET_YES;
-}
-
-
-/**
- * Iterator over all the peers to remove the oldest entry.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- */
-static int
-peer_timeout (void *cls,
-              const struct GNUNET_PeerIdentity *key,
-              void *value)
-{
-  struct MeshPeer *p = value;
-  struct GNUNET_TIME_Absolute *abs = cls;
-
-  if (p->last_contact.abs_value_us == abs->abs_value_us &&
-      GNUNET_NO == peer_is_used (p))
-  {
-    peer_destroy (p);
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-}
-
-
-/**
- * Delete oldest unused peer.
- */
-static void
-peer_delete_oldest (void)
-{
-  struct GNUNET_TIME_Absolute abs;
-
-  abs = GNUNET_TIME_UNIT_FOREVER_ABS;
-
-  GNUNET_CONTAINER_multipeermap_iterate (peers,
-                                         &peer_get_oldest,
-                                         &abs);
-  GNUNET_CONTAINER_multipeermap_iterate (peers,
-                                         &peer_timeout,
-                                         &abs);
-}
-
-
-/**
- * Retrieve the MeshPeer stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer Full identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeer *
-peer_get (const struct GNUNET_PeerIdentity *peer_id)
-{
-  struct MeshPeer *peer;
-
-  peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
-  if (NULL == peer)
-  {
-    peer = GNUNET_new (struct MeshPeer);
-    if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
-    {
-      peer_delete_oldest ();
-    }
-    GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-    peer->id = GNUNET_PEER_intern (peer_id);
-  }
-  peer->last_contact = GNUNET_TIME_absolute_get();
-
-  return peer;
-}
-
-
-/**
- * Retrieve the MeshPeer stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer Short identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeer *
-peer_get_short (const GNUNET_PEER_Id peer)
-{
-  return peer_get (GNUNET_PEER_resolve2 (peer));
-}
-
-
-/**
- * Get a cost of a path for a peer considering existing tunnel connections.
- *
- * @param peer Peer towards which the path is considered.
- * @param path Candidate path.
- *
- * @return Cost of the path (path length + number of overlapping nodes)
- */
-static unsigned int
-peer_get_path_cost (const struct MeshPeer *peer,
-                    const struct MeshPeerPath *path)
-{
-  struct MeshConnection *c;
-  unsigned int overlap;
-  unsigned int i;
-  unsigned int j;
-
-  if (NULL == path)
-    return 0;
-
-  overlap = 0;
-  GNUNET_assert (NULL != peer->tunnel);
-
-  for (i = 0; i < path->length; i++)
-  {
-    for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
-    {
-      for (j = 0; j < c->path->length; j++)
-      {
-        if (path->peers[i] == c->path->peers[j])
-        {
-          overlap++;
-          break;
-        }
-      }
-    }
-  }
-  return (path->length + overlap) * (path->score * -1);
-}
-
-
-/**
- * Choose the best path towards a peer considering the tunnel properties.
- *
- * @param peer The destination peer.
- *
- * @return Best current known path towards the peer, if any.
- */
-static struct MeshPeerPath *
-peer_get_best_path (const struct MeshPeer *peer)
-{
-  struct MeshPeerPath *best_p;
-  struct MeshPeerPath *p;
-  struct MeshConnection *c;
-  unsigned int best_cost;
-  unsigned int cost;
-
-  best_cost = UINT_MAX;
-  best_p = NULL;
-  for (p = peer->path_head; NULL != p; p = p->next)
-  {
-    for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
-      if (c->path == p)
-        break;
-    if (NULL != c)
-      continue; /* If path is in use in a connection, skip it. */
-
-    if ((cost = peer_get_path_cost (peer, p)) < best_cost)
-    {
-      best_cost = cost;
-      best_p = p;
-    }
-  }
-  return best_p;
-}
-
-
-
-/**
- * Try to establish a new connection to this peer in the given tunnel.
- * If the peer doesn't have any path to it yet, try to get one.
- * If the peer already has some path, send a CREATE CONNECTION towards it.
- *
- * @param peer PeerInfo of the peer.
- */
-static void
-peer_connect (struct MeshPeer *peer)
-{
-  struct MeshTunnel2 *t;
-  struct MeshPeerPath *p;
-  struct MeshConnection *c;
-  int rerun_dhtget;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "peer_connect towards %s\n",
-              peer2s (peer));
-  t = peer->tunnel;
-  c = NULL;
-  rerun_dhtget = GNUNET_NO;
-
-  if (NULL != peer->path_head)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "path exists\n");
-    p = peer_get_best_path (peer);
-    if (NULL != p)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  %u hops\n", p->length);
-      c = tunnel_use_path (t, p);
-      if (NULL == c)
-      {
-        /* This case can happen when the path includes a first hop that is
-         * not yet known to be connected.
-         * 
-         * This happens quite often during testing when running mesh
-         * under valgrind: core connect notifications come very late and the
-         * DHT result has already come and created a valid path.
-         * In this case, the peer->connections hashmap will be NULL and
-         * tunnel_use_path will not be able to create a connection from that
-         * path.
-         *
-         * Re-running the DHT GET should give core time to callback.
-         */
-        GNUNET_break(0);
-        rerun_dhtget = GNUNET_YES;
-      }
-      else
-      {
-        send_connection_create (c);
-        return;
-      }
-    }
-  }
-
-  if (NULL != peer->dhtget && GNUNET_YES == rerun_dhtget)
-  {
-    GNUNET_DHT_get_stop (peer->dhtget);
-    peer->dhtget = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Stopping DHT GET for peer %s\n", peer2s (peer));
-  }
-
-  if (NULL == peer->dhtget)
-  {
-    const struct GNUNET_PeerIdentity *id;
-    struct GNUNET_HashCode phash;
-
-    id = GNUNET_PEER_resolve2 (peer->id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Starting DHT GET for peer %s\n", peer2s (peer));
-    GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &phash);
-    peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
-                                         GNUNET_BLOCK_TYPE_MESH_PEER, /* type 
*/
-                                         &phash,     /* key to search */
-                                         dht_replication_level, /* replication 
level */
-                                         GNUNET_DHT_RO_RECORD_ROUTE |
-                                         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
-                                         NULL,       /* xquery */
-                                         0,     /* xquery bits */
-                                         &dht_get_id_handler, peer);
-    if (MESH_TUNNEL_NEW == t->state)
-      tunnel_change_state (t, MESH_TUNNEL_SEARCHING);
-  }
-}
-
-
-
-/**
- * Add the path to the peer and update the path used to reach it in case this
- * is the shortest.
- *
- * @param peer_info Destination peer to add the path to.
- * @param path New path to add. Last peer must be the peer in arg 1.
- *             Path will be either used of freed if already known.
- * @param trusted Do we trust that this path is real?
- */
-void
-peer_add_path (struct MeshPeer *peer_info, struct MeshPeerPath *path,
-                    int trusted)
-{
-  struct MeshPeerPath *aux;
-  unsigned int l;
-  unsigned int l2;
-
-  if ((NULL == peer_info) || (NULL == path))
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return;
-  }
-  if (path->peers[path->length - 1] != peer_info->id)
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return;
-  }
-  if (2 >= path->length && GNUNET_NO == trusted)
-  {
-    /* Only allow CORE to tell us about direct paths */
-    path_destroy (path);
-    return;
-  }
-  for (l = 1; l < path->length; l++)
-  {
-    if (path->peers[l] == myid)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
-      for (l2 = 0; l2 < path->length - l; l2++)
-      {
-        path->peers[l2] = path->peers[l + l2];
-      }
-      path->length -= l;
-      l = 1;
-      path->peers =
-          GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
-    }
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
-              path->length, peer2s (peer_info));
-
-  l = path_get_length (path);
-  if (0 == l)
-  {
-    path_destroy (path);
-    return;
-  }
-
-  GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
-  for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
-  {
-    l2 = path_get_length (aux);
-    if (l2 > l)
-    {
-      GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
-                                          peer_info->path_tail, aux, path);
-      return;
-    }
-    else
-    {
-      if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
-      {
-        path_destroy (path);
-        return;
-      }
-    }
-  }
-  GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
-                                    path);
-  return;
-}
-
-
-/**
- * Add the path to the origin peer and update the path used to reach it in case
- * this is the shortest.
- * The path is given in peer_info -> destination, therefore we turn the path
- * upside down first.
- *
- * @param peer_info Peer to add the path to, being the origin of the path.
- * @param path New path to add after being inversed.
- *             Path will be either used or freed.
- * @param trusted Do we trust that this path is real?
- */
-static void
-peer_add_path_to_origin (struct MeshPeer *peer_info,
-                         struct MeshPeerPath *path, int trusted)
-{
-  if (NULL == path)
-    return;
-  path_invert (path);
-  peer_add_path (peer_info, path, trusted);
-}
-
-/**
  * Build a PeerPath from the paths returned from the DHT, reversing the paths
  * to obtain a local peer -> destination path and interning the peer ids.
  *
@@ -2630,9 +2174,8 @@
   GML_init (server);    /* Local clients */
   GMC_init (c);         /* Connections */
   GMP_init (c);         /* Peers */
-  GMD_init (c);         /* DHT */
+  GMD_init (c, &my_full_id);         /* DHT */
 
-  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
 }
 

Modified: gnunet/src/mesh/gnunet-service-mesh_dht.c
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh_dht.c   2013-10-04 07:43:50 UTC (rev 
29838)
+++ gnunet/src/mesh/gnunet-service-mesh_dht.c   2013-10-04 09:13:35 UTC (rev 
29839)
@@ -103,10 +103,10 @@
    * - Set data expiration in function of X
    * - Adapt X to churn
    */
-  DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
+  DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (id));
 
-  block.id = my_full_id;
-  GNUNET_CRYPTO_hash (&my_full_id, sizeof (struct GNUNET_PeerIdentity), 
&phash);
+  block.id = *id;
+  GNUNET_CRYPTO_hash (id, sizeof (struct GNUNET_PeerIdentity), &phash);
   GNUNET_DHT_put (dht_handle,   /* DHT handle */
                   &phash,       /* Key to use */
                   dht_replication_level,     /* Replication level */
@@ -131,10 +131,13 @@
  * Initialize the DHT subsystem.
  *
  * @param c Configuration.
+ * @param peer_id Local peer ID (must remain valid during all execution time).
  */
 void
-GMD_init (const struct GNUNET_CONFIGURATION_Handle *c)
+GMD_init (const struct GNUNET_CONFIGURATION_Handle *c,
+          struct GNUNET_PeerIdentity *peer_id)
 {
+  id = peer_id;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (c, "MESH", 
"DHT_REPLICATION_LEVEL",
                                              &dht_replication_level))
@@ -160,7 +163,7 @@
     GNUNET_break (0);
   }
 
-  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
+  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL);
 }
 
 

Modified: gnunet/src/mesh/gnunet-service-mesh_dht.h
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh_dht.h   2013-10-04 07:43:50 UTC (rev 
29838)
+++ gnunet/src/mesh/gnunet-service-mesh_dht.h   2013-10-04 09:13:35 UTC (rev 
29839)
@@ -46,12 +46,14 @@
 
/******************************************************************************/
 
 /**
- * Initialize DHT subsystem.
+ * Initialize the DHT subsystem.
  *
  * @param c Configuration.
+ * @param peer_id Local peer ID (must remain valid during all execution time).
  */
 void
-GMD_init (const struct GNUNET_CONFIGURATION_Handle *c);
+GMD_init (const struct GNUNET_CONFIGURATION_Handle *c,
+          struct GNUNET_PeerIdentity *peer_id);
 
 /**
  * Shut down the DHT subsystem.

Modified: gnunet/src/mesh/gnunet-service-mesh_peer.c
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh_peer.c  2013-10-04 07:43:50 UTC (rev 
29838)
+++ gnunet/src/mesh/gnunet-service-mesh_peer.c  2013-10-04 09:13:35 UTC (rev 
29839)
@@ -23,6 +23,7 @@
 #include "gnunet_util_lib.h"
 
 #include "gnunet-service-mesh_peer.h"
+#include "mesh_path.h"
 
 
/******************************************************************************/
 /********************************   STRUCTS  
**********************************/
@@ -132,6 +133,463 @@
 }
 
 
+
+/**
+ * Destroy the peer_info and free any allocated resources linked to it
+ *
+ * @param peer The peer_info to destroy.
+ *
+ * @return GNUNET_OK on success
+ */
+static int
+peer_destroy (struct MeshPeer *peer)
+{
+  struct GNUNET_PeerIdentity id;
+  struct MeshPeerPath *p;
+  struct MeshPeerPath *nextp;
+  
+  GNUNET_PEER_resolve (peer->id, &id);
+  GNUNET_PEER_change_rc (peer->id, -1);
+  
+  if (GNUNET_YES !=
+    GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "removing peer %s, not in peermap\n", GNUNET_i2s (&id));
+  }
+    if (NULL != peer->dhtget)
+    {
+      GNUNET_DHT_get_stop (peer->dhtget);
+    }
+      p = peer->path_head;
+      while (NULL != p)
+      {
+        nextp = p->next;
+        GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
+        path_destroy (p);
+        p = nextp;
+      }
+        tunnel_destroy_empty (peer->tunnel);
+        GNUNET_free (peer);
+        return GNUNET_OK;
+}
+
+
+/**
+ * Returns if peer is used (has a tunnel, is neighbor).
+ *
+ * @peer Peer to check.
+ *
+ * @return GNUNET_YES if peer is in use.
+ */
+static int
+peer_is_used (struct MeshPeer *peer)
+{
+  struct MeshPeerPath *p;
+  
+  if (NULL != peer->tunnel)
+    return GNUNET_YES;
+  
+  for (p = peer->path_head; NULL != p; p = p->next)
+  {
+    if (p->length < 3)
+      return GNUNET_YES;
+  }
+    return GNUNET_NO;
+}
+
+
+/**
+ * Iterator over all the peers to get the oldest timestamp.
+ *
+ * @param cls Closure (unsued).
+ * @param key ID of the peer.
+ * @param value Peer_Info of the peer.
+ */
+static int
+peer_get_oldest (void *cls,
+                 const struct GNUNET_PeerIdentity *key,
+                 void *value)
+{
+  struct MeshPeer *p = value;
+  struct GNUNET_TIME_Absolute *abs = cls;
+  
+  /* Don't count active peers */
+  if (GNUNET_YES == peer_is_used (p))
+    return GNUNET_YES;
+  
+  if (abs->abs_value_us < p->last_contact.abs_value_us)
+    abs->abs_value_us = p->last_contact.abs_value_us;
+  
+  return GNUNET_YES;
+}
+
+
+/**
+ * Iterator over all the peers to remove the oldest entry.
+ *
+ * @param cls Closure (unsued).
+ * @param key ID of the peer.
+ * @param value Peer_Info of the peer.
+ */
+static int
+peer_timeout (void *cls,
+              const struct GNUNET_PeerIdentity *key,
+              void *value)
+{
+  struct MeshPeer *p = value;
+  struct GNUNET_TIME_Absolute *abs = cls;
+  
+  if (p->last_contact.abs_value_us == abs->abs_value_us &&
+    GNUNET_NO == peer_is_used (p))
+  {
+    peer_destroy (p);
+    return GNUNET_NO;
+  }
+    return GNUNET_YES;
+}
+
+
+/**
+ * Delete oldest unused peer.
+ */
+static void
+peer_delete_oldest (void)
+{
+  struct GNUNET_TIME_Absolute abs;
+  
+  abs = GNUNET_TIME_UNIT_FOREVER_ABS;
+  
+  GNUNET_CONTAINER_multipeermap_iterate (peers,
+                                         &peer_get_oldest,
+                                         &abs);
+  GNUNET_CONTAINER_multipeermap_iterate (peers,
+                                         &peer_timeout,
+                                         &abs);
+}
+
+
+/**
+ * Retrieve the MeshPeer stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer Full identity of the peer.
+ *
+ * @return Existing or newly created peer info.
+ */
+static struct MeshPeer *
+peer_get (const struct GNUNET_PeerIdentity *peer_id)
+{
+  struct MeshPeer *peer;
+  
+  peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
+  if (NULL == peer)
+  {
+    peer = GNUNET_new (struct MeshPeer);
+    if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
+    {
+      peer_delete_oldest ();
+    }
+        GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer,
+                                           
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+        peer->id = GNUNET_PEER_intern (peer_id);
+  }
+    peer->last_contact = GNUNET_TIME_absolute_get();
+    
+    return peer;
+}
+
+
+/**
+ * Retrieve the MeshPeer stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer Short identity of the peer.
+ *
+ * @return Existing or newly created peer info.
+ */
+static struct MeshPeer *
+peer_get_short (const GNUNET_PEER_Id peer)
+{
+  return peer_get (GNUNET_PEER_resolve2 (peer));
+}
+
+
+/**
+ * Get a cost of a path for a peer considering existing tunnel connections.
+ *
+ * @param peer Peer towards which the path is considered.
+ * @param path Candidate path.
+ *
+ * @return Cost of the path (path length + number of overlapping nodes)
+ */
+static unsigned int
+peer_get_path_cost (const struct MeshPeer *peer,
+                    const struct MeshPeerPath *path)
+{
+  struct MeshConnection *c;
+  unsigned int overlap;
+  unsigned int i;
+  unsigned int j;
+  
+  if (NULL == path)
+    return 0;
+  
+  overlap = 0;
+  GNUNET_assert (NULL != peer->tunnel);
+  
+  for (i = 0; i < path->length; i++)
+  {
+    for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
+    {
+      for (j = 0; j < c->path->length; j++)
+      {
+        if (path->peers[i] == c->path->peers[j])
+        {
+          overlap++;
+          break;
+        }
+      }
+    }
+  }
+    return (path->length + overlap) * (path->score * -1);
+}
+
+
+/**
+ * Choose the best path towards a peer considering the tunnel properties.
+ *
+ * @param peer The destination peer.
+ *
+ * @return Best current known path towards the peer, if any.
+ */
+static struct MeshPeerPath *
+peer_get_best_path (const struct MeshPeer *peer)
+{
+  struct MeshPeerPath *best_p;
+  struct MeshPeerPath *p;
+  struct MeshConnection *c;
+  unsigned int best_cost;
+  unsigned int cost;
+  
+  best_cost = UINT_MAX;
+  best_p = NULL;
+  for (p = peer->path_head; NULL != p; p = p->next)
+  {
+    for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
+      if (c->path == p)
+        break;
+      if (NULL != c)
+        continue; /* If path is in use in a connection, skip it. */
+        
+            if ((cost = peer_get_path_cost (peer, p)) < best_cost)
+            {
+              best_cost = cost;
+              best_p = p;
+            }
+  }
+    return best_p;
+}
+
+
+
+/**
+ * Try to establish a new connection to this peer in the given tunnel.
+ * If the peer doesn't have any path to it yet, try to get one.
+ * If the peer already has some path, send a CREATE CONNECTION towards it.
+ *
+ * @param peer PeerInfo of the peer.
+ */
+static void
+peer_connect (struct MeshPeer *peer)
+{
+  struct MeshTunnel2 *t;
+  struct MeshPeerPath *p;
+  struct MeshConnection *c;
+  int rerun_dhtget;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "peer_connect towards %s\n",
+              peer2s (peer));
+  t = peer->tunnel;
+  c = NULL;
+  rerun_dhtget = GNUNET_NO;
+
+  if (NULL != peer->path_head)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "path exists\n");
+    p = peer_get_best_path (peer);
+    if (NULL != p)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  %u hops\n", p->length);
+      c = tunnel_use_path (t, p);
+      if (NULL == c)
+      {
+        /* This case can happen when the path includes a first hop that is
+         * not yet known to be connected.
+         * 
+         * This happens quite often during testing when running mesh
+         * under valgrind: core connect notifications come very late and the
+         * DHT result has already come and created a valid path.
+         * In this case, the peer->connections hashmap will be NULL and
+         * tunnel_use_path will not be able to create a connection from that
+         * path.
+         *
+         * Re-running the DHT GET should give core time to callback.
+         */
+        GNUNET_break(0);
+        rerun_dhtget = GNUNET_YES;
+      }
+            else
+            {
+              send_connection_create (c);
+              return;
+            }
+    }
+  }
+  
+    if (NULL != peer->dhtget && GNUNET_YES == rerun_dhtget)
+    {
+      GNUNET_DHT_get_stop (peer->dhtget);
+      peer->dhtget = NULL;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "  Stopping DHT GET for peer %s\n", peer2s (peer));
+    }
+    
+      if (NULL == peer->dhtget)
+      {
+        const struct GNUNET_PeerIdentity *id;
+        struct GNUNET_HashCode phash;
+        
+        id = GNUNET_PEER_resolve2 (peer->id);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "  Starting DHT GET for peer %s\n", peer2s (peer));
+        GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &phash);
+        peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
+                                             GNUNET_BLOCK_TYPE_MESH_PEER, /* 
type */
+                                             &phash,     /* key to search */
+                                             dht_replication_level, /* 
replication level */
+                                             GNUNET_DHT_RO_RECORD_ROUTE |
+                                                                               
       GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
+                                             NULL,       /* xquery */
+                                             0,     /* xquery bits */
+                                             &dht_get_id_handler, peer);
+        if (MESH_TUNNEL_NEW == t->state)
+          tunnel_change_state (t, MESH_TUNNEL_SEARCHING);
+      }
+}
+
+
+
+/**
+ * Add the path to the peer and update the path used to reach it in case this
+ * is the shortest.
+ *
+ * @param peer_info Destination peer to add the path to.
+ * @param path New path to add. Last peer must be the peer in arg 1.
+ *             Path will be either used of freed if already known.
+ * @param trusted Do we trust that this path is real?
+ */
+void
+peer_add_path (struct MeshPeer *peer_info, struct MeshPeerPath *path,
+               int trusted)
+{
+  struct MeshPeerPath *aux;
+  unsigned int l;
+  unsigned int l2;
+  
+  if ((NULL == peer_info) || (NULL == path))
+  {
+    GNUNET_break (0);
+    path_destroy (path);
+    return;
+  }
+    if (path->peers[path->length - 1] != peer_info->id)
+    {
+      GNUNET_break (0);
+      path_destroy (path);
+      return;
+    }
+      if (2 >= path->length && GNUNET_NO == trusted)
+      {
+        /* Only allow CORE to tell us about direct paths */
+        path_destroy (path);
+        return;
+      }
+        for (l = 1; l < path->length; l++)
+        {
+          if (path->peers[l] == myid)
+          {
+            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
+            for (l2 = 0; l2 < path->length - l; l2++)
+            {
+              path->peers[l2] = path->peers[l + l2];
+            }
+                  path->length -= l;
+                  l = 1;
+                  path->peers =
+                            GNUNET_realloc (path->peers, path->length * sizeof 
(GNUNET_PEER_Id));
+          }
+        }
+        
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
+                      path->length, peer2s (peer_info));
+          
+          l = path_get_length (path);
+          if (0 == l)
+          {
+            path_destroy (path);
+            return;
+          }
+          
+            GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
+            for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
+            {
+              l2 = path_get_length (aux);
+              if (l2 > l)
+              {
+                GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
+                                                    peer_info->path_tail, aux, 
path);
+                return;
+              }
+                  else
+                  {
+                    if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
+                    {
+                      path_destroy (path);
+                      return;
+                    }
+                  }
+            }
+              GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, 
peer_info->path_tail,
+                                                path);
+              return;
+}
+
+
+/**
+ * Add the path to the origin peer and update the path used to reach it in case
+ * this is the shortest.
+ * The path is given in peer_info -> destination, therefore we turn the path
+ * upside down first.
+ *
+ * @param peer_info Peer to add the path to, being the origin of the path.
+ * @param path New path to add after being inversed.
+ *             Path will be either used or freed.
+ * @param trusted Do we trust that this path is real?
+ */
+static void
+peer_add_path_to_origin (struct MeshPeer *peer_info,
+                         struct MeshPeerPath *path, int trusted)
+{
+  if (NULL == path)
+    return;
+  path_invert (path);
+  peer_add_path (peer_info, path, trusted);
+}
+
+
 
/******************************************************************************/
 /********************************    API    
***********************************/
 
/******************************************************************************/




reply via email to

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