[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
***********************************/
/******************************************************************************/
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r29839 - gnunet/src/mesh,
gnunet <=