diff options
-rw-r--r-- | src/rps/Makefile.am | 5 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps_view.c | 256 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps_view.h | 124 | ||||
-rw-r--r-- | src/rps/test_service_rps_view.c | 121 |
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 */ |