aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rps/Makefile.am5
-rw-r--r--src/rps/gnunet-service-rps_view.c256
-rw-r--r--src/rps/gnunet-service-rps_view.h124
-rw-r--r--src/rps/test_service_rps_view.c121
4 files changed, 506 insertions, 0 deletions
diff --git a/src/rps/Makefile.am b/src/rps/Makefile.am
index 9425c6e877..c0b60ee0ba 100644
--- a/src/rps/Makefile.am
+++ b/src/rps/Makefile.am
@@ -69,6 +69,7 @@ gnunet_service_rps_LDADD = \
if HAVE_TESTING
check_PROGRAMS = \
+ test_service_rps_view \
test_service_rps_peers \
test_rps_malicious_1 \
test_rps_malicious_2 \
@@ -95,6 +96,10 @@ AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PAT
TESTS = $(check_PROGRAMS)
endif
+test_service_rps_view_SOURCES = gnunet-service-rps_view.h gnunet-service-rps_view.c \
+ test_service_rps_view.c
+test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la
+
test_service_rps_peers_SOURCES = gnunet-service-rps_peers.h gnunet-service-rps_peers.c \
test_service_rps_peers.c
test_service_rps_peers_LDADD = $(top_builddir)/src/util/libgnunetutil.la
diff --git a/src/rps/gnunet-service-rps_view.c b/src/rps/gnunet-service-rps_view.c
new file mode 100644
index 0000000000..2cf0287bb8
--- /dev/null
+++ b/src/rps/gnunet-service-rps_view.c
@@ -0,0 +1,256 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file rps/gnunet-service-rps_view.c
+ * @brief wrapper around the "local view"
+ * @author Julius Bünger
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet-service-rps_view.h"
+#include <inttypes.h>
+
+
+/**
+ * Array containing the peers
+ */
+static struct GNUNET_PeerIdentity *array;
+
+/**
+ * (Maximum) length of the view
+ */
+static uint32_t length;
+
+/**
+ * Multipeermap containing the peers
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *mpm;
+
+
+/**
+ * Create an empty view.
+ *
+ * @param len the maximum length for the view
+ */
+void
+View_create (uint32_t len)
+{
+ length = len;
+ array = GNUNET_new_array (len, struct GNUNET_PeerIdentity);
+ mpm = GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO); /* might even be
+ * set to _YES */
+}
+
+/**
+ * Change length of view
+ *
+ * @param len the (maximum) length for the view
+ */
+void
+View_change_len (uint32_t len)
+{
+ uint32_t i;
+ uint32_t *index;
+
+ if (GNUNET_CONTAINER_multipeermap_size (mpm) < len)
+ { /* Simply shrink */
+ /* We might simply clear and free the left over space */
+ GNUNET_array_grow (array, length, len);
+ }
+ else /* We have to remove elements */
+ {
+ /* TODO find a way to preserve indices */
+ for (i = 0; i < len; i++)
+ {
+ index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]);
+ GNUNET_assert (NULL != index);
+ GNUNET_free (index);
+ }
+ GNUNET_array_grow (array, length, len);
+ GNUNET_CONTAINER_multipeermap_destroy (mpm);
+ mpm = GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO);
+ for (i = 0; i < len; i++)
+ {
+ index = GNUNET_new (uint32_t);
+ *index = i;
+ GNUNET_CONTAINER_multipeermap_put (mpm, &array[i], index,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ }
+ }
+ GNUNET_assert (length == len);
+}
+
+/**
+ * Get the view as an array
+ *
+ * @return the view in array representation
+ */
+const struct GNUNET_PeerIdentity *
+View_get_as_array ()
+{
+ return array;
+}
+
+/**
+ * Get the size of the view
+ *
+ * @return current number of actually contained peers
+ */
+unsigned int
+View_size ()
+{
+ return GNUNET_CONTAINER_multipeermap_size (mpm);
+}
+
+/**
+ * Insert peer into the view
+ *
+ * @param peer the peer to insert
+ *
+ * @return GNUNET_OK if peer was actually inserted
+ * GNUNET_NO if peer was not inserted
+ */
+int
+View_put (const struct GNUNET_PeerIdentity *peer)
+{
+ uint32_t *index;
+
+ if ((length <= View_size ()) || /* If array is 'full' */
+ (GNUNET_YES == View_contains_peer (peer)))
+ {
+ return GNUNET_NO;
+ }
+ else
+ {
+ index = GNUNET_new (uint32_t);
+ *index = (uint32_t) View_size ();
+ array[*index] = *peer;
+ GNUNET_CONTAINER_multipeermap_put (mpm, peer, index,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ return GNUNET_OK;
+ }
+}
+
+/**
+ * Check whether view contains a peer
+ *
+ * @param peer the peer to check for
+ *
+ * @return GNUNET_OK if view contains peer
+ * GNUNET_NO otherwise
+ */
+int
+View_contains_peer (const struct GNUNET_PeerIdentity *peer)
+{
+ return GNUNET_CONTAINER_multipeermap_contains (mpm, peer);
+}
+
+/**
+ * Remove peer from view
+ *
+ * @param peer the peer to remove
+ *
+ * @return GNUNET_OK if view contained peer and removed it successfully
+ * GNUNET_NO if view does not contain peer
+ */
+int
+View_remove_peer (const struct GNUNET_PeerIdentity *peer)
+{
+ uint32_t *index;
+
+ if (GNUNET_YES == View_contains_peer (peer))
+ {
+ index = GNUNET_CONTAINER_multipeermap_get (mpm, peer);
+ GNUNET_assert (NULL != index);
+ if (*index == GNUNET_CONTAINER_multipeermap_size (mpm) - 1)
+ { /* Last peer in array - simply remove */
+ }
+ else
+ { /* Fill the 'gap' in the array with the last peer */
+ array[*index] = array[View_size ()];
+ }
+ GNUNET_CONTAINER_multipeermap_remove_all (mpm, peer);
+ return GNUNET_OK;
+ }
+ else
+ {
+ return GNUNET_NO;
+ }
+}
+
+/**
+ * Get a peer by index
+ *
+ * @param index the index of the peer to get
+ *
+ * @return peer to the corresponding index.
+ * NULL if this index is not known
+ */
+const struct GNUNET_PeerIdentity *
+View_get_peer_by_index (uint32_t index)
+{
+ if (index < GNUNET_CONTAINER_multipeermap_size (mpm))
+ {
+ return &array[index];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/**
+ * Clear the custom peer map
+ *
+ * @param c_peer_map the custom peer map to look in
+ *
+ * @return size of the map
+ */
+void
+View_clear ()
+{
+ uint32_t i;
+ uint32_t *index;
+
+ for (i = 0; i < GNUNET_CONTAINER_multipeermap_size (mpm); i++)
+ { /* Need to free indices stored at peers */
+ index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]);
+ GNUNET_assert (NULL != index);
+ GNUNET_free (index);
+ GNUNET_CONTAINER_multipeermap_remove_all (mpm, &array[i]);
+ }
+ GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (mpm));
+}
+
+/**
+ * Destroy peermap.
+ *
+ * @param c_peer_map the map to destroy
+ */
+void
+View_destroy ()
+{
+ View_clear ();
+ GNUNET_free (array);
+ GNUNET_CONTAINER_multipeermap_destroy (mpm);
+}
+
+/* end of gnunet-service-rps_view.c */
diff --git a/src/rps/gnunet-service-rps_view.h b/src/rps/gnunet-service-rps_view.h
new file mode 100644
index 0000000000..e05823013d
--- /dev/null
+++ b/src/rps/gnunet-service-rps_view.h
@@ -0,0 +1,124 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file rps/gnunet-service-rps_view.h
+ * @brief wrapper around the "local view"
+ * @author Julius Bünger
+ */
+#include "gnunet_util_lib.h"
+#include <inttypes.h>
+
+
+/**
+ * Create an empty view.
+ *
+ * @param len the maximum length for the view
+ */
+void
+View_create (unsigned int len);
+
+/**
+ * Change length of view
+ *
+ * @param len the (maximum) length for the view
+ */
+void
+View_change_len (unsigned int len);
+
+/**
+ * Get the view as an array
+ *
+ * @return the view in array representation
+ */
+const struct GNUNET_PeerIdentity *
+View_get_as_array ();
+
+/**
+ * Get the size of the view
+ *
+ * @return current number of actually contained peers
+ */
+unsigned int
+View_size ();
+
+/**
+ * Insert peer into the view
+ *
+ * @param peer the peer to insert
+ *
+ * @return GNUNET_OK if peer was actually inserted
+ * GNUNET_NO if peer was not inserted
+ */
+int
+View_put (const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Check whether view contains a peer
+ *
+ * @param peer the peer to check for
+ *
+ * @return GNUNET_OK if view contains peer
+ * GNUNET_NO otherwise
+ */
+int
+View_contains_peer (const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Remove peer from view
+ *
+ * @param peer the peer to remove
+ *
+ * @return GNUNET_OK if view contained peer and removed it successfully
+ * GNUNET_NO if view does not contain peer
+ */
+int
+View_remove_peer (const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Get a peer by index
+ *
+ * @param index the index of the peer to get
+ *
+ * @return peer to the corresponding index.
+ * NULL if this index is not known
+ */
+const struct GNUNET_PeerIdentity *
+View_get_peer_by_index (uint32_t index);
+
+/**
+ * Clear the custom peer map
+ *
+ * @param c_peer_map the custom peer map to look in
+ *
+ * @return size of the map
+ */
+void
+View_clear ();
+
+/**
+ * Destroy peermap.
+ *
+ * @param c_peer_map the map to destroy
+ */
+void
+View_destroy ();
+
+/* end of gnunet-service-rps_view.h */
diff --git a/src/rps/test_service_rps_view.c b/src/rps/test_service_rps_view.c
new file mode 100644
index 0000000000..8e018cba5b
--- /dev/null
+++ b/src/rps/test_service_rps_view.c
@@ -0,0 +1,121 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file rps/test_service_rps_view.c
+ * @brief testcase for gnunet-service-rps_view.c
+ */
+#include <gnunet/platform.h>
+#include "gnunet-service-rps_view.h"
+
+#define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); View_destroy(); return 1; }
+#define CHECK(c) { if (! (c)) ABORT(); }
+
+
+static int
+check ()
+{
+ struct GNUNET_PeerIdentity k1;
+ struct GNUNET_PeerIdentity k2;
+ const struct GNUNET_PeerIdentity *array;
+ int j;
+
+ View_create (3);
+ memset (&k1, 0, sizeof (k1));
+ memset (&k2, 1, sizeof (k2));
+ CHECK (GNUNET_NO == View_contains_peer (&k1));
+ CHECK (GNUNET_NO == View_contains_peer (&k2));
+ CHECK (GNUNET_NO == View_remove_peer (&k1));
+ CHECK (GNUNET_NO == View_remove_peer (&k2));
+ CHECK (NULL == View_get_peer_by_index (0));
+ CHECK (NULL == View_get_peer_by_index (1));
+ View_clear (); /* See if assertions trigger */
+ CHECK (0 == View_size ());
+
+ CHECK (GNUNET_OK == View_put (&k1));
+ CHECK (1 == View_size ());
+ CHECK (GNUNET_NO == View_put (&k1));
+ CHECK (1 == View_size ());
+ CHECK (GNUNET_YES == View_contains_peer (&k1));
+ CHECK (GNUNET_OK == View_remove_peer (&k1));
+ CHECK (0 == View_size ());
+ CHECK (GNUNET_NO == View_contains_peer (&k1));
+ CHECK (GNUNET_NO == View_contains_peer (&k2));
+
+ CHECK (GNUNET_OK == View_put (&k1));
+ CHECK (1 == View_size ());
+ for (j = 0; j < 16; j++)
+ {
+ CHECK (GNUNET_NO == View_put (&k1));
+ }
+ CHECK (1 == View_size ());
+ CHECK (GNUNET_OK == View_put (&k2));
+ CHECK (2 == View_size ());
+ for (j = 0; j < 16; j++)
+ {
+ CHECK (GNUNET_NO == View_put (&k2));
+ }
+ CHECK (2 == View_size ());
+
+ /* iterate */
+ for (j = 0; j < View_size (); j++)
+ {
+ CHECK (NULL != View_get_peer_by_index (j));
+ }
+ CHECK ((0 == memcmp (View_get_peer_by_index (0),
+ &k1, sizeof (k1))));
+ CHECK ((0 == memcmp (View_get_peer_by_index (1),
+ &k2, sizeof (k2))));
+ CHECK (GNUNET_OK == View_remove_peer (&k1));
+ CHECK (1 == View_size ());
+ CHECK (GNUNET_NO == View_contains_peer (&k1));
+ CHECK (GNUNET_YES == View_contains_peer (&k2));
+ CHECK (NULL != View_get_peer_by_index (0));
+
+ View_clear ();
+ CHECK (0 == View_size ());
+
+ CHECK (GNUNET_OK == View_put (&k1));
+ CHECK (1 == View_size ());
+ CHECK (GNUNET_OK == View_put (&k2));
+ CHECK (2 == View_size ());
+ array = View_get_as_array ();
+ CHECK (0 == memcmp (&array[0], &k1, sizeof (k1)));
+ CHECK (0 == memcmp (&array[1], &k2, sizeof (k2)));
+ View_clear ();
+ CHECK (0 == View_size ());
+
+ /*View_change_len () */
+
+ View_destroy ();
+
+ return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ GNUNET_log_setup ("test_service_rps_peers",
+ "WARNING",
+ NULL);
+ return check ();
+}
+
+/* end of test_service_rps_view.c */