trying to make KX logic slightly more readable
[oweals/gnunet.git] / src / cadet / cadet_path.c
index 1b2d377f546146e3c18690d47d4ea5b4a4cd0b82..79a498805bf3853bc36620438143eca9491dee75 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2001 - 2013 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2001 - 2013 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
 
 /**
  * @brief Destroy a path after some time has past.
- *
- * If the path is returned from DHT again after a while, try again.
- *
- * Removes the path from the peer (except for direct paths).
+ * Removes the path from the peer (must not be used for direct paths).
  *
  * @param cls Closure (path to destroy).
- * @param tc Task context.
  */
 static void
-path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+path_destroy_delayed (void *cls)
 {
   struct CadetPeerPath *path = cls;
   struct CadetPeer *peer;
 
-  LOG (GNUNET_ERROR_TYPE_INFO, "Destroy delayed %p (%u)\n", path, path->length);
-  path->path_delete = GNUNET_SCHEDULER_NO_TASK;
-  peer = GCP_get_short (path->peers[path->length - 1]);
-  if (2 < path->length)
-    GCP_remove_path (peer, path);
-  else
-    path_destroy (path);
+  path->path_delete = NULL;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Destroy delayed %p (%u)\n",
+       path,
+       path->length);
+  GNUNET_assert (2 < path->length);
+  peer = GCP_get_short (path->peers[path->length - 1],
+                       GNUNET_NO);
+  GNUNET_assert (NULL != peer);
+  GCP_remove_path (peer, path);
 }
 
 
@@ -61,7 +60,6 @@ path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  * Create a new path
  *
  * @param length How many hops will the path have.
- *
  * @return A newly allocated path with a peer array of the specified length.
  */
 struct CadetPeerPath *
@@ -75,6 +73,7 @@ path_new (unsigned int length)
     p->length = length;
     p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id));
   }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "New path %p (%u)\n", p, p->length);
   return p;
 }
 
@@ -111,7 +110,9 @@ path_duplicate (const struct CadetPeerPath *path)
   unsigned int i;
 
   aux = path_new (path->length);
-  memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id));
+  GNUNET_memcpy (aux->peers,
+         path->peers,
+         path->length * sizeof (GNUNET_PEER_Id));
   for (i = 0; i < aux->length; i++)
     GNUNET_PEER_change_rc (aux->peers[i], 1);
   return aux;
@@ -150,12 +151,16 @@ path_get_length (struct CadetPeerPath *path)
 void
 path_invalidate (struct CadetPeerPath *p)
 {
-  if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
+  if (NULL != p->path_delete)
     return;
 
-  LOG (GNUNET_ERROR_TYPE_INFO, "Invalidating path %p (%u)\n", p, p->length);
-  p->path_delete = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
-                                                 &path_destroy_delayed, p);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Invalidating path %p (%u)\n",
+       p,
+       p->length);
+  p->path_delete
+    = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
+                                   &path_destroy_delayed, p);
 }
 
 
@@ -222,6 +227,43 @@ path_build_from_peer_ids (struct GNUNET_PeerIdentity *peers,
 }
 
 
+/**
+ * Test if two paths are equivalent (equal or revese of each other).
+ *
+ * @param p1 First path
+ * @param p2 Second path
+ *
+ * @return #GNUNET_YES if both paths are equivalent
+ *         #GNUNET_NO otherwise
+ */
+int
+path_equivalent (const struct CadetPeerPath *p1,
+                 const struct CadetPeerPath *p2)
+{
+  unsigned int i;
+  unsigned int l;
+  unsigned int half;
+
+  if (NULL == p1 || NULL == p2)
+    return GNUNET_NO;
+
+  if (p1->length != p2->length)
+    return GNUNET_NO;
+
+  l = p1->length;
+  if (0 == memcmp (p1->peers, p2->peers, sizeof (p1->peers[0]) * l))
+    return GNUNET_YES;
+
+  half = l / 2;
+  l = l - 1;
+  for (i = 0; i <= half; i++)
+    if (p1->peers[i] != p2->peers[l - i])
+      return GNUNET_NO;
+
+  return GNUNET_YES;
+}
+
+
 /**
  * Test if a path is valid (or at least not known to be invalid).
  *
@@ -233,7 +275,7 @@ path_build_from_peer_ids (struct GNUNET_PeerIdentity *peers,
 int
 path_is_valid (const struct CadetPeerPath *path)
 {
-  return (GNUNET_SCHEDULER_NO_TASK == path->path_delete);
+  return (NULL == path->path_delete);
 }
 
 
@@ -242,7 +284,7 @@ path_is_valid (const struct CadetPeerPath *path)
  *
  * @param p the path to destroy
  *
- * @return GNUNET_OK on success
+ * @return #GNUNET_OK on success
  */
 int
 path_destroy (struct CadetPeerPath *p)
@@ -250,16 +292,45 @@ path_destroy (struct CadetPeerPath *p)
   if (NULL == p)
     return GNUNET_OK;
 
-  LOG (GNUNET_ERROR_TYPE_INFO, "destroying path %p (%u)\n", p, p->length);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "destroying path %p (%u)\n",
+       p,
+       p->length);
   GNUNET_PEER_decrement_rcs (p->peers, p->length);
   GNUNET_free_non_null (p->peers);
-  if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
+  if (NULL != p->path_delete)
     GNUNET_SCHEDULER_cancel (p->path_delete);
   GNUNET_free (p);
   return GNUNET_OK;
 }
 
 
+/**
+ * Compare two paths.
+ *
+ * @param p1 First path.
+ * @param p2 Second path.
+ *
+ * @return > 0 if p1 is longer, or the first differing PEER_Id is higher on p1.
+ *         < 0 if p2 is longer, or the first differing PEER_Id is higher on p2.
+ *         0 if they are identical.
+ */
+int
+path_cmp (const struct CadetPeerPath *p1,
+         const struct CadetPeerPath *p2)
+{
+  if (p1->length > p2->length)
+    return 1;
+
+  if (p1->length < p2->length)
+    return -1;
+
+  return memcmp (p1->peers,
+                p2->peers,
+                sizeof (GNUNET_PEER_Id) * p1->length);
+}
+
+
 char *
 path_2s (struct CadetPeerPath *p)
 {