#include "mesh.h"
#include "mesh_path.h"
+#include "gnunet-service-mesh_peer.h"
+
+/**
+ * @brief Destroy a path after some time has past.
+ *
+ * If the path is returned from DHT again after a while, try again.
+ *
+ * @param cls Closure (path to destroy).
+ * @param tc Task context.
+ */
+static void
+path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct MeshPeerPath *path = cls;
+ struct MeshPeer *peer;
+
+ path->path_delete = GNUNET_SCHEDULER_NO_TASK;
+ peer = GMP_get_short (path->peers[path->length - 1]);
+ GMP_remove_path (peer, path);
+}
/**
{
struct MeshPeerPath *p;
- p = GNUNET_malloc (sizeof (struct MeshPeerPath));
+ p = GNUNET_new (struct MeshPeerPath);
if (length > 0)
{
p->length = length;
* @param path The path to duplicate.
*/
struct MeshPeerPath *
-path_duplicate (struct MeshPeerPath *path)
+path_duplicate (const struct MeshPeerPath *path)
{
struct MeshPeerPath *aux;
unsigned int i;
aux = path_new (path->length);
memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id));
- for (i = 0; i < path->length; i++)
- GNUNET_PEER_change_rc (path->peers[i], 1);
+ for (i = 0; i < aux->length; i++)
+ GNUNET_PEER_change_rc (aux->peers[i], 1);
return aux;
}
}
+
+/**
+ * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop.
+ *
+ * DHT_get sometimes returns bad cached results, for instance, on a locally
+ * cached result where the PUT followed a path that is no longer current.
+ *
+ * @param p Path to invalidate.
+ */
+void
+path_invalidate (struct MeshPeerPath *p)
+{
+ if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
+ return;
+
+ p->path_delete = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
+ &path_destroy_delayed, p);
+}
+
+
+/**
+ * Test if a path is valid (or at least not known to be invalid).
+ *
+ * @param path Path to test.
+ *
+ * @return #GNUNET_YES If the path is valid or unknown,
+ * #GNUNET_NO If the path is known to be invalid.
+ */
+int
+path_is_valid (const struct MeshPeerPath *path)
+{
+ return (GNUNET_SCHEDULER_NO_TASK == path->path_delete);
+}
+
+
/**
* Destroy the path and free any allocated resources linked to it
*
{
if (NULL == p)
return GNUNET_OK;
+
GNUNET_PEER_decrement_rcs (p->peers, p->length);
GNUNET_free_non_null (p->peers);
+ if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
+ GNUNET_SCHEDULER_cancel (p->path_delete);
GNUNET_free (p);
return GNUNET_OK;
}
+
+char *
+path_2s (struct MeshPeerPath *p)
+{
+ char *s;
+ char *old;
+ unsigned int i;
+
+ s = old = NULL;
+ for (i = 0; i < p->length; i++)
+ {
+ GNUNET_asprintf (&s, "%s %s",
+ old, GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
+ GNUNET_free_non_null (old);
+ old = s;
+ }
+ return s;
+}
+
+void
+path_debug (struct MeshPeerPath *p)
+{
+ unsigned int i;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH:\n");
+ for (i = 0; i < p->length; i++)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n",
+ GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "END\n");
+}