*/
/**
- * @file include/gnunet_scalarproduct.h
+ * @file scalarproduct/gnunet_scalarproduct.h
* @brief API to the scalarproduct service
* @author Christian M. Fuchs
*/
-/*
- * File: scalarproduct_testing.h
- * Author: gnunet
+/*
+ This file is part of GNUnet.
+ (C) 2013 Christian Grothoff (and other contributing authors)
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+/**
+ * @file scalarproduct/scalarproduct_testing.h
+ * @brief VectorProduct testcase common declarations
+ * @author Gaurav Kukreja
+ * @author Christian Fuchs
*
* Created on June 29, 2013, 7:39 PM
*/
-
/*
This file is part of GNUnet.
(C) 2013 Christian Grothoff (and other contributing authors)
+++ /dev/null
-INCLUDES = -I$(top_srcdir)/src/include
-
-pkgcfgdir= $(pkgdatadir)/config.d/
-
-libexecdir= $(pkglibdir)/libexec/
-
-pkgcfg_DATA = \
- vectorproduct.conf
-
-if MINGW
- WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
-endif
-
-if USE_COVERAGE
- AM_CFLAGS = -fprofile-arcs -ftest-coverage
-endif
-
-bin_PROGRAMS = \
- gnunet-vectorproduct
-
-libexec_PROGRAMS = \
- gnunet-service-vectorproduct
-
-# FIXME: add option "configure --with-evil"?
-#if HAVE_EXPERIMENTAL
-#libexec_PROGRAMS += \
-# gnunet-service-evil-consensus
-#endif
-
-lib_LTLIBRARIES = \
- libgnunetvectorproduct.la
-
-gnunet_vectorproduct_SOURCES = \
- gnunet-vectorproduct.c
-gnunet_vectorproduct_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
- -lgcrypt \
- $(GN_LIBINTL)
-gnunet_vectorproduct_DEPENDENCIES = \
- libgnunetvectorproduct.la
-
-gnunet_service_vectorproduct_SOURCES = \
- gnunet-service-vectorproduct.c
-gnunet_service_vectorproduct_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la \
- $(top_builddir)/src/set/libgnunetset.la \
- -lgcrypt \
- $(GN_LIBINTL)
-
-libgnunetvectorproduct_la_SOURCES = \
- vectorproduct_api.c
-libgnunetvectorproduct_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/statistics/libgnunetstatistics.la \
- -lgcrypt \
- $(LTLIBINTL)
-libgnunetvectorproduct_la_LDFLAGS = \
- $(GN_LIB_LDFLAGS)
-
-check_PROGRAMS = \
- test_vectorproduct_api_regression \
- test_vectorproduct_api \
- test_vectorproduct_api_4peers
-#FIXME unfinished
-#test_vectorproduct_api_regression2
-
-if ENABLE_TEST_RUN
- TESTS = $(check_PROGRAMS)
-endif
-
-test_consensus_api_SOURCES = \
- test_consensus_api.c
-test_consensus_api_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/consensus/libgnunetconsensus.la
-
-test_vectorproduct_api_SOURCES = \
- test_vectorproduct_api.c
-test_vectorproduct_api_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
- -lgcrypt
-
-#FIXME unfinished
-#test_vectorproduct_api_regression2_SOURCES = \
-# test_vectorproduct_api_regression2.c
-#test_vectorproduct_api_regression2_LDADD = \
-# $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
-# $(top_builddir)/src/util/libgnunetutil.la \
-# -lgcrypt
-
-test_vectorproduct_api_regression_SOURCES = \
- test_vectorproduct_api_regression.c
-test_vectorproduct_api_regression_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
- -lgcrypt
-
-test_vectorproduct_api_4peers_SOURCES = \
- test_vectorproduct_api_4peers.c
-test_vectorproduct_api_4peers_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
- -lgcrypt
-
-EXTRA_DIST = \
- test_vectorproduct.conf
-
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file vectorproduct/gnunet-service-vectorproduct.c
- * @brief vectorproduct service implementation
- * @author Christian M. Fuchs
- */
-#include <limits.h>
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_mesh_service.h"
-#include "gnunet_applications.h"
-#include "gnunet_protocols.h"
-#include "gnunet_vectorproduct_service.h"
-#include "gnunet_vectorproduct.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// Global Variables
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Handle to the core service (NULL until we've connected to it).
- */
-static struct GNUNET_CORE_Handle *my_core;
-
-/**
- * Handle to the core service (NULL until we've connected to it).
- */
-static struct GNUNET_MESH_Handle *my_mesh;
-
-/**
- * The identity of this host.
- */
-static struct GNUNET_PeerIdentity me;
-
-/**
- * Service's own public key represented as string
- */
-static unsigned char * my_pubkey_external;
-
-/**
- * Service's own public key represented as string
- */
-static uint16_t my_pubkey_external_length = 0;
-
-/**
- * Service's own n
- */
-static gcry_mpi_t my_n;
-
-/**
- * Service's own n^2 (kept for performance)
- */
-static gcry_mpi_t my_nsquare;
-
-/**
- * Service's own public exponent
- */
-static gcry_mpi_t my_g;
-
-/**
- * Service's own private multiplier
- */
-static gcry_mpi_t my_mu;
-
-/**
- * Service's own private exponent
- */
-static gcry_mpi_t my_lambda;
-
-/**
- * Head of our double linked list for client-requests sent to us.
- * for all of these elements we calculate a vector product with a remote peer
- * split between service->service and client->service for simplicity
- */
-static struct ServiceSession * from_client_head;
-/**
- * Tail of our double linked list for client-requests sent to us.
- * for all of these elements we calculate a vector product with a remote peer
- * split between service->service and client->service for simplicity
- */
-static struct ServiceSession * from_client_tail;
-
-/**
- * Head of our double linked list for service-requests sent to us.
- * for all of these elements we help the requesting service in calculating a vector product
- * split between service->service and client->service for simplicity
- */
-static struct ServiceSession * from_service_head;
-
-/**
- * Tail of our double linked list for service-requests sent to us.
- * for all of these elements we help the requesting service in calculating a vector product
- * split between service->service and client->service for simplicity
- */
-static struct ServiceSession * from_service_tail;
-
-/**
- * Certain events (callbacks for server & mesh operations) must not be queued after shutdown.
- */
-static int do_shutdown;
-
-///////////////////////////////////////////////////////////////////////////////
-// Helper Functions
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Generates an Paillier private/public keyset and extracts the values using libgrcypt only
- */
-static void
-generate_keyset ()
-{
- gcry_sexp_t gen_parms;
- gcry_sexp_t key;
- gcry_sexp_t tmp_sexp;
- gcry_mpi_t p;
- gcry_mpi_t q;
- gcry_mpi_t tmp1;
- gcry_mpi_t tmp2;
- gcry_mpi_t gcd;
-
- size_t erroff = 0;
-
- // we can still use the RSA keygen for generating p,q,n, but using e is pointless.
- GNUNET_assert (0 == gcry_sexp_build (&gen_parms, &erroff,
- "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",
- KEYBITS));
-
- GNUNET_assert (0 == gcry_pk_genkey (&key, gen_parms));
- gcry_sexp_release (gen_parms);
-
- // get n and d of our publickey as MPI
- tmp_sexp = gcry_sexp_find_token (key, "n", 0);
- GNUNET_assert (tmp_sexp);
- my_n = gcry_sexp_nth_mpi (tmp_sexp, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (tmp_sexp);
- tmp_sexp = gcry_sexp_find_token (key, "p", 0);
- GNUNET_assert (tmp_sexp);
- p = gcry_sexp_nth_mpi (tmp_sexp, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (tmp_sexp);
- tmp_sexp = gcry_sexp_find_token (key, "q", 0);
- GNUNET_assert (tmp_sexp);
- q = gcry_sexp_nth_mpi (tmp_sexp, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (key);
-
- tmp1 = gcry_mpi_new (0);
- tmp2 = gcry_mpi_new (0);
- gcd = gcry_mpi_new (0);
- my_g = gcry_mpi_new (0);
- my_mu = gcry_mpi_new (0);
- my_nsquare = gcry_mpi_new (0);
- my_lambda = gcry_mpi_new (0);
-
- // calculate lambda
- // lambda = \frac{(p-1)*(q-1)}{gcd(p-1,q-1)}
- gcry_mpi_sub_ui (tmp1, p, 1);
- gcry_mpi_sub_ui (tmp2, q, 1);
- gcry_mpi_gcd (gcd, tmp1, tmp2);
- gcry_mpi_set (my_lambda, tmp1);
- gcry_mpi_mul (my_lambda, my_lambda, tmp2);
- gcry_mpi_div (my_lambda, NULL, my_lambda, gcd, 0);
-
- // generate a g
- gcry_mpi_mul (my_nsquare, my_n, my_n);
- do
- {
- // find a matching g
- do
- {
- gcry_mpi_randomize (my_g, KEYBITS * 2, GCRY_WEAK_RANDOM);
- // g must be smaller than n^2
- if (0 >= gcry_mpi_cmp (my_g, my_nsquare))
- continue;
-
- // g must have gcd == 1 with n^2
- gcry_mpi_gcd (gcd, my_g, my_nsquare);
- }
- while (gcry_mpi_cmp_ui (gcd, 1));
-
- // is this a valid g?
- // if so, gcd(((g^lambda mod n^2)-1 )/n, n) = 1
- gcry_mpi_powm (tmp1, my_g, my_lambda, my_nsquare);
- gcry_mpi_sub_ui (tmp1, tmp1, 1);
- gcry_mpi_div (tmp1, NULL, tmp1, my_n, 0);
- gcry_mpi_gcd (gcd, tmp1, my_n);
- }
- while (gcry_mpi_cmp_ui (gcd, 1));
-
- // calculate our mu based on g and n.
- // mu = (((g^lambda mod n^2)-1 )/n)^-1 mod n
- gcry_mpi_invm (my_mu, tmp1, my_n);
-
- GNUNET_assert (0 == gcry_sexp_build (&key, &erroff,
- "(public-key (paillier (n %M)(g %M)))",
- my_n, my_g));
-
- // get the length of this sexpression
- my_pubkey_external_length = gcry_sexp_sprint (key,
- GCRYSEXP_FMT_CANON,
- NULL,
- UINT16_MAX);
-
- GNUNET_assert (my_pubkey_external_length > 0);
- my_pubkey_external = GNUNET_malloc (my_pubkey_external_length);
-
- // convert the sexpression to canonical format
- gcry_sexp_sprint (key,
- GCRYSEXP_FMT_CANON,
- my_pubkey_external,
- my_pubkey_external_length);
-
- gcry_sexp_release (key);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Generated key set with key length %d bits.\n"), KEYBITS);
-}
-
-
-/**
- * If target != size, move target bytes to the
- * end of the size-sized buffer and zero out the
- * first target-size bytes.
- *
- * @param buf original buffer
- * @param size number of bytes in the buffer
- * @param target target size of the buffer
- */
-static void
-adjust (unsigned char *buf, size_t size, size_t target)
-{
- if (size < target)
- {
- memmove (&buf[target - size], buf, size);
- memset (buf, 0, target - size);
- }
-}
-
-
-/**
- * encrypts an element using the paillier crypto system
- *
- * @param c ciphertext (output)
- * @param m plaintext
- * @param g the public base
- * @param r random base (optional) gets generated and if not NULL but uninitialized
- * @param n the module from which which r is chosen (Z*_n)
- * @param n_square the module for encryption, for performance reasons.
- */
-static void
-encrypt_element (gcry_mpi_t c, gcry_mpi_t m, gcry_mpi_t g, gcry_mpi_t r, gcry_mpi_t n, gcry_mpi_t n_square)
-{
-#ifndef DISABLE_CRYPTO
- gcry_mpi_t tmp;
- int release_r = GNUNET_NO;
-
- GNUNET_assert (tmp = gcry_mpi_new (0));
- if (NULL == r)
- {
- GNUNET_assert (r = gcry_mpi_new (0));
- release_r = GNUNET_YES;
-
- while (0 <= gcry_mpi_cmp (r, n) || 0 >= gcry_mpi_cmp_ui (r, 1))
- {
- gcry_mpi_randomize (r, KEYBITS, GCRY_WEAK_RANDOM);
- // r must be 1 < r < n
- }
- }
-
-
- gcry_mpi_powm (c, g, m, n_square);
- gcry_mpi_powm (tmp, r, n, n_square);
- gcry_mpi_mulm (c, tmp, c, n_square);
-
- gcry_mpi_release (tmp);
- if (GNUNET_YES == release_r)
- gcry_mpi_release (r);
-#else
- gcry_mpi_set (c, m);
-#endif
-}
-
-
-/**
- * decrypts an element using the paillier crypto system
- *
- * @param m plaintext (output)
- * @param c the ciphertext
- * @param mu the modifier to correct encryption
- * @param lambda the private exponent
- * @param n the outer module for decryption
- * @param n_square the inner module for decryption
- */
-static void
-decrypt_element (gcry_mpi_t m, gcry_mpi_t c, gcry_mpi_t mu, gcry_mpi_t lambda, gcry_mpi_t n, gcry_mpi_t n_square)
-{
-#ifndef DISABLE_CRYPTO
- gcry_mpi_powm (m, c, lambda, n_square);
- gcry_mpi_sub_ui (m, m, 1);
- gcry_mpi_div (m, NULL, m, n, 0);
- gcry_mpi_mulm (m, m, mu, n);
-#else
- gcry_mpi_set (m, c);
-#endif
-}
-
-
-/**
- * computes the square sum over a vector of a given length.
- *
- * @param vector the vector to encrypt
- * @param length the length of the vector
- * @return an MPI value containing the calculated sum, never NULL
- */
-static gcry_mpi_t
-compute_square_sum (gcry_mpi_t * vector, uint16_t length)
-{
- gcry_mpi_t elem;
- gcry_mpi_t sum;
- int32_t i;
-
- GNUNET_assert (sum = gcry_mpi_new (0));
- GNUNET_assert (elem = gcry_mpi_new (0));
-
- // calculare E(sum (ai ^ 2), publickey)
- for (i = 0; i < length; i++)
- {
- gcry_mpi_mul (elem, vector[i], vector[i]);
- gcry_mpi_add (sum, sum, elem);
- }
- gcry_mpi_release (elem);
-
- return sum;
-}
-
-
-/**
- * Primitive callback for copying over a message, as they
- * usually are too complex to be handled in the callback itself.
- * clears a session-callback, if a session was handed over and the transmit handle was stored
- *
- * @param cls the message object
- * @param size the size of the buffer we got
- * @param buf the buffer to copy the message to
- * @return 0 if we couldn't copy, else the size copied over
- */
-static size_t
-do_send_message (void *cls, size_t size, void *buf)
-{
- struct MessageObject * info = cls;
- struct GNUNET_MessageHeader * msg;
- size_t written = 0;
-
- GNUNET_assert (info);
- msg = info->msg;
- GNUNET_assert (msg);
- GNUNET_assert (buf);
-
- if (ntohs (msg->size) == size)
- {
- memcpy (buf, msg, size);
- written = size;
- }
-
- // reset the transmit handle, if necessary
- if (info->transmit_handle)
- *info->transmit_handle = NULL;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Sent a message of type %hu.\n"), ntohs (msg->type));
- GNUNET_free(msg);
- GNUNET_free(info);
- return written;
-}
-
-
-/**
- * initializes a new vector with fresh MPI values (=0) of a given length
- *
- * @param length of the vector to create
- * @return the initialized vector, never NULL
- */
-static gcry_mpi_t *
-initialize_mpi_vector (uint16_t length)
-{
- uint32_t i;
- gcry_mpi_t * output = GNUNET_malloc (sizeof (gcry_mpi_t) * length);
-
- for (i = 0; i < length; i++)
- GNUNET_assert (NULL != (output[i] = gcry_mpi_new (0)));
- return output;
-}
-
-
-/**
- * permutes an MPI vector according to the given permutation vector
- *
- * @param vector the vector to permuted
- * @param perm the permutation to use
- * @param length the length of the vectors
- * @return the permuted vector (same as input), never NULL
- */
-static gcry_mpi_t *
-permute_vector (gcry_mpi_t * vector,
- unsigned int * perm,
- uint32_t length)
-{
- gcry_mpi_t tmp[length];
- uint32_t i;
-
- GNUNET_assert (length > 0);
-
- // backup old layout
- memcpy (tmp, vector, length * sizeof (gcry_mpi_t));
-
- // permute vector according to given
- for (i = 0; i < length; i++)
- vector[i] = tmp[perm[i]];
-
- return vector;
-}
-
-
-/**
- * Populate a vector with random integer values and convert them to
- *
- * @param length the length of the vector we must generate
- * @return an array of MPI values with random values
- */
-static gcry_mpi_t *
-generate_random_vector (uint16_t length)
-{
- gcry_mpi_t * random_vector;
- int32_t value;
- uint32_t i;
-
- random_vector = initialize_mpi_vector (length);
- for (i = 0; i < length; i++)
- {
- value = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
-
- // long to gcry_mpi_t
- if (value < 0)
- gcry_mpi_sub_ui (random_vector[i],
- random_vector[i],
- -value);
- else
- random_vector[i] = gcry_mpi_set_ui (random_vector[i], value);
- }
-
- return random_vector;
-}
-
-
-/**
- * Finds a not terminated client/service session in the
- * given DLL based on session key, element count and state.
- *
- * @param tail - the tail of the DLL
- * @param my - the session to compare it to
- * @return a pointer to a matching session,
- * else NULL
- */
-static struct ServiceSession *
-find_matching_session (struct ServiceSession * tail,
- struct GNUNET_HashCode * key,
- uint16_t element_count,
- enum SessionState * state,
- const struct GNUNET_PeerIdentity * peerid)
-{
- struct ServiceSession * curr;
-
- for (curr = tail; NULL != curr; curr = curr->prev)
- {
- // if the key matches, and the element_count is same
- if ((!memcmp (&curr->key, key, sizeof (struct GNUNET_HashCode)))
- && (curr->element_count == element_count))
- {
- // if incoming state is NULL OR is same as state of the queued request
- if ((NULL == state) || (curr->state == *state))
- {
- // if peerid is NULL OR same as the peer Id in the queued request
- if ((NULL == peerid)
- || (!memcmp (&curr->peer, peerid, sizeof (struct GNUNET_PeerIdentity))))
- // matches and is not an already terminated session
- return curr;
- }
- }
- }
-
- return NULL;
-}
-
-
-static void
-destroy_tunnel (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ServiceSession * session = cls;
-
- if (session->tunnel)
- {
- GNUNET_MESH_tunnel_destroy (session->tunnel);
- session->tunnel = NULL;
- }
- session->service_transmit_handle = NULL;
- // we need to set this to NULL so there is no problem with double-cancel later on.
-}
-
-
-static void
-free_session (struct ServiceSession * session)
-{
- int i;
-
- if (FINALIZED != session->state)
- {
- if (session->a)
- {
- for (i = 0; i < session->used_element_count; i++)
- gcry_mpi_release (session->a[i]);
-
- GNUNET_free (session->a);
- }
- if (session->product)
- gcry_mpi_release (session->product);
-
- if (session->remote_pubkey)
- gcry_sexp_release (session->remote_pubkey);
-
- GNUNET_free_non_null (session->vector);
- }
-
- GNUNET_free (session);
-}
-///////////////////////////////////////////////////////////////////////////////
-// Event and Message Handlers
-///////////////////////////////////////////////////////////////////////////////
-
-
-/**
- * A client disconnected.
- *
- * Remove the associated session(s), release datastructures
- * and cancel pending outgoing transmissions to the client.
- * if the session has not yet completed, we also cancel Alice's request to Bob.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- */
-static void
-handle_client_disconnect (void *cls,
- struct GNUNET_SERVER_Client
- * client)
-{
- struct ServiceSession * elem;
- struct ServiceSession * next;
-
- // start from the tail, old stuff will be there...
- for (elem = from_client_head; NULL != elem; elem = next)
- {
- next = elem->next;
- if (elem->client != client)
- continue;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Client (%p) disconnected from us.\n"), client);
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, elem);
-
- if (!(elem->role == BOB && elem->state == FINALIZED))
- {
- //we MUST terminate any client message underway
- if (elem->service_transmit_handle && elem->tunnel)
- GNUNET_MESH_notify_transmit_ready_cancel (elem->service_transmit_handle);
- if (elem->tunnel && elem->state == WAITING_FOR_RESPONSE_FROM_SERVICE)
- destroy_tunnel (elem, NULL);
- }
- free_session (elem);
- }
-}
-
-
-/**
- * Notify the client that the session has succeeded or failed completely.
- * This message gets sent to
- * * alice's client if bob disconnected or to
- * * bob's client if the operation completed or alice disconnected
- *
- * @param client_session the associated client session
- * @return GNUNET_NO, if we could not notify the client
- * GNUNET_YES if we notified it.
- */
-static void
-prepare_client_end_notification (void * cls,
- const struct GNUNET_SCHEDULER_TaskContext * tc)
-{
- struct ServiceSession * session = cls;
- struct GNUNET_VECTORPRODUCT_client_response * msg;
- struct MessageObject * msg_obj;
-
- GNUNET_assert (NULL != session);
-
- msg = GNUNET_new (struct GNUNET_VECTORPRODUCT_client_response);
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_SERVICE_TO_CLIENT);
- memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode));
- memcpy (&msg->peer, &session->peer, sizeof ( struct GNUNET_PeerIdentity));
- msg->header.size = htons (sizeof (struct GNUNET_VECTORPRODUCT_client_response));
- // 0 size and the first char in the product is 0, which should never be zero if encoding is used.
- msg->product_length = htonl (0);
-
- msg_obj = GNUNET_malloc (sizeof (struct MessageObject));
- msg_obj->msg = (struct GNUNET_MessageHeader *) msg;
- msg_obj->transmit_handle = NULL; // do not reset the transmit handle, please
-
- //transmit this message to our client
- session->client_transmit_handle =
- GNUNET_SERVER_notify_transmit_ready (session->client,
- sizeof (struct GNUNET_VECTORPRODUCT_client_response),
- GNUNET_TIME_UNIT_FOREVER_REL,
- &do_send_message,
- msg_obj);
-
-
- // if we could not even queue our request, something is wrong
- if ( ! session->client_transmit_handle)
- {
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not send message to client (%p)! This is OK if it was disconnected beforehand already.\n"), session->client);
- // usually gets freed by do_send_message
- GNUNET_free (msg_obj);
- GNUNET_free (msg);
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Sending session-end notification to client (%p) for session %s\n"), &session->client, GNUNET_h2s (&session->key));
-
- free_session(session);
-}
-
-
-/**
- * Bob executes:
- * generates the response message to be sent to alice after computing
- * the values (1), (2), S and S'
- * (1)[]: $E_A(a_{pi(i)}) times E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
- * (2)[]: $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
- * S: $S := E_A(sum (r_i + b_i)^2)$
- * S': $S' := E_A(sum r_i^2)$
- *
- * @param kp (1)[]: $E_A(a_{pi(i)}) times E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
- * @param kq (2)[]: $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
- * @param s S: $S := E_A(sum (r_i + b_i)^2)$
- * @param stick S': $S' := E_A(sum r_i^2)$
- * @param request the associated requesting session with alice
- * @param response the associated responder session with bob's client
- * @return GNUNET_SYSERR if the function was called with NULL parameters or if there was an error
- * GNUNET_NO if we could not send our message
- * GNUNET_OK if the operation succeeded
- */
-static int
-prepare_service_response (gcry_mpi_t * kp,
- gcry_mpi_t * kq,
- gcry_mpi_t s,
- gcry_mpi_t stick,
- struct ServiceSession * request,
- struct ServiceSession * response)
-{
- struct GNUNET_VECTORPRODUCT_service_response * msg;
- uint16_t msg_length = 0;
- unsigned char * current = NULL;
- unsigned char * element_exported = NULL;
- size_t element_length = 0;
- int i;
-
- GNUNET_assert (request);
-
- msg_length = sizeof (struct GNUNET_VECTORPRODUCT_service_response)
- + 2 * request->used_element_count * PAILLIER_ELEMENT_LENGTH // kp, kq
- + 2 * PAILLIER_ELEMENT_LENGTH; // s, stick
-
- msg = GNUNET_malloc (msg_length);
- GNUNET_assert (msg);
-
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_BOB_TO_ALICE);
- msg->header.size = htons (msg_length);
- msg->element_count = htons (request->element_count);
- msg->used_element_count = htons (request->used_element_count);
- memcpy (&msg->key, &request->key, sizeof (struct GNUNET_HashCode));
- current = (unsigned char *) &msg[1];
-
- // 4 times the same logics with slight variations.
- // doesn't really justify having 2 functions for that
- // so i put it into blocks to enhance readability
- // convert s
- {
- element_exported = GNUNET_malloc (PAILLIER_ELEMENT_LENGTH);
- GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
- element_exported, PAILLIER_ELEMENT_LENGTH,
- &element_length,
- s));
- adjust (element_exported, element_length, PAILLIER_ELEMENT_LENGTH);
- memcpy (current, element_exported, PAILLIER_ELEMENT_LENGTH);
- GNUNET_free (element_exported);
- current += PAILLIER_ELEMENT_LENGTH;
- }
-
- // convert stick
- {
- element_exported = GNUNET_malloc (PAILLIER_ELEMENT_LENGTH);
- GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
- element_exported, PAILLIER_ELEMENT_LENGTH,
- &element_length,
- stick));
- adjust (element_exported, element_length, PAILLIER_ELEMENT_LENGTH);
- memcpy (current, element_exported, PAILLIER_ELEMENT_LENGTH);
- GNUNET_free (element_exported);
- current += PAILLIER_ELEMENT_LENGTH;
- }
-
- // convert kp[]
- for (i = 0; i < request->used_element_count; i++)
- {
- element_exported = GNUNET_malloc (PAILLIER_ELEMENT_LENGTH);
- GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
- element_exported, PAILLIER_ELEMENT_LENGTH,
- &element_length,
- kp[i]));
- adjust (element_exported, element_length, PAILLIER_ELEMENT_LENGTH);
- memcpy (current, element_exported, PAILLIER_ELEMENT_LENGTH);
- GNUNET_free (element_exported);
- current += PAILLIER_ELEMENT_LENGTH;
- }
-
-
- // convert kq[]
- for (i = 0; i < request->used_element_count; i++)
- {
- element_exported = GNUNET_malloc (PAILLIER_ELEMENT_LENGTH);
- GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
- element_exported, PAILLIER_ELEMENT_LENGTH,
- &element_length,
- kq[i]));
- adjust (element_exported, element_length, PAILLIER_ELEMENT_LENGTH);
- memcpy (current, element_exported, PAILLIER_ELEMENT_LENGTH);
- GNUNET_free (element_exported);
- current += PAILLIER_ELEMENT_LENGTH;
- }
-
- if (GNUNET_SERVER_MAX_MESSAGE_SIZE >= msg_length)
- {
- struct MessageObject * msg_obj;
-
- msg_obj = GNUNET_new (struct MessageObject);
- msg_obj->msg = (struct GNUNET_MessageHeader *) msg;
- msg_obj->transmit_handle = (void *) &request->service_transmit_handle; //and reset the transmit handle
- request->service_transmit_handle =
- GNUNET_MESH_notify_transmit_ready (request->tunnel,
- GNUNET_YES,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &request->peer, //must be specified, we are a slave/participant/non-owner
- msg_length,
- &do_send_message,
- msg_obj);
- // we don't care if it could be send or not. either way, the session is over for us.
- request->state = FINALIZED;
- response->state = FINALIZED;
- }
- else
- {
- // TODO FEATURE: fallback to fragmentation, in case the message is too long
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!)\n"));
- }
-
- //disconnect our client
- if ( ! request->service_transmit_handle)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response message via mesh!)\n"));
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, response);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_end_notification,
- response);
- return GNUNET_NO;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * executed by bob:
- * compute the values
- * (1)[]: $E_A(a_{pi(i)}) times E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
- * (2)[]: $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
- * S: $S := E_A(sum (r_i + b_i)^2)$
- * S': $S' := E_A(sum r_i^2)$
- *
- * @param request the requesting session + bob's requesting peer
- * @param response the responding session + bob's client handle
- * @return GNUNET_SYSERR if the computation failed
- * GNUNET_OK if everything went well.
- */
-static int
-compute_service_response (struct ServiceSession * request,
- struct ServiceSession * response)
-{
- int i, j, ret = GNUNET_SYSERR;
- unsigned int * p;
- unsigned int * q;
- uint16_t count;
- gcry_mpi_t * r = NULL;
- gcry_mpi_t * kp = NULL;
- gcry_mpi_t * kq = NULL;
- gcry_mpi_t * b;
- gcry_mpi_t * ap;
- gcry_mpi_t * aq;
- gcry_mpi_t * bp;
- gcry_mpi_t * bq;
- gcry_mpi_t * rp;
- gcry_mpi_t * rq;
- gcry_mpi_t s = NULL;
- gcry_mpi_t stick = NULL;
- gcry_mpi_t remote_n = NULL;
- gcry_mpi_t remote_nsquare;
- gcry_mpi_t remote_g = NULL;
- gcry_sexp_t tmp_exp;
- uint32_t value;
-
- GNUNET_assert (request != NULL && response != NULL);
- count = request->used_element_count;
-
- b = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- ap = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- bp = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- aq = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- bq = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- rp = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- rq = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
-
- // convert responder session to from long to mpi
- for (i = 0, j = 0; i < response->element_count && j < count; i++)
- {
- if (request->mask[i / 8] & (1 << (i % 8)))
- {
- value = response->vector[i] >= 0 ? response->vector[i] : -response->vector[i];
- // long to gcry_mpi_t
- if (0 > response->vector[i])
- {
- b[j] = gcry_mpi_new (0);
- gcry_mpi_sub_ui (b[j], b[j], value);
- }
- else
- {
- b[j] = gcry_mpi_set_ui (NULL, value);
- }
- j++;
- }
- }
- GNUNET_free (response->vector);
- response->vector = NULL;
-
- tmp_exp = gcry_sexp_find_token (request->remote_pubkey, "n", 0);
- if ( ! tmp_exp)
- {
- GNUNET_break_op (0);
- gcry_sexp_release (request->remote_pubkey);
- request->remote_pubkey = NULL;
- goto except;
- }
- remote_n = gcry_sexp_nth_mpi (tmp_exp, 1, GCRYMPI_FMT_USG);
- if ( ! remote_n)
- {
- GNUNET_break (0);
- gcry_sexp_release (tmp_exp);
- goto except;
- }
- remote_nsquare = gcry_mpi_new (KEYBITS + 1);
- gcry_mpi_mul (remote_nsquare, remote_n, remote_n);
- gcry_sexp_release (tmp_exp);
- tmp_exp = gcry_sexp_find_token (request->remote_pubkey, "g", 0);
- gcry_sexp_release (request->remote_pubkey);
- request->remote_pubkey = NULL;
- if ( ! tmp_exp)
- {
- GNUNET_break_op (0);
- gcry_mpi_release (remote_n);
- goto except;
- }
- remote_g = gcry_sexp_nth_mpi (tmp_exp, 1, GCRYMPI_FMT_USG);
- if ( ! remote_g)
- {
- GNUNET_break (0);
- gcry_mpi_release (remote_n);
- gcry_sexp_release (tmp_exp);
- goto except;
- }
- gcry_sexp_release (tmp_exp);
-
- // generate r, p and q
- r = generate_random_vector (count);
- p = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count);
- q = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count);
- //initialize the result vectors
- kp = initialize_mpi_vector (count);
- kq = initialize_mpi_vector (count);
-
- // copy the REFERNCES of a, b and r into aq and bq. we will not change
- // those values, thus we can work with the references
- memcpy (ap, request->a, sizeof (gcry_mpi_t) * count);
- memcpy (aq, request->a, sizeof (gcry_mpi_t) * count);
- memcpy (bp, b, sizeof (gcry_mpi_t) * count);
- memcpy (bq, b, sizeof (gcry_mpi_t) * count);
- memcpy (rp, r, sizeof (gcry_mpi_t) * count);
- memcpy (rq, r, sizeof (gcry_mpi_t) * count);
-
- // generate p and q permutations for a, b and r
- GNUNET_assert (permute_vector (ap, p, count));
- GNUNET_assert (permute_vector (bp, p, count));
- GNUNET_assert (permute_vector (rp, p, count));
- GNUNET_assert (permute_vector (aq, q, count));
- GNUNET_assert (permute_vector (bq, q, count));
- GNUNET_assert (permute_vector (rq, q, count));
-
- // encrypt the element
- // for the sake of readability I decided to have dedicated permutation
- // vectors, which get rid of all the lookups in p/q.
- // however, ap/aq are not absolutely necessary but are just abstraction
- // Calculate Kp = E(a_pi) + E(-r_pi - b_pi)
- for (i = 0; i < count; i++)
- {
- // E(-r_pi - b_pi)
- gcry_mpi_sub (kp[i], kp[i], rp[i]);
- gcry_mpi_sub (kp[i], kp[i], bp[i]);
- encrypt_element (kp[i], kp[i], NULL, remote_g, remote_n, remote_nsquare);
-
- // E(-r_pi - b_pi) * E(a_pi) == E(a + (-r -b))
- //gcry_mpi_mulm (kp[i], kp[i], ap[i], remote_nsquare);
- gcry_mpi_add (kp[i], kp[i], ap[i]);
- }
- GNUNET_free (ap);
- GNUNET_free (bp);
- GNUNET_free (rp);
-
- // Calculate Kq = E(a_qi) + E( -r_qi)
- for (i = 0; i < count; i++)
- {
- // E(-r_qi)
- gcry_mpi_sub (kq[i], kq[i], rq[i]);
- encrypt_element (kq[i], kq[i], NULL, remote_g, remote_n, remote_nsquare);
-
- // E(-r_qi) * E(a_qi) == E(aqi + (- rqi))
- //gcry_mpi_mulm (kq[i], kq[i], aq[i], remote_nsquare);
- gcry_mpi_add (kq[i], kq[i], aq[i]);
- }
- GNUNET_free (aq);
- GNUNET_free (bq);
- GNUNET_free (rq);
-
- // Calculate S' = E(SUM( r_i^2 ))
- stick = compute_square_sum (r, count);
- encrypt_element (stick, stick, NULL, remote_g, remote_n, remote_nsquare);
-
- // Calculate S = E(SUM( (r_i + b_i)^2 ))
- for (i = 0; i < count; i++)
- {
- gcry_mpi_add (r[i], r[i], b[i]);
- }
- s = compute_square_sum (r, count);
- encrypt_element (s, s, NULL, remote_g, remote_n, remote_nsquare);
- gcry_mpi_release (remote_n);
- gcry_mpi_release (remote_g);
- gcry_mpi_release (remote_nsquare);
-
- // release r and tmp
- for (i = 0; i < count; i++)
- // rp, rq, aq, ap, bp, bq are released along with a, r, b respectively, (a and b are handled at except:)
- gcry_mpi_release (r[i]);
-
- // copy the Kp[], Kq[], S and Stick into a new message
- if (GNUNET_YES != prepare_service_response (kp, kq, s, stick, request, response))
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Computation of values for alice failed!\n"));
- else
- ret = GNUNET_OK;
-
- for (i = 0; i < count; i++)
- {
- gcry_mpi_release (kq[i]);
- gcry_mpi_release (kp[i]);
- }
-
- gcry_mpi_release (s);
- gcry_mpi_release (stick);
-
-except:
- for (i = 0; i < count; i++)
- {
- gcry_mpi_release (b[i]);
- gcry_mpi_release (request->a[i]);
- }
-
- GNUNET_free (b);
- GNUNET_free (request->a);
- request->a = NULL;
-
- return ret;
-}
-
-
-/**
- * Executed by Alice, fills in a service-request message and sends it to the given peer
- *
- * @param session the session associated with this request, then also holds the CORE-handle
- * @return GNUNET_SYSERR if we could not send the message
- * GNUNET_NO if the message was too large
- * GNUNET_OK if we sent it
- */
-static void
-prepare_service_request (void *cls,
- const struct GNUNET_PeerIdentity * peer,
- const struct GNUNET_ATS_Information * atsi)
-{
- struct ServiceSession * session = cls;
- unsigned char * current;
- struct GNUNET_VECTORPRODUCT_service_request * msg;
- struct MessageObject * msg_obj;
- unsigned int i;
- unsigned int j;
- uint16_t msg_length;
- size_t element_length = 0; //gets initialized by gcry_mpi_print, but the compiler doesn't know that
- gcry_mpi_t a;
- gcry_mpi_t r;
- uint32_t value;
-
- GNUNET_assert (NULL != cls);
- GNUNET_assert (NULL != peer);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new tunnel to peer (%s)!\n"), GNUNET_i2s (peer));
-
- msg_length = sizeof (struct GNUNET_VECTORPRODUCT_service_request)
- + session->used_element_count * PAILLIER_ELEMENT_LENGTH
- + session->mask_length
- + my_pubkey_external_length;
-
- if (GNUNET_SERVER_MAX_MESSAGE_SIZE < sizeof (struct GNUNET_VECTORPRODUCT_service_request)
- + session->used_element_count * PAILLIER_ELEMENT_LENGTH
- + session->mask_length
- + my_pubkey_external_length)
- {
- // TODO FEATURE: fallback to fragmentation, in case the message is too long
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!\n"));
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_end_notification,
- session);
- return;
- }
- msg = GNUNET_malloc (msg_length);
-
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_ALICE_TO_BOB);
- memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode));
- msg->mask_length = htons (session->mask_length);
- msg->pk_length = htons (my_pubkey_external_length);
- msg->used_element_count = htons (session->used_element_count);
- msg->element_count = htons (session->element_count);
- msg->header.size = htons (msg_length);
-
- // fill in the payload
- current = (unsigned char *) &msg[1];
- // copy over the mask
- memcpy (current, session->mask, session->mask_length);
- // copy over our public key
- current += session->mask_length;
- memcpy (current, my_pubkey_external, my_pubkey_external_length);
- current += my_pubkey_external_length;
-
- // now copy over the element vector
- session->a = GNUNET_malloc (sizeof (gcry_mpi_t) * session->used_element_count);
- a = gcry_mpi_new (KEYBITS * 2);
- r = gcry_mpi_new (KEYBITS * 2);
- // encrypt our vector and generate string representations
- for (i = 0, j = 0; i < session->element_count; i++)
- {
- // if this is a used element...
- if (session->mask[i / 8] & 1 << (i % 8))
- {
- unsigned char * element_exported = GNUNET_malloc (PAILLIER_ELEMENT_LENGTH);
- value = session->vector[i] >= 0 ? session->vector[i] : -session->vector[i];
-
- // long to gcry_mpi_t
- if (session->vector[i] < 0)
- {
- a = gcry_mpi_set_ui (NULL, 0);
- gcry_mpi_sub_ui (a, a, value);
- }
- else
- a = gcry_mpi_set_ui (NULL, value);
-
- // multiply with a given factor to avoid disclosing 1
- session->a[j++] = gcry_mpi_set (NULL, a);
- encrypt_element (a, a, r, my_g, my_n, my_nsquare);
-
- // get representation as string
- // we always supply some value, so gcry_mpi_print fails only if it can't reserve memory
- GNUNET_assert ( ! gcry_mpi_print (GCRYMPI_FMT_USG,
- element_exported, PAILLIER_ELEMENT_LENGTH,
- &element_length,
- a));
-
- // move buffer content to the end of the buffer so it can easily be read by libgcrypt. also this now has fixed size
- adjust (element_exported, element_length, PAILLIER_ELEMENT_LENGTH);
-
- // copy over to the message
- memcpy (current, element_exported, PAILLIER_ELEMENT_LENGTH);
- current += PAILLIER_ELEMENT_LENGTH;
- }
- }
- gcry_mpi_release (a);
- gcry_mpi_release (r);
-
- msg_obj = GNUNET_malloc (sizeof (struct MessageObject));
- msg_obj->msg = (struct GNUNET_MessageHeader *) msg;
- msg_obj->transmit_handle = (void *) &session->service_transmit_handle; //and reset the transmit handle
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting service request.\n"));
-
- //transmit via mesh messaging
- session->state = WAITING_FOR_RESPONSE_FROM_SERVICE;
- session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->tunnel, GNUNET_YES,
- GNUNET_TIME_UNIT_FOREVER_REL,
- peer, //multicast to all targets, maybe useful in the future
- msg_length,
- &do_send_message,
- msg_obj);
- if ( ! session->service_transmit_handle)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not send mutlicast message to tunnel!\n"));
- GNUNET_free (msg_obj);
- GNUNET_free (msg);
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_end_notification,
- session);
- return;
- }
-}
-
-
-/**
- * Method called whenever a peer has disconnected from the tunnel.
- * Implementations of this callback must NOT call
- * GNUNET_MESH_tunnel_destroy immediately, but instead schedule those
- * to run in some other task later. However, calling
- * "GNUNET_MESH_notify_transmit_ready_cancel" is allowed.
- *
- * @param cls closure
- * @param peer peer identity the tunnel stopped working with
- */
-static void
-tunnel_peer_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity * peer)
-{
- // as we have only one peer connected in each session, just remove the session and say good bye
- struct ServiceSession * session = cls;
- struct ServiceSession * curr;
- GNUNET_assert(cls);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Peer (%s) disconnected from our tunnel!\n"), GNUNET_i2s (peer));
-
- if ((session->role == ALICE) && (FINALIZED != session->state) && ( ! do_shutdown))
- {
- for (curr = from_client_head; NULL != curr; curr = curr->next)
- if (curr == session)
- {
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
- break;
- }
- GNUNET_SCHEDULER_add_now (&destroy_tunnel,
- session);
- // if this happened before we received the answer, we must terminate the session
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_end_notification,
- session);
- }
-}
-
-
-/**
- * Handler for a client request message.
- * Can either be type A or B
- * A: request-initiation to compute a scalar product with a peer
- * B: response role, keep the values + session and wait for a matching session or process a waiting request
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_client_request (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct GNUNET_VECTORPRODUCT_client_request * msg = (struct GNUNET_VECTORPRODUCT_client_request *) message;
- struct ServiceSession * session;
- uint16_t element_count;
- uint16_t mask_length;
- uint16_t msg_type;
- int32_t * vector;
- uint32_t i;
-
- GNUNET_assert (message);
-
- //we need at least a peer and one message id to compare
- if (sizeof (struct GNUNET_VECTORPRODUCT_client_request) > ntohs (msg->header.size))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Too short message received from client!\n"));
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- msg_type = ntohs (msg->header.type);
- element_count = ntohs (msg->element_count);
- mask_length = ntohs (msg->mask_length);
-
- //sanity check: is the message as long as the message_count fields suggests?
- if (( ntohs (msg->header.size) != (sizeof (struct GNUNET_VECTORPRODUCT_client_request) + element_count * sizeof (int32_t) + mask_length))
- || (0 == element_count))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Invalid message received from client, session information incorrect!\n"));
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- // do we have a duplicate session here already?
- if (NULL != find_matching_session (from_client_tail,
- &msg->key,
- element_count,
- NULL, NULL))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Duplicate session information received, cannot create new session with key `%s'\n"), GNUNET_h2s (&msg->key));
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- session = GNUNET_malloc (sizeof (struct ServiceSession));
- session->client = client;
- session->element_count = element_count;
- session->mask_length = mask_length;
- // get our transaction key
- memcpy (&session->key, &msg->key, sizeof (struct GNUNET_HashCode));
- //allocate memory for vector and encrypted vector
- session->vector = GNUNET_malloc (sizeof (int32_t) * element_count);
- vector = (int32_t *) & msg[1];
-
- if (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_CLIENT_TO_ALICE == msg_type)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Got client-request-session with key %s, preparing tunnel to remote service.\n"), GNUNET_h2s (&session->key));
-
- session->role = ALICE;
- // fill in the mask
- session->mask = GNUNET_malloc (mask_length);
- memcpy (session->mask, &vector[element_count], mask_length);
-
- // copy over the elements
- session->used_element_count = 0;
- for (i = 0; i < element_count; i++)
- {
- session->vector[i] = ntohl (vector[i]);
- if (session->vector[i] == 0)
- session->mask[i / 8] &= ~(1 << (i % 8));
- if (session->mask[i / 8] & (1 << (i % 8)))
- session->used_element_count++;
- }
-
- if ( ! session->used_element_count)
- {
- GNUNET_break_op (0);
- GNUNET_free (session->vector);
- GNUNET_free (session->a);
- GNUNET_free (session);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- //session with ourself makes no sense!
- if ( ! memcmp (&msg->peer, &me, sizeof (struct GNUNET_PeerIdentity)))
- {
- GNUNET_break (0);
- GNUNET_free (session->vector);
- GNUNET_free (session->a);
- GNUNET_free (session);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- // get our peer ID
- memcpy (&session->peer, &msg->peer, sizeof (struct GNUNET_PeerIdentity));
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Creating new tunnel to for session with key %s.\n"), GNUNET_h2s (&session->key));
- GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session);
- session->tunnel = GNUNET_MESH_tunnel_create (my_mesh, session,
- prepare_service_request,
- tunnel_peer_disconnect_handler,
- session);
- if ( ! session->tunnel)
- {
- GNUNET_break (0);
- GNUNET_free (session->vector);
- GNUNET_free (session->a);
- GNUNET_free (session);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- GNUNET_MESH_peer_request_connect_add (session->tunnel, &session->peer);
- GNUNET_SERVER_receive_done (client, GNUNET_YES);
- session->state = WAITING_FOR_BOBS_CONNECT;
- }
- else
- {
- struct ServiceSession * requesting_session;
- enum SessionState needed_state = REQUEST_FROM_SERVICE_RECEIVED;
-
- session->role = BOB;
- session->mask = NULL;
- // copy over the elements
- session->used_element_count = element_count;
- for (i = 0; i < element_count; i++)
- session->vector[i] = ntohl (vector[i]);
- session->state = MESSAGE_FROM_RESPONDING_CLIENT_RECEIVED;
-
- GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session);
- GNUNET_SERVER_receive_done (client, GNUNET_YES);
- //check if service queue contains a matching request
- requesting_session = find_matching_session (from_service_tail,
- &session->key,
- session->element_count,
- &needed_state, NULL);
- if (NULL != requesting_session)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got client-responder-session with key %s and a matching service-request-session set, processing.\n"), GNUNET_h2s (&session->key));
- if (GNUNET_OK != compute_service_response (requesting_session, session))
- {
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_end_notification,
- session);
- }
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got client-responder-session with key %s but NO matching service-request-session set, queuing element for later use.\n"), GNUNET_h2s (&session->key));
- // no matching session exists yet, store the response
- // for later processing by handle_service_request()
- }
-}
-
-
-/**
- * Function called for inbound tunnels.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
- * @return initial tunnel context for the tunnel
- * (can be NULL -- that's not an error)
- */
-static void *
-tunnel_incoming_handler (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
- const struct GNUNET_PeerIdentity *initiator,
- const struct GNUNET_ATS_Information *atsi)
-{
-
- struct ServiceSession * c = GNUNET_new (struct ServiceSession);
-
- memcpy (&c->peer, initiator, sizeof (struct GNUNET_PeerIdentity));
- c->tunnel = tunnel;
- c->role = BOB;
- return c;
-}
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed. Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- * with the tunnel is stored (our 'struct TunnelState')
- */
-static void
-tunnel_destruction_handler (void *cls,
- const struct GNUNET_MESH_Tunnel *tunnel,
- void *tunnel_ctx)
-{
- struct ServiceSession * service_session = tunnel_ctx;
- struct ServiceSession * client_session;
- struct ServiceSession * curr;
-
- GNUNET_assert (service_session);
- if (!memcmp (&service_session->peer, &me, sizeof (struct GNUNET_PeerIdentity)))
- return;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Tunnel destroyed, terminating session with peer (%s)\n"), GNUNET_i2s (&service_session->peer));
- // remove the session, unless it has already been dequeued, but somehow still active
- // this could bug without the IF in case the queue is empty and the service session was the only one know to the service
- for (curr = from_service_head; NULL != curr; curr = curr->next)
- if (curr == service_session)
- {
- GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, curr);
- break;
- }
- // there is a client waiting for this service session, terminate it, too!
- // i assume the tupel of key and element count is unique. if it was not the rest of the code would not work either.
- client_session = find_matching_session (from_client_tail,
- &service_session->key,
- service_session->element_count,
- NULL, NULL);
- free_session (service_session);
-
- // the client has to check if it was waiting for a result
- // or if it was a responder, no point in adding more statefulness
- if (client_session && ( ! do_shutdown))
- {
- // remove the session, we just found it in the queue, so it must be there
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, client_session);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_end_notification,
- client_session);
- }
-}
-
-
-/**
- * Compute our scalar product, done by Alice
- *
- * @param session - the session associated with this computation
- * @param kp - (1) from the protocol definition:
- * $E_A(a_{pi(i)}) times E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
- * @param kq - (2) from the protocol definition:
- * $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
- * @param s - S from the protocol definition:
- * $S := E_A(sum (r_i + b_i)^2)$
- * @param stick - S' from the protocol definition:
- * $S' := E_A(sum r_i^2)$
- * @return product as MPI, never NULL
- */
-static gcry_mpi_t
-compute_scalar_product (struct ServiceSession * session,
- gcry_mpi_t * kp, gcry_mpi_t * kq, gcry_mpi_t s, gcry_mpi_t stick)
-{
- uint16_t count;
- gcry_mpi_t divider;
- gcry_mpi_t t;
- gcry_mpi_t u;
- gcry_mpi_t utick;
- gcry_mpi_t p;
- gcry_mpi_t ptick;
- gcry_mpi_t product;
- gcry_mpi_t tmp;
- unsigned int i;
-
- count = session->used_element_count;
- tmp = gcry_mpi_new (KEYBITS);
- for (i = 0; i < count; i++)
- {
- decrypt_element (kp[i], kp[i], my_mu, my_lambda, my_n, my_nsquare);
- decrypt_element (kq[i], kq[i], my_mu, my_lambda, my_n, my_nsquare);
- }
-
- // calculate t = E(sum(ai))
- t = compute_square_sum (session->a, count);
- encrypt_element (t, t, NULL, my_g, my_n, my_nsquare);
-
- // calculate U
- u = gcry_mpi_new (0);
- tmp = compute_square_sum (kp, count);
- gcry_mpi_sub (u, u, tmp);
- encrypt_element (u, u, NULL, my_g, my_n, my_nsquare);
- gcry_mpi_release (tmp);
-
- //calculate U'
- utick = gcry_mpi_new (0);
- tmp = compute_square_sum (kq, count);
- gcry_mpi_sub (utick, utick, tmp);
- encrypt_element (utick, utick, NULL, my_g, my_n, my_nsquare);
- gcry_mpi_release (tmp);
-
- GNUNET_assert (p = gcry_mpi_new (0));
- GNUNET_assert (ptick = gcry_mpi_new (0));
-
- // compute P
- gcry_mpi_add (p, s, t);
- //gcry_mpi_mulm (p, p, u, my_nsquare);
- gcry_mpi_add (p, p, u);
- decrypt_element (p, p, my_mu, my_lambda, my_n, my_nsquare);
-
- // compute P'
- gcry_mpi_add (ptick, stick, t);
- //gcry_mpi_mulm (ptick, ptick, utick, my_nsquare);
- gcry_mpi_add (ptick, ptick, utick);
- decrypt_element (ptick, ptick, my_mu, my_lambda, my_n, my_nsquare);
-
- gcry_mpi_release (t);
- gcry_mpi_release (u);
- gcry_mpi_release (utick);
-
- // compute product
- GNUNET_assert (product = gcry_mpi_new (0));
- gcry_mpi_sub (product, p, ptick);
- gcry_mpi_release (p);
- gcry_mpi_release (ptick);
- divider = gcry_mpi_set_ui (NULL, 2);
- gcry_mpi_div (product, NULL, product, divider, 0);
-
- gcry_mpi_release (divider);
- for (i = 0; i < count; i++)
- gcry_mpi_release (session->a[i]);
- GNUNET_free (session->a);
- session->a = NULL;
-
- return product;
-}
-
-
-/**
- * prepare the response we will send to alice or bobs' clients.
- * in Bobs case the product will be NULL.
- *
- * @param session the session associated with our client.
- */
-static void
-prepare_client_response (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ServiceSession * session = cls;
- struct GNUNET_VECTORPRODUCT_client_response * msg;
- unsigned char * product_exported = NULL;
- size_t product_length = 0;
- uint16_t msg_length = 0;
- struct MessageObject * msg_obj;
-
- GNUNET_assert (session);
-
- if (session->product)
- {
- // get representation as string
- GNUNET_assert ( ! gcry_mpi_aprint (GCRYMPI_FMT_USG,
- &product_exported,
- &product_length,
- session->product));
- gcry_mpi_release (session->product);
- session->product = NULL;
- }
-
- msg_length = sizeof (struct GNUNET_VECTORPRODUCT_client_response) +product_length;
- msg = GNUNET_malloc (msg_length);
- memcpy (&msg[1], product_exported, product_length);
- GNUNET_free_non_null (product_exported);
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_SERVICE_TO_CLIENT);
- msg->header.size = htons (msg_length);
- memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode));
- memcpy (&msg->peer, &session->peer, sizeof ( struct GNUNET_PeerIdentity));
- msg->product_length = htonl (product_length);
-
- msg_obj = GNUNET_malloc (sizeof (struct MessageObject));
- msg_obj->msg = (struct GNUNET_MessageHeader *) msg;
- msg_obj->transmit_handle = NULL; // don't reset the transmit handle
-
- //transmit this message to our client
- session->client_transmit_handle =
- GNUNET_SERVER_notify_transmit_ready (session->client,
- msg_length,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &do_send_message,
- msg_obj);
- if ( ! session->client_transmit_handle)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not send message to client (%p)! This probably is OK if the client disconnected before us.\n"), session->client);
- session->client = NULL;
- // callback was not called!
- GNUNET_free (msg_obj);
- GNUNET_free (msg);
- }
- else
- // gracefully sent message, just terminate session structure
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Sent result to client (%p), this session (%s) has ended!\n"), session->client, GNUNET_h2s (&session->key));
- free_session (session);
-}
-
-
-/**
- * Handle a request from another service to calculate a vectorproduct with us.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_service_request (void *cls,
- struct GNUNET_MESH_Tunnel * tunnel,
- void **tunnel_ctx,
- const struct GNUNET_PeerIdentity * sender,
- const struct GNUNET_MessageHeader * message,
- const struct GNUNET_ATS_Information * atsi)
-{
- struct ServiceSession * session;
- struct GNUNET_VECTORPRODUCT_service_request * msg = (struct GNUNET_VECTORPRODUCT_service_request *) message;
- uint16_t mask_length;
- uint16_t pk_length;
- uint16_t used_elements;
- uint16_t element_count;
- uint16_t msg_length;
- unsigned char * current;
- struct ServiceSession * responder_session;
- int32_t i = -1;
- enum SessionState needed_state;
-
- GNUNET_assert (NULL != message);
- GNUNET_assert (NULL != sender);
- GNUNET_assert (NULL != tunnel_ctx);
- session = (struct ServiceSession *) * tunnel_ctx;
- // is this tunnel already in use?
- if ( (session->next) || (from_service_head == session))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Got a service request over a tunnel that is already in use, ignoring!\n"));
- return GNUNET_SYSERR;
- }
- // Check if message was sent by me, which would be bad!
- if ( ! memcmp (sender, &me, sizeof (struct GNUNET_PeerIdentity)))
- {
- GNUNET_break (0);
- GNUNET_free (session);
- return GNUNET_SYSERR;
- }
- // this protocol can at best be 1:N, but never M:N!
- // Check if the sender is not the peer, I am connected to, which would be bad!
- if (memcmp (sender, &session->peer, sizeof (struct GNUNET_PeerIdentity)))
- {
- GNUNET_break (0);
- GNUNET_free (session);
- return GNUNET_SYSERR;
- }
-
- //we need at least a peer and one message id to compare
- if (ntohs (msg->header.size) < sizeof (struct GNUNET_VECTORPRODUCT_service_request))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Too short message received from peer!\n"));
- GNUNET_free (session);
- return GNUNET_SYSERR;
- }
- mask_length = ntohs (msg->mask_length);
- pk_length = ntohs (msg->pk_length);
- used_elements = ntohs (msg->used_element_count);
- element_count = ntohs (msg->element_count);
- msg_length = sizeof (struct GNUNET_VECTORPRODUCT_service_request)
- + mask_length + pk_length + used_elements * PAILLIER_ELEMENT_LENGTH;
-
- //sanity check: is the message as long as the message_count fields suggests?
- if ((ntohs (msg->header.size) != msg_length) || (element_count < used_elements)
- || (used_elements == 0) || (mask_length != (element_count / 8 + (element_count % 8 ? 1 : 0)))
- )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Invalid message received from peer, message count does not match message length!\n"));
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Used elements: %hu\nElement Count: %hu\nExpected Mask Length: %hu\nCalculated Masklength: %d\n"), used_elements, element_count, mask_length, (element_count / 8 + (element_count % 8 ? 1 : 0)));
- GNUNET_free (session);
- return GNUNET_SYSERR;
- }
- if (find_matching_session (from_service_tail,
- &msg->key,
- element_count,
- NULL,
- sender))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Got message with duplicate session key (`%s'), ignoring service request.\n"), (const char *) &(msg->key));
- GNUNET_free (session);
- return GNUNET_SYSERR;
- }
-
- memcpy (&session->peer, sender, sizeof (struct GNUNET_PeerIdentity));
- session->state = REQUEST_FROM_SERVICE_RECEIVED;
- session->element_count = ntohs (msg->element_count);
- session->used_element_count = used_elements;
- session->tunnel = tunnel;
-
- // session key
- memcpy (&session->key, &msg->key, sizeof (struct GNUNET_HashCode));
- current = (unsigned char *) &msg[1];
- //preserve the mask, we will need that later on
- session->mask = GNUNET_malloc (mask_length);
- memcpy (session->mask, current, mask_length);
- //the public key
- current += mask_length;
-
- //convert the publickey to sexp
- if (gcry_sexp_new (&session->remote_pubkey, current, pk_length, 1))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not translate remote public key to sexpression!\n"));
- GNUNET_free (session->mask);
- GNUNET_free (session);
- return GNUNET_SYSERR;
- }
-
- current += pk_length;
-
- //check if service queue contains a matching request
- needed_state = MESSAGE_FROM_RESPONDING_CLIENT_RECEIVED;
- responder_session = find_matching_session (from_client_tail,
- &session->key,
- session->element_count,
- &needed_state, NULL);
-
- session->a = GNUNET_malloc (sizeof (gcry_mpi_t) * used_elements);
-
- if (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_VECTORPRODUCT_service_request)
- +pk_length
- + mask_length
- + used_elements * PAILLIER_ELEMENT_LENGTH)
- {
- gcry_error_t ret = 0;
- session->a = GNUNET_malloc (sizeof (gcry_mpi_t) * used_elements);
- // Convert each vector element to MPI_value
- for (i = 0; i < used_elements; i++)
- {
- size_t read = 0;
-
- ret = gcry_mpi_scan (&session->a[i],
- GCRYMPI_FMT_USG,
- ¤t[i * PAILLIER_ELEMENT_LENGTH],
- PAILLIER_ELEMENT_LENGTH,
- &read);
- if (ret) // read < GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not translate E[a%d] to MPI!\n%s/%s\n"),
- i, gcry_strsource (ret), gcry_strerror (ret));
- goto except;
- }
- }
- GNUNET_CONTAINER_DLL_insert (from_service_head, from_service_tail, session);
- if (responder_session)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s and a matching element set, processing.\n"), GNUNET_h2s (&session->key));
- if (GNUNET_OK != compute_service_response (session, responder_session))
- {
- //something went wrong, remove it again...
- GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
- goto except;
- }
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a matching element set, queueing.\n"), GNUNET_h2s (&session->key));
- return GNUNET_OK;
- }
- else
- {
- // TODO FEATURE: fallback to fragmentation, in case the message is too long
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!\n"));
- goto except;
- }
-except:
- for (i = 0; i < used_elements; i++)
- if (session->a[i])
- gcry_mpi_release (session->a[i]);
- gcry_sexp_release (session->remote_pubkey);
- session->remote_pubkey = NULL;
- GNUNET_free_non_null (session->a);
- session->a = NULL;
- free_session (session);
- // and notify our client-session that we could not complete the session
- if (responder_session)
- {
- // we just found the responder session in this queue
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, responder_session);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_end_notification,
- responder_session);
- }
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Handle a response we got from another service we wanted to calculate a vectorproduct with.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_service_response (void *cls,
- struct GNUNET_MESH_Tunnel * tunnel,
- void **tunnel_ctx,
- const struct GNUNET_PeerIdentity * sender,
- const struct GNUNET_MessageHeader * message,
- const struct GNUNET_ATS_Information * atsi)
-{
-
- struct ServiceSession * session;
- struct GNUNET_VECTORPRODUCT_service_response * msg = (struct GNUNET_VECTORPRODUCT_service_response *) message;
- unsigned char * current;
- uint16_t count;
- gcry_mpi_t s = NULL;
- gcry_mpi_t stick = NULL;
- size_t read;
- size_t i;
- uint16_t used_element_count;
- size_t msg_size;
- gcry_mpi_t * kp = NULL;
- gcry_mpi_t * kq = NULL;
-
- GNUNET_assert (NULL != message);
- GNUNET_assert (NULL != sender);
- GNUNET_assert (NULL != tunnel_ctx);
- session = (struct ServiceSession *) * tunnel_ctx;
- GNUNET_assert (NULL != session);
- count = session->used_element_count;
- session->product = NULL;
-
- if (memcmp (&session->peer, sender, sizeof (struct GNUNET_PeerIdentity)))
- {
- GNUNET_break_op (0);
- goto invalid_msg;
- }
- //we need at least a peer and one message id to compare
- if (sizeof (struct GNUNET_VECTORPRODUCT_service_response) > ntohs (msg->header.size))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Too short message received from peer!\n"));
- goto invalid_msg;
- }
- used_element_count = ntohs (msg->used_element_count);
- msg_size = sizeof (struct GNUNET_VECTORPRODUCT_service_response)
- + 2 * used_element_count * PAILLIER_ELEMENT_LENGTH
- + 2 * PAILLIER_ELEMENT_LENGTH;
- //sanity check: is the message as long as the message_count fields suggests?
- if ((ntohs (msg->header.size) != msg_size) || (count != used_element_count))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Invalid message received from peer!\n"));
- goto invalid_msg;
- }
- if (GNUNET_SERVER_MAX_MESSAGE_SIZE < msg_size)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!\n"));
- goto invalid_msg;
- }
-
- //convert s
- current = (unsigned char *) &msg[1];
- if (gcry_mpi_scan (&s, GCRYMPI_FMT_USG, current,
- PAILLIER_ELEMENT_LENGTH, &read))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not translate s to an MPI value!\n"));
- goto invalid_msg;
- }
- current += PAILLIER_ELEMENT_LENGTH;
- //convert stick
- if (gcry_mpi_scan (&stick, GCRYMPI_FMT_USG, current,
- PAILLIER_ELEMENT_LENGTH, &read))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not translate s' to an MPI value!\n"));
- goto invalid_msg;
- }
- current += PAILLIER_ELEMENT_LENGTH;
-
- kp = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- // Convert each kp[] to its MPI_value
- for (i = 0; i < count; i++)
- {
- if (gcry_mpi_scan (&kp[i], GCRYMPI_FMT_USG, current,
- PAILLIER_ELEMENT_LENGTH, &read))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not translate Kp[%d]to an MPI value!\n"), i);
- goto invalid_msg;
- }
- current += PAILLIER_ELEMENT_LENGTH;
- }
-
-
- kq = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
- // Convert each kq[] to its MPI_value
- for (i = 0; i < count; i++)
- {
- if (gcry_mpi_scan (&kq[i], GCRYMPI_FMT_USG, current,
- PAILLIER_ELEMENT_LENGTH, &read))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not translate Kq[%d]to an MPI value!\n"), i);
- goto invalid_msg;
- }
- current += PAILLIER_ELEMENT_LENGTH;
- }
-
- session->product = compute_scalar_product (session, kp, kq, s, stick);
-
-invalid_msg:
- if (s)
- gcry_mpi_release (s);
- if (stick)
- gcry_mpi_release (stick);
- for (i = 0; kp && i < count; i++)
- if (kp[i]) gcry_mpi_release (kp[i]);
- for (i = 0; kq && i < count; i++)
- if (kq[i]) gcry_mpi_release (kq[i]);
- GNUNET_free_non_null (kp);
- GNUNET_free_non_null (kq);
-
- session->state = FINALIZED;
- // the tunnel has done its job, terminate our connection and the tunnel
- // the peer will be notified that the tunnel was destroyed via tunnel_destruction_handler
- GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
- GNUNET_SCHEDULER_add_now (&destroy_tunnel, session);
- // send message with product to client
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &prepare_client_response, session);
- return GNUNET_OK;
- // if success: terminate the session gracefully, else terminate with error
-}
-
-
-/**
- * Task run during shutdown.
- *
- * @param cls unused
- * @param tc unused
- */
-static void
-shutdown_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ServiceSession * curr;
- struct ServiceSession * next;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Shutting down, initiating cleanup.\n"));
-
- do_shutdown = GNUNET_YES;
- // terminate all owned open tunnels.
- for (curr = from_client_head; NULL != curr; curr = next)
- {
- next = curr->next;
- if (FINALIZED != curr->state)
- {
- destroy_tunnel (curr, NULL);
- curr->state = FINALIZED;
- }
- }
-
- if (my_core)
- {
- GNUNET_CORE_disconnect (my_core);
- my_core = NULL;
- }
-
- if (my_mesh)
- {
- GNUNET_MESH_disconnect (my_mesh);
- my_mesh = NULL;
- }
-}
-
-
-/**
- * To be called on core init/fail.
- *
- * @param cls closure, NULL
- * @param server handle to the server for this service
- * @param my_identity the public identity of this peer
- */
-static void
-core_init (void *cls, struct GNUNET_CORE_Handle *server,
- const struct GNUNET_PeerIdentity *my_identity)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Core initialized\n"));
- me = *my_identity;
-}
-
-
-/**
- * Initialization of the program and message handlers
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls,
- struct GNUNET_SERVER_Handle *server,
- const struct GNUNET_CONFIGURATION_Handle *c)
-{
- static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
- {&handle_client_request, NULL, GNUNET_MESSAGE_TYPE_VECTORPRODUCT_CLIENT_TO_ALICE, 0},
- {&handle_client_request, NULL, GNUNET_MESSAGE_TYPE_VECTORPRODUCT_CLIENT_TO_BOB, 0},
- {NULL, NULL, 0, 0}
- };
- static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
- { &handle_service_request, GNUNET_MESSAGE_TYPE_VECTORPRODUCT_ALICE_TO_BOB, 0},
- { &handle_service_response, GNUNET_MESSAGE_TYPE_VECTORPRODUCT_BOB_TO_ALICE, 0},
- {NULL, 0, 0}
- };
- static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
- {NULL, 0, 0}
- };
- static GNUNET_MESH_ApplicationType mesh_types[] = {
- GNUNET_APPLICATION_TYPE_VECTORPRODUCT,
- GNUNET_APPLICATION_TYPE_END
- };
-
- //generate private/public key set
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Generating rsa-key.\n"));
- generate_keyset ();
- // register server callbacks and disconnect handler
- GNUNET_SERVER_add_handlers (server, server_handlers);
- GNUNET_SERVER_disconnect_notify (server,
- &handle_client_disconnect,
- NULL);
-
- my_core = GNUNET_CORE_connect (c, NULL, &core_init, NULL, NULL, NULL,
- GNUNET_NO, NULL, GNUNET_NO, core_handlers);
- if (!my_core)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to CORE failed\n"));
- return;
- }
- my_mesh = GNUNET_MESH_connect (c, NULL,
- &tunnel_incoming_handler,
- &tunnel_destruction_handler,
- mesh_handlers, mesh_types);
- if (!my_mesh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to MESH failed\n"));
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Mesh initialized\n"));
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
- &shutdown_task,
- NULL);
-}
-
-
-/**
- * The main function for the vectorproduct service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
- return (GNUNET_OK ==
- GNUNET_SERVICE_run (argc, argv,
- "vectorproduct",
- GNUNET_SERVICE_OPTION_NONE,
- &run, NULL)) ? 0 : 1;
-}
-
-/* end of gnunet-service-ext.c */
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file vectorproduct/gnunet-vectorproduct.c
- * @brief vectorproduct client
- * @author Christian M. Fuchs
- */
-#define GCRYPT_NO_DEPRECATED
-#include <gcrypt.h>
-#include <inttypes.h>
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_vectorproduct_service.h"
-#include "gnunet_protocols.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "gnunet-vectorproduct",__VA_ARGS__)
-/**
- * Option -p: destination peer identity for checking message-ids with
- */
-static char *input_peer_id = NULL;
-
-/**
- * Option -p: destination peer identity for checking message-ids with
- */
-static char *input_key = NULL;
-
-/**
- * Option -e: vector to calculate a vectorproduct with
- */
-static char *input_elements = NULL;
-
-/**
- * Option -m: message-ids to calculate a vectorproduct with
- */
-static char *input_mask = NULL;
-
-/**
- * the count of the messages sent to the service for processing
- */
-static unsigned short element_count;
-
-/**
- * the count of the mask bytes
- */
-unsigned short mask_length = 0;
-
-/**
- * the count of the number of mask bytes
- */
-unsigned short mask_bytes;
-
-/**
- * the array of converted message IDs to send to our service
- */
-static int32_t * elements = NULL;
-
-/**
- * the array of converted message IDs to send to our service
- */
-static unsigned char * mask = NULL;
-
-/**
- * information about the peer we are comparing with
- */
-struct GNUNET_PeerIdentity peer;
-
-/**
- * information about the peer we are comparing with
- */
-struct GNUNET_HashCode key;
-
-/**
- * Pointer to the GNUNET_VECTORPRODUCT_Handle
- */
-struct GNUNET_VECTORPRODUCT_Handle *handle;
-
-/**
- * Global return value
- */
-static int ret;
-
-struct GNUNET_VECTORPRODUCT_TestCls
-{
- struct GNUNET_VECTORPRODUCT_Handle * h;
-};
-
-struct GNUNET_VECTORPRODUCT_TestCls test_cls;
-
-
-/**
- * Callback called if we are initiating a new computation session
- *
- * @param cls unused
- * @param status if our job was successfully processed
- */
-static void
-responder_callback (void *cls,
- const struct GNUNET_HashCode * key,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status)
-{
- ret = -1;
-
- switch (status)
- {
- case GNUNET_VECTORPRODUCT_Status_Success:
- ret = 0;
- LOG (GNUNET_ERROR_TYPE_INFO, "Session %s concluded.\n", GNUNET_h2s (key));
- break;
- case GNUNET_VECTORPRODUCT_Status_InvalidResponse:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: invalid response\n", GNUNET_h2s (key));
- break;
- case GNUNET_VECTORPRODUCT_Status_Timeout:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: timeout\n", GNUNET_h2s (key));
- break;
- case GNUNET_VECTORPRODUCT_Status_Failure:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: service failure\n", GNUNET_h2s (key));
- case GNUNET_VECTORPRODUCT_Status_ServiceDisconnected:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: service disconnect!!\n", GNUNET_h2s (key));
- break;
- default:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: return code %d\n", GNUNET_h2s (key), (int) status);
- }
-
- GNUNET_VECTORPRODUCT_disconnect (handle);
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Callback called if we are initiating a new computation session
- *
- * @param cls unused
- * @param key unused
- * @param peer unused
- * @param status if our job was successfully processed
- * @param size size of the msg returned
- * @param msg the response we got.
- * @param type of the message received
- */
-static void
-requester_callback (void *cls,
- const struct GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity * peer,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status,
- const struct GNUNET_VECTORPRODUCT_client_response *msg)
-{
- uint32_t product_len;
- ret = -1;
-
- switch (status)
- {
- case GNUNET_VECTORPRODUCT_Status_Success:
- product_len = ntohl (msg->product_length);
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Session %s concluded.\n", GNUNET_h2s (key));
-
- if (0 < product_len && NULL != &msg[1])
- {
- gcry_mpi_t result;
- size_t read = 0;
-
- if (0 != gcry_mpi_scan (&result, GCRYMPI_FMT_USG, &msg[1], product_len, &read))
- LOG (GNUNET_ERROR_TYPE_ERROR, "Could not convert to mpi to value!\n");
- else
- {
- unsigned char * buf;
- gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, result);
-
- printf ("Successfully computed result for session %s: %s\n", GNUNET_h2s (key), buf);
- ret = 0;
- }
- }
- else
- { //currently not used, but if we get more info due to MESH we will need this
- LOG (GNUNET_ERROR_TYPE_ERROR, "Service-side error in session %s, return code: %d\n", GNUNET_h2s (key), product_len);
- }
- break;
- case GNUNET_VECTORPRODUCT_Status_InvalidResponse:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: invalid response\n", GNUNET_h2s (key));
- break;
- case GNUNET_VECTORPRODUCT_Status_Timeout:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: timeout\n", GNUNET_h2s (key));
- break;
- case GNUNET_VECTORPRODUCT_Status_Failure:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: service failure\n", GNUNET_h2s (key));
- case GNUNET_VECTORPRODUCT_Status_ServiceDisconnected:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Disconnected from service.\n", GNUNET_h2s (key));
- break;
- default:
- LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: return code %d\n", GNUNET_h2s (key), (int) status);
- }
- GNUNET_VECTORPRODUCT_disconnect (handle);
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param cfg configuration
- */
-static void
-run (void *cls,
- char *const *args,
- const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- char * begin = input_elements;
- char * end;
- int32_t element;
- int i;
- ret = -1;
-
- if (NULL == input_elements)
- {
- FPRINTF (stderr, "%s", _ ("You must specify at least one message ID to check!\n"));
- return;
- }
-
- if (NULL == input_key)
- {
- FPRINTF (stderr, "%s", _ ("This program needs a session identifier for comparing vectors.\n"));
- return;
- }
-
- if (1 > strnlen (input_key, sizeof (struct GNUNET_HashCode)))
- {
- FPRINTF (stderr, _ ("Please give a session key for --input_key!\n"));
- return;
- }
- GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
-
- if (input_peer_id && GNUNET_OK != GNUNET_CRYPTO_hash_from_string (input_peer_id,
- (struct GNUNET_HashCode *) &peer))
- {
- FPRINTF (stderr, _ ("Tried to set initiator mode, as peer ID was given. "
- "However, `%s' is not a valid peer identifier.\n"),
- input_peer_id);
- return;
- }
-
- int exit_loop = 0;
- /* Read input_elements_peer1, and put in elements_peer1 array */
- do
- {
- unsigned int mcount = element_count;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (*end == ',')
- *end = '\0';
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- return;
- }
-
- GNUNET_array_append (elements, mcount, element);
- element_count++;
-
- begin = ++end;
- }
- while (!exit_loop);
-
- GNUNET_assert (elements != NULL);
- GNUNET_assert (element_count > 1);
- mask_length = element_count / 8 + (element_count % 8 ? 1 : 0);
- mask = GNUNET_malloc ((element_count / 8) + 2);
-
- /* Read input_mask_peer1 and read in mask_peer1 array */
- if (NULL != input_mask)
- {
- begin = input_mask;
- unsigned short mask_count = 0;
- int exit_loop = 0;
-
- do
- {
- //ignore empty rows of ,,,,,,
- while (* begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- // gnunet_ascii-armor uses base32, thus we can use , as separator!
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (*end == ',')
- *end = '\0';
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- return;
- }
-
- GNUNET_assert (mask_count <= element_count);
-
- if (element)
- mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8);
-
- mask_count++;
- begin = ++end;
- }
- while (!exit_loop);
- // +1 to see if we would have more data, which would indicate malformed/superficial input
- GNUNET_assert (mask_count == element_count);
- }
- else if (input_peer_id)
- {
- for (i = 0; i <= mask_length; i++)
- mask[i] = UCHAR_MAX; // all 1's
- }
-
- handle = GNUNET_VECTORPRODUCT_connect (cfg);
- if (handle == NULL)
- {
- FPRINTF (stderr, _ ("Could not connect to the GNUNET Vector Product Service\n"));
- return;
- }
-
- test_cls.h = handle;
-
- if (input_peer_id && !GNUNET_VECTORPRODUCT_request (handle,
- &key,
- &peer,
- element_count,
- mask_length,
- elements, mask,
- GNUNET_TIME_UNIT_MINUTES,
- &requester_callback,
- (void *) &test_cls))
- return;
- if ( !input_peer_id && !GNUNET_VECTORPRODUCT_prepare_response (handle,
- &key,
- element_count,
- elements,
- GNUNET_TIME_UNIT_MINUTES,
- &responder_callback,
- (void *) &test_cls))
- return;
-
- ret = 0;
-}
-
-
-/**
- * The main function to the vectorproduct client.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
- static const struct GNUNET_GETOPT_CommandLineOption options[] = {
- {'e', "elements", "\"val1,val2,...,valn\"",
- gettext_noop ("A comma separated list of elements to compare as vector with our remote peer."),
- 1, &GNUNET_GETOPT_set_string, &input_elements},
- {'m', "mask", "\"0,1,...,maskn\"",
- gettext_noop ("A comma separated mask to select which elements should actually be compared."),
- 1, &GNUNET_GETOPT_set_string, &input_mask},
- {'p', "peer", "PEERID",
- gettext_noop ("[Optional] peer to calculate our vectorproduct with. If this parameter is not given, the service will wait for a remote peer to compute the request."),
- 1, &GNUNET_GETOPT_set_string, &input_peer_id},
- {'k', "key", "TRANSACTION_ID",
- gettext_noop ("Transaction ID shared with peer."),
- 1, &GNUNET_GETOPT_set_string, &input_key},
- GNUNET_GETOPT_OPTION_END
- };
-
- return (GNUNET_OK ==
- GNUNET_PROGRAM_run (argc,
- argv,
- "gnunet-vectorproduct",
- gettext_noop ("Calculate the Vectorproduct with a GNUnet peer."),
- options, &run, NULL)) ? ret : 1;
-}
-
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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 2, 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file vectorproduct/gnunet_vectorproduct.h
- * @brief API to the vectorproduct service
- * @author Christian M. Fuchs
- */
-
-#ifndef GNUNET_VECTORPRODUCT_H
-#define GNUNET_VECTORPRODUCT_H
-
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-#define DISABLE_CRYPTO
-
-/**
- * Length of the key used for encryption
- */
-#define KEYBITS 2048
-
-/**
- * When performing our crypto, we may add two encrypted values with each
- * a maximal length of GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH.
- * thus we can receive a slightly longer element (+1 byte)
- */
-#define PAILLIER_ELEMENT_LENGTH (2*KEYBITS/8 +1)
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Service Structure Definitions
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Message type passed from requesting service Alice to responding service Bob
- * to initiate a request and make bob participate in our protocol
- */
-struct GNUNET_VECTORPRODUCT_service_request {
- /**
- * GNUNET message header
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * how many bytes the mask has
- */
- uint16_t mask_length GNUNET_PACKED;
-
- /**
- * the length of the publickey contained within this message
- */
- uint16_t pk_length GNUNET_PACKED;
-
- /**
- * the transaction/session key used to identify a session
- */
- struct GNUNET_HashCode key;
-
- /**
- * how many elements the vector in payload contains
- */
- uint16_t element_count GNUNET_PACKED;
-
- /**
- * how many elements are actually included after the mask was applied.
- */
- uint16_t used_element_count GNUNET_PACKED;
-
- /**
- * followed by mask | public_key | vector[used_element_count]
- */
-};
-
-/**
- * Message type passed from responding service Bob to responding service Alice
- * to complete a request and allow Alice to compute the result
- */
-struct GNUNET_VECTORPRODUCT_service_response {
- /**
- * GNUNET message header
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * how many elements the vector in payload contains
- */
- uint16_t element_count GNUNET_PACKED;
-
- /**
- * how many elements are actually included after the mask was applied.
- */
- uint16_t used_element_count GNUNET_PACKED;
-
- /**
- * the transaction/session key used to identify a session
- */
- struct GNUNET_HashCode key;
-
- /**
- * followed by s | s' | kp[] | kq[]
- */
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Service Structure Definitions
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * state a session can be in
- */
-enum SessionState
-{
- WAITING_FOR_BOBS_CONNECT,
- MESSAGE_FROM_RESPONDING_CLIENT_RECEIVED,
- WAITING_FOR_RESPONSE_FROM_SERVICE,
- REQUEST_FROM_SERVICE_RECEIVED,
- FINALIZED
-};
-
-/**
- * role a peer in a session can assume
- */
-enum PeerRole
-{
- ALICE,
- BOB
-};
-/**
- * A vectorproduct session which tracks:
- *
- * a request form the client to our final response.
- * or
- * a request from a service to us(service).
- */
-struct ServiceSession
-{
- /**
- * the role this peer has
- */
- enum PeerRole role;
-
- /**
- * session information is kept in a DLL
- */
- struct ServiceSession *next;
-
- /**
- * session information is kept in a DLL
- */
- struct ServiceSession *prev;
-
- /**
- * (hopefully) unique transaction ID
- */
- struct GNUNET_HashCode key;
-
- /**
- * state of the session
- */
- enum SessionState state;
-
- /**
- * Alice or Bob's peerID
- */
- struct GNUNET_PeerIdentity peer;
-
- /**
- * the client this request is related to
- */
- struct GNUNET_SERVER_Client * client;
-
- /**
- * how many elements we were supplied with from the client
- */
- uint16_t element_count;
-
- /**
- * how many elements actually are used after applying the mask
- */
- uint16_t used_element_count;
-
- /**
- * how many bytes the mask is long.
- * just for convenience so we don't have to re-re-re calculate it each time
- */
- uint16_t mask_length;
-
- /**
- * all the vector elements we received
- */
- int32_t * vector;
-
- /**
- * mask of which elements to check
- */
- unsigned char * mask;
-
- /**
- * Public key of the remote service, only used by bob
- */
- gcry_sexp_t remote_pubkey;
-
- /**
- * E(ai)(Bob) or ai(Alice) after applying the mask
- */
- gcry_mpi_t * a;
-
- /**
- * The computed scalar
- */
- gcry_mpi_t product;
-
- /**
- * My transmit handle for the current message to a alice/bob
- */
- struct GNUNET_MESH_TransmitHandle * service_transmit_handle;
-
- /**
- * My transmit handle for the current message to the client
- */
- struct GNUNET_SERVER_TransmitHandle * client_transmit_handle;
-
- /**
- * tunnel-handle associated with our mesh handle
- */
- struct GNUNET_MESH_Tunnel * tunnel;
-
-};
-
-/**
- * We need to do a minimum of bookkeeping to maintain track of our transmit handles.
- * each msg is associated with a session and handle. using this information we can determine which msg was sent.
- */
-struct MessageObject
-{
- /**
- * The handle used to transmit with this request
- */
- void ** transmit_handle;
-
- /**
- * The message to send
- */
- struct GNUNET_MessageHeader * msg;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GNUNET_VECTORPRODUCT_H */
-
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * Aim of test_vectorproduct_api : This test creates two peers. Peer1 is the
- * responder peer, Bob and Peer2 is the initiator peer, Alice. Both peers
- * connect to VectorProduct Service, and use the API to issue requests to
- * service. Test passes, when the expected scalar product is received from the
- * service.
- */
-
-/**
- * @file vectorproduct/testbed_vectorproduct_api.c
- * @brief VectorProduct API testing between 4 peers using testing API
- * @author Gaurav Kukreja
- * @author Christian Fuchs
- */
-
-#include <string.h>
-
-#include <inttypes.h>
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_testbed_service.h"
-#include "gnunet_common.h"
-#include "gnunet_vectorproduct_service.h"
-#include "gnunet_protocols.h"
-
-#define NUM_PEERS 2
-
-#define LOG(kind,...) GNUNET_log_from (kind, "test-vectorproduct-api",__VA_ARGS__)
-
-/**
- * Structure for holding peer's sockets and IO Handles
- */
-struct PeerData
-{
- /**
- * Handle to testbed peer
- */
- struct GNUNET_TESTBED_Peer *peer;
-
- /**
- * The service connect operation to stream
- */
- struct GNUNET_TESTBED_Operation *op;
-
- /**
- * Our Peer id
- */
- struct GNUNET_PeerIdentity our_id;
-
- /**
- * Pointer to Vector Product Handle
- */
- struct GNUNET_VECTORPRODUCT_Handle *vh;
-};
-
-/**
- * Different states in test setup
- */
-enum SetupState
-{
- /**
- * Get the identity of peer 1
- */
- PEER1_GET_IDENTITY,
-
- /**
- * Get the identity of peer 2
- */
- PEER2_GET_IDENTITY,
-
- /**
- * Connect to stream service of peer 1
- */
- PEER1_VECTORPRODUCT_CONNECT,
-
- /**
- * Connect to stream service of peer 2
- */
- PEER2_VECTORPRODUCT_CONNECT
-
-};
-
-/******************************************************************************
- *** Global Variables *****************************
- ******************************************************************************/
-
-/**
- * Maximum allowed message-ids we can check in one go (with one GNUNET_message)
- */
-static unsigned int max_mids;
-
-/**
- * Session Key used by both the test peers
- */
-char input_key[103] = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhe";
-
-/**
- * Input elements for peer1
- */
-char input_elements_peer1[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-//char input_elements_peer1[] = "11,11,11";
-
-/**
- * Input Mask for peer 1
- */
-char input_mask_peer1[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-//char input_mask_peer1[] = "1,1,1";
-
-/**
- * the array of converted message IDs to send to our service
- */
-static int32_t * elements_peer1 = NULL;
-
-/**
- * Number of elements
- */
-uint16_t element_count_peer1 = 0;
-
-/**
- * Input elements for peer2
- */
-char input_elements_peer2[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-//char input_elements_peer2[] = "11,11,11";
-
-/**
- * Input Mask for peer 2
- */
-char input_mask_peer2[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-//char input_mask_peer2[] = "1,1,1";
-
-/**
- * the array of converted message IDs to send to our service
- */
-static int32_t * elements_peer2 = NULL;
-
-/**
- * the array of converted message IDs to send to our service
- */
-static unsigned char * mask_peer2 = NULL;
-
-/**
- * Number of elements
- */
-uint16_t element_count_peer2 = 0;
-
-/**
- * Data context for peer 1
- */
-static struct PeerData peer1;
-
-/**
- * Data context for peer 2
- */
-static struct PeerData peer2;
-
-/**
- * Various states during test setup
- */
-static enum SetupState setup_state;
-
-/**
- * Testbed operation handle
- */
-static struct GNUNET_TESTBED_Operation *op;
-
-static int ok;
-
-static int responder_ok;
-
-static int requester_ok;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-/******************************************************************************
- *** Static Functions *****************************
- ******************************************************************************/
-
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Close sockets and stop testing deamons nicely
- */
-static void
-do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
- if (peer1.op != NULL)
- do_shutdown (&peer1, NULL);
-
- if (peer2.op != NULL)
- do_shutdown (&peer2, NULL);
-
- if (GNUNET_SCHEDULER_NO_TASK != abort_task)
- GNUNET_SCHEDULER_cancel (abort_task);
-
- GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */
-}
-
-/**
- * Shutdown a peer
- *
- * @param cls pointer to "struct PeerData" of the peer to be disconnected
- * @param tc Task Context
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- static int shutdown;
- shutdown++;
- struct PeerData* peer = (struct PeerData*) cls;
-
- if (peer == &peer1)
- LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting Peer1\n\n");
- else if (peer == &peer2)
- LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting Peer2\n\n");
-
- // peer->op contains handle to the TESTBED_connect_service operation
- // calling operation done, leads to call to vectorproduct_da
- if (peer->op != NULL)
- {
- GNUNET_TESTBED_operation_done (peer->op);
- peer->op = NULL;
- }
-
- if (shutdown >= 2)
- GNUNET_SCHEDULER_add_now (&do_close, NULL);
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n");
- ok = GNUNET_SYSERR;
- abort_task = 0;
- do_close (cls, tc);
-}
-
-
-/**
- * Controller event callback
- *
- * @param cls NULL
- * @param event the controller event
- */
-static void
-controller_event_cb (void *cls,
- const struct GNUNET_TESTBED_EventInformation *event)
-{
- GNUNET_assert (event->type == GNUNET_TESTBED_ET_OPERATION_FINISHED);
-
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- case PEER2_VECTORPRODUCT_CONNECT:
- GNUNET_assert (NULL == event->details.operation_finished.emsg);
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-static void
-responder_callback (void *cls,
- const struct GNUNET_HashCode * key,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status)
-{
-
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status failure\n");
- responder_ok = -1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status invalid response\n");
- responder_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received timeout occured\n");
- responder_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received service disconnected!!\n");
- responder_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- LOG (GNUNET_ERROR_TYPE_INFO, "Responder Client expected response received!\n");
- responder_ok = 1;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client status = %d!\n", (int) status);
- responder_ok = -1;
- }
- // TODO : Responder Session Complete. Shutdown Test Cleanly!!!
- //do_shutdown(&peer1, NULL);
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer1);
- return;
-}
-
-
-static void
-requester_callback (void *cls,
- const struct GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity * peer,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status,
- const struct GNUNET_VECTORPRODUCT_client_response *msg)
-{
- uint32_t product_len;
-
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status failure\n");
- requester_ok = -1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status invalid response\n");
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client timeout occured\n");
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client service disconnected!!\n");
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success != status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client Status = %d\n", (int) status);
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- LOG (GNUNET_ERROR_TYPE_INFO, "Requester Client expected response received!\n");
- product_len = ntohl(msg->product_length);
-
- if (0 < product_len)
- {
- gcry_mpi_t result;
- gcry_error_t ret = 0;
- size_t read = 0;
- ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, &msg[1], product_len, &read);
-
- if (0 != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not convert to mpi to value!\n");
- ok = -1;
- }
- else
- {
- uint16_t i = 0;
-
- // calculate expected product
- gcry_mpi_t expected_result;
- gcry_mpi_t v1;
- gcry_mpi_t v2;
- gcry_mpi_t v1_v2_prod;
-
- expected_result = gcry_mpi_new (0);
-
- for (i = 0; i < element_count_peer1; i++)
- {
- uint32_t value;
- v1_v2_prod = gcry_mpi_new (0);
-
- // long to gcry_mpi_t
- value = elements_peer1[i] >= 0 ? elements_peer1[i] : -elements_peer1[i];
- if (elements_peer1[i] < 0)
- {
- v1 = gcry_mpi_new (0);
- gcry_mpi_sub_ui (v1, v1, value);
- }
- else
- v1 = gcry_mpi_set_ui (NULL, value);
-
- // long to gcry_mpi_t
- value = elements_peer2[i] >= 0 ? elements_peer2[i] : -elements_peer2[i];
- if (elements_peer2[i] < 0)
- {
- v2 = gcry_mpi_new (0);
- gcry_mpi_sub_ui (v2, v2, value);
- }
- else
- v2 = gcry_mpi_set_ui (NULL, value);
-
- gcry_mpi_mul (v1_v2_prod, v1, v2);
- gcry_mpi_add (expected_result, expected_result, v1_v2_prod);
-
- gcry_mpi_release (v1);
- gcry_mpi_release (v2);
- gcry_mpi_release (v1_v2_prod);
-
- }
-
- // compare the result
- if (!gcry_mpi_cmp (expected_result, result))
- {
- LOG (GNUNET_ERROR_TYPE_INFO, "Scalar Product matches expected Result!!\n");
- requester_ok = 1;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Scalar Product DOES NOT match expected Result!!\n");
- requester_ok = -1;
- }
- gcry_mpi_release (result);
- gcry_mpi_release (expected_result);
- }
- }
- else
- { //currently not used, but if we get more info due to MESH we will need this
- LOG (GNUNET_ERROR_TYPE_WARNING, "Error during computation of vector product, return code: %d\n", product_len);
- requester_ok = -1;
- }
- }
-
- //do_shutdown(&peer2, NULL);
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer2);
- return;
-}
-
-/**
- * Prepare the message to be sent by peer2 to its vectorproduct service, to
- * initiate a request to peer1.
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-requester_request ()
-{
- unsigned int i;
- int exit_loop;
- uint16_t mask_length = 0;
- char * begin = input_elements_peer2;
- char * end;
- int32_t element;
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
- struct GNUNET_HashCode key;
-
- GNUNET_assert (peer2.vh != NULL);
-
- GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
-
- /* Read input_elements_peer2, and put in elements_peer2 array */
- exit_loop = 0;
- do
- {
- unsigned int mcount = element_count_peer2;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_array_append (elements_peer2, mcount, element);
- element_count_peer2++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count_peer2 < max_mids);
- GNUNET_assert (elements_peer2 != NULL);
- GNUNET_assert (element_count_peer2 >= 1);
-
- /* Read input_mask_peer2 and read in mask_peer2 array */
- mask_length = element_count_peer2 / 8 + (element_count_peer2 % 8 ? 1 : 0);
- mask_peer2 = GNUNET_malloc ((element_count_peer2 / 8) + 2);
- GNUNET_assert (NULL != mask_peer2);
- if (NULL != input_mask_peer2)
- {
- begin = input_mask_peer2;
- unsigned short mask_count = 0;
- int exit_loop = 0;
-
- do
- {
- //ignore empty rows of ,,,,,,
- while (* begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- // gnunet_ascii-armor uses base32, thus we can use , as separator!
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_assert (mask_count <= element_count_peer2);
-
- if (element)
- mask_peer2[mask_count / 8] = mask_peer2[mask_count / 8] | 1 << (mask_count % 8);
-
- mask_count++;
- begin = ++end;
- }
- while (!exit_loop);
- // +1 to see if we would have more data, which would indicate malformed/superficial input
- GNUNET_assert (mask_count == element_count_peer2);
- }
- else
- {
- for (i = 0; i <= mask_length; i++)
- mask_peer2[i] = UCHAR_MAX; // all 1's
- }
-
- qe = GNUNET_VECTORPRODUCT_request (peer2.vh,
- &key,
- &peer1.our_id,
- element_count_peer2,
- mask_length,
- elements_peer2, mask_peer2,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
- &requester_callback,
- NULL);
-
- if (qe == NULL)
- {
- LOG(GNUNET_ERROR_TYPE_ERROR, "Could not send request to vectorproduct service! Exitting!");
- ok = -1;
- return NULL;
- }
-
- return qe;
-}
-
-
-/**
- * Function prepares the message to be sent by peer1 to its vectorproduct service
- * to prepare response, and wait for a request session to be initiated by peer1
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-responder_prepare_response ()
-{
- GNUNET_assert (peer1.vh != NULL);
-
- char * begin = input_elements_peer1;
- char * end;
- int32_t element;
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
- struct GNUNET_HashCode key;
-
- GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
-
- /* Read input_elements_peer1, and put in elements_peer1 array */
- int exit_loop = 0;
- do
- {
- unsigned int mcount = element_count_peer1;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_array_append (elements_peer1, mcount, element);
- element_count_peer1++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count_peer1 < max_mids);
- GNUNET_assert (elements_peer1 != NULL);
- GNUNET_assert (element_count_peer1 >= 1);
-
- qe = GNUNET_VECTORPRODUCT_prepare_response (peer1.vh,
- &key,
- element_count_peer1,
- elements_peer1,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
- &responder_callback,
- NULL);
-
- if (qe == NULL)
- {
- LOG(GNUNET_ERROR_TYPE_ERROR, "Could not send request to vectorproduct service! Exitting!");
- ok = -1;
- return NULL;
- }
-
- return qe;
-}
-
-
-/**
- * Scheduler task to initiate requester client
- *
- * @param cls void* to struct PeerData
- * @param tc Task Context
- */
-static void
-request_task(void *cls,
- const struct GNUNET_SCHEDULER_TaskContext
- * tc)
-{
- requester_request();
- return;
-}
-
-/**
- * Scheduler task to initiate responder client
- *
- * @param cls void* to struct PeerData
- * @param tc Task Context
- */
-static void
-prepare_response_task(void *cls,
- const struct GNUNET_SCHEDULER_TaskContext
- * tc)
-{
- responder_prepare_response();
- return;
-}
-
-
-/**
- * Adapter function called to destroy a connection to
- * a service. This function is called when GNUNET_TESTBED_operation_done is
- * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect
- * operation.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void
-vectorproduct_da (void *cls, void *op_result)
-{
- struct PeerData* peer = (struct PeerData*) cls;
-
- GNUNET_VECTORPRODUCT_disconnect (peer->vh);
- return;
-}
-
-
-/**
- * Adapter function called to establish a connection to
- * a service. This function is called to by GNUNET_TESTBED_service_connect.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- * GNUNET_TESTBED_operation_done() is called on the operation returned
- * from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-vectorproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- struct PeerData *p = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2,
- GNUNET_i2s (&p->our_id));
-
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- /* Connect peer 2 to vectorproduct service */
- {
- peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer2);
- setup_state = PEER2_VECTORPRODUCT_CONNECT;
- }
-
- /* Actually connect peer 1 to vectorproduct service */
- peer1.vh = GNUNET_VECTORPRODUCT_connect (cfg);
- return peer1.vh;
-
- case PEER2_VECTORPRODUCT_CONNECT:
- /* Actually connect peer 2 to vectorproduct service */
- peer2.vh = GNUNET_VECTORPRODUCT_connect (cfg);
-
- /* Schedule tasks to initiate request from peer2 and prepare_response from peer1 */
- if(peer1.vh != NULL && peer2.vh != NULL)
- {
- GNUNET_SCHEDULER_add_now(&prepare_response_task, &peer1);
- GNUNET_SCHEDULER_add_now(&request_task, &peer2);
- }
-
- return peer2.vh;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed; will be NULL if the
- * operation is successfull
- */
-static void
-peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
- const struct GNUNET_TESTBED_PeerInformation *pinfo,
- const char *emsg)
-{
- GNUNET_assert (NULL == emsg);
- GNUNET_assert (op == op_);
- switch (setup_state)
- {
- case PEER1_GET_IDENTITY:
- {
- memcpy (&peer1.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full
- (&peer1.our_id));
-
- /* Request for peer id of peer 2*/
- op = GNUNET_TESTBED_peer_get_information (peer2.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER2_GET_IDENTITY;
- }
- break;
- case PEER2_GET_IDENTITY:
- {
- memcpy (&peer2.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full
- (&peer2.our_id));
-
- /* Connect peer 1 to vectorproduct service */
- peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer1);
- setup_state = PEER1_VECTORPRODUCT_CONNECT;
- }
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Signature of a main function for a testcase.
- *
- * @param cls closure
- * @param num_peers number of peers in 'peers'
- * @param peers handle to peers run in the testbed
- */
-static void
-test_master (void *cls, unsigned int num_peers,
- struct GNUNET_TESTBED_Peer **peers)
-{
- GNUNET_assert (NULL != peers);
- GNUNET_assert (NULL != peers[0]);
- GNUNET_assert (NULL != peers[1]);
- peer1.peer = peers[0];
- peer2.peer = peers[1];
- /* Get the peer identity and configuration of peer 1 */
- op = GNUNET_TESTBED_peer_get_information (peer1.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER1_GET_IDENTITY;
-
- /* Abort task for stopping test on timeout */
- abort_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
- NULL);
-}
-
-
-/**
- * Main function
- */
-int
-main (int argc, char **argv)
-{
- uint64_t event_mask;
-
- ok = GNUNET_NO;
- event_mask = 0;
- event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
- max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader))
- / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
-
- (void) GNUNET_TESTBED_test_run ("test_vectorproduct_api",
- "test_vectorproduct_api_data.conf",
- NUM_PEERS, event_mask, &controller_event_cb,
- NULL,
- &test_master, NULL);
-
- if (GNUNET_SYSERR == ok)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error before calling API for request or prepare_response\n");
- return 1;
- }
- else if (GNUNET_SYSERR == responder_ok)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error in responding_client\n");
- return 1;
- }
- else if (GNUNET_SYSERR == requester_ok)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error in requesting client\n");
- return 1;
- }
- else
- return 0;
-}
-
-
+++ /dev/null
-
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * AIM OF THIS TEST
- *
- * The aim for the extended test is to verify the queuing functionality in the
- * service and the API. The API queues requests received from the clients. The
- * service queues requests that are received from other services.
- *
- * To test this, we create 4 peers. peer1 and peer2 are designated responders,
- * and peer3 and peer4 are designated as requesters. Each peer calls API for the
- * vectorproduct service accordingly.
- *
- * * peer1 tells the service to prepare response for requests with keys
- * input_key_p1_p3(shared key b/w peer1 and peer3) and input_key_p1_p4.
- * Similarly peer2 tells service to prepare response for requests with keys
- * input_key_p2_p3, and input_key_p2_p4.
- * * Simultaneously, peer3 tells its service to send a request to peer1 with key
- * input_key_p1_p3, and a request to peer2 with key input_key_p2_p3. Similarly,
- * peer 4 sends requests with appropriate keys.
- *
- * Each peer sends 2 requests to its service, which tests the queuing in API.
- * Each service receives 2 requests from other service, which tests the queuing
- * functionality in the service.
- */
-
-
-/**
- * @file vectorproduct/test_vectorproduct_api_4peers.c
- * @brief Vectorproduct API testing between 4 peers using testing API
- * @author Gaurav Kukreja
- * @author Christian Fuchs
- */
-
-#include <string.h>
-
-#include <inttypes.h>
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_testbed_service.h"
-#include "gnunet_common.h"
-#include "gnunet_vectorproduct_service.h"
-#include "gnunet_protocols.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "test-vectorproduct-api-4peers",__VA_ARGS__)
-
-#define NUM_PEERS 4
-
-/**
- * Structure for holding peer's sockets and IO Handles
- */
-struct PeerData
-{
- /**
- * Handle to testbed peer
- */
- struct GNUNET_TESTBED_Peer *peer;
-
- /**
- * The service connect operation to stream
- */
- struct GNUNET_TESTBED_Operation *op;
-
- /**
- * Our Peer id
- */
- struct GNUNET_PeerIdentity our_id;
-
- /**
- * Pointer to Vector Product Handle
- */
- struct GNUNET_VECTORPRODUCT_Handle *vh;
-
- /**
- * Input elements for peer
- */
- char * input_elements;
-
- /**
- * Input Mask for peer
- */
- char * input_mask;
-
- /**
- * 2 Input keys for peer for 2 sessions of each peer
- */
- char * input_keys[2];
-
- /**
- * Number of requests(or prepare_response) sent by the peer
- */
- int request_num;
-
- /**
- * Number of callbacks received by the peer
- */
- int callback_num;
-
- /**
- * PeerData of the peers, this peer will talk to
- */
- struct PeerData * peers[2];
-
-
-};
-
-/**
- * Different states in test setup
- */
-enum SetupState
-{
- /**
- * Get the identity of peer 1
- */
- PEER1_GET_IDENTITY,
-
- /**
- * Get the identity of peer 2
- */
- PEER2_GET_IDENTITY,
-
- /**
- * Get the identity of peer 3
- */
- PEER3_GET_IDENTITY,
-
- /**
- * Get the identity of peer 4
- */
- PEER4_GET_IDENTITY,
-
- /**
- * Connect to stream service of peer 1
- */
- PEER1_VECTORPRODUCT_CONNECT,
-
- /**
- * Connect to stream service of peer 2
- */
- PEER2_VECTORPRODUCT_CONNECT,
-
- /**
- * Connect to stream service of peer 3
- */
- PEER3_VECTORPRODUCT_CONNECT,
-
- /**
- * Connect to stream service of peer 4
- */
- PEER4_VECTORPRODUCT_CONNECT
-
-};
-
-/******************************************************************************
- *** Global Variables *****************************
- ******************************************************************************/
-
-/**
- * Maximum allowed message-ids we can check in one go (with one GNUNET_message)
- */
-static unsigned int max_mids;
-
-/**
- * Session Key used by both the test peers
- */
-char input_key_p1_p3[103] = "111111111111111111111111111111111111111111111111113333333333333333333333333333333333333333333333333333";
-
-/**
- * Session Key used by both the test peers
- */
-char input_key_p1_p4[103] = "111111111111111111111111111111111111111111111111114444444444444444444444444444444444444444444444444444";
-
-/**
- * Session Key used by both the test peers
- */
-char input_key_p2_p3[103] = "222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333";
-
-/**
- * Session Key used by both the test peers
- */
-char input_key_p2_p4[103] = "222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444";
-
-/**
- * Input elements for peer1
- */
-//char input_elements_peer1[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-char input_elements_peer1[] = "11,11,11";
-
-/**
- * Input Mask for peer 1
- */
-//char input_mask_peer1[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-char input_mask_peer1[] = "1,1,1";
-
-/**
- * Input elements for peer2
- */
-//char input_elements_peer2[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-char input_elements_peer2[] = "11,11,11";
-/**
- * Input Mask for peer 2
- */
-//char input_mask_peer2[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-char input_mask_peer2[] = "1,1,1";
-
-/**
- * Input elements for peer3
- */
-//char input_elements_peer3[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-char input_elements_peer3[] = "11,11,11";
-
-/**
- * Input Mask for peer 3
- */
-//char input_mask_peer3[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-char input_mask_peer3[] = "1,1,1";
-
-/**
- * Input elements for peer4
- */
-//char input_elements_peer4[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-char input_elements_peer4[] = "11,11,11";
-/**
- * Input Mask for peer 4
- */
-//char input_mask_peer4[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-char input_mask_peer4[] = "1,1,1";
-
-
-/**
- * Data context for peer 1
- */
-static struct PeerData peer1;
-
-/**
- * Data context for peer 2
- */
-static struct PeerData peer2;
-
-/**
- * Data context for peer 3
- */
-static struct PeerData peer3;
-
-/**
- * Data context for peer 4
- */
-static struct PeerData peer4;
-
-/**
- * Various states during test setup
- */
-static enum SetupState setup_state;
-
-/**
- * Testbed operation handle
- */
-static struct GNUNET_TESTBED_Operation *op;
-
-/**
- * Return value for the test
- */
-static int ok;
-
-/**
- * Abort Task for timeout
- */
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-/******************************************************************************
- *** Static Functions *****************************
- ******************************************************************************/
-
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Close sockets and stop testing deamons nicely
- */
-static void
-do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- if (peer1.op != NULL)
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer1);
-
- if (peer2.op != NULL)
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer2);
-
- if (peer3.op != NULL)
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer3);
-
- if (peer4.op != NULL)
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer4);
-
- if (GNUNET_SCHEDULER_NO_TASK != abort_task)
- GNUNET_SCHEDULER_cancel (abort_task);
-
- GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */
-}
-
-
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- static int shutdown;
- shutdown++;
- struct PeerData* peer = (struct PeerData*) cls;
-
- if (peer == &peer1)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 1!!! \n");
- else if (peer == &peer2)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 2!!! \n");
- else if (peer == &peer3)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 3!!! \n");
- else if (peer == &peer4)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 4!!! \n");
-
- // peer->op contains handle to the TESTBED_connect_service operation
- // calling operation done, leads to call to vectorproduct_da
- GNUNET_TESTBED_operation_done (peer->op);
- peer->op = NULL;
-
- if (shutdown == 4)
- GNUNET_SCHEDULER_add_now (&do_close, NULL);
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n");
- ok = GNUNET_SYSERR;
- abort_task = 0;
- do_close (cls, tc);
-}
-
-
-/**
- * Controller event callback
- *
- * @param cls NULL
- * @param event the controller event
- */
-static void
-controller_event_cb (void *cls,
- const struct GNUNET_TESTBED_EventInformation *event)
-{
- switch (event->type)
- {
- case GNUNET_TESTBED_ET_OPERATION_FINISHED:
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- case PEER2_VECTORPRODUCT_CONNECT:
- GNUNET_assert (NULL == event->details.operation_finished.emsg);
- break;
- default:
- GNUNET_assert (0);
- }
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-static void
-responder_callback (void *cls,
- const struct GNUNET_HashCode * key,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status)
-{
- struct PeerData * peer = cls;
-
- peer->callback_num++;
-
- if (peer == &peer1)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer1 received callback!!!\n");
- }
- else if (peer == &peer2)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer2 received callback!!!\n");
- }
- else
- LOG (GNUNET_ERROR_TYPE_ERROR, "Requester callback received, but peer is neither peer1 nor peer2!!!\n");
-
-
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received status failure\n");
- ok = -1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received status invalid response\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received timeout occured\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received service disconnected!!\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Responder Client expected response received!\n");
- ok = 1;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client status = %d!\n", (int) status);
- ok = -1;
- }
-
- // TODO : Responder Session Complete. Shutdown Test Cleanly!!!
- if (peer->callback_num == 2)
- GNUNET_SCHEDULER_add_now (&do_shutdown, peer);
-}
-
-
-static void
-requester_callback (void *cls,
- const struct GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity * peer,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status,
- const struct GNUNET_VECTORPRODUCT_client_response *msg)
-{
- struct PeerData * peer_ = cls;
- uint32_t product_len;
-
- peer_->callback_num++;
-
- if (peer_ == &peer3)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer3 received callback!!!\n");
- }
- else if (peer_ == &peer4)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer4 received callback!!!\n");
- }
- else
- LOG (GNUNET_ERROR_TYPE_ERROR, "Requester callback received, but peer is neither peer3 nor peer4!!!\n");
-
-
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client received status failure\n");
- ok = -1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client received status invalid response\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client timeout occured\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client service disconnected!!\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success != status)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client Status = %d\n", (int) status);
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requester client received status successful!\n");
- product_len = ntohl (msg->product_length);
-
- if (0 < product_len)
- {
- gcry_mpi_t result;
- gcry_error_t ret = 0;
- size_t read = 0;
-
- ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, (void*) &(msg[1]), product_len, &read);
-
- if (0 != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not convert to mpi to value!\n");
- }
- else
- {
- gcry_mpi_release (result);
- }
- ok = 1;
- }
- else
- {
- //currently not used, but if we get more info due to MESH we will need this
- LOG (GNUNET_ERROR_TYPE_ERROR, "Error during computation of vector product, return code: %d\n", product_len);
- ok = -1;
- }
- }
-
- if (peer_->callback_num == 2)
- GNUNET_SCHEDULER_add_now (&do_shutdown, peer_);
-}
-
-
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-requester_request (char * input_elements,
- char * input_mask,
- char * input_key,
- struct PeerData * peer,
- struct PeerData * to_peer)
-{
-
-
- unsigned int i;
- uint16_t element_count = 0;
- int32_t * elements = NULL;
- uint16_t mask_length = 0;
- unsigned char * mask = NULL;
- int32_t element;
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
- struct GNUNET_HashCode key;
- int exit_loop;
- char * begin = input_elements;
- char * end;
-
- GNUNET_assert (peer->vh != NULL);
-
- GNUNET_CRYPTO_hash_from_string (input_key, &key);
-
- exit_loop = 0;
- /* Read input_elements, and put in elements array */
- do
- {
- unsigned int mcount = element_count;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_array_append (elements, mcount, element);
- element_count++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count < max_mids);
- GNUNET_assert (elements != NULL);
- GNUNET_assert (element_count >= 1);
-
- /* Read input_mask and read in mask array */
- mask_length = element_count / 8 + (element_count % 8 ? 1 : 0);
- mask = GNUNET_malloc ((element_count / 8) + 2);
- GNUNET_assert (NULL != mask);
- if (NULL != input_mask)
- {
- begin = input_mask;
- unsigned short mask_count = 0;
- int exit_loop = 0;
-
- do
- {
- //ignore empty rows of ,,,,,,
- while (* begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- // gnunet_ascii-armor uses base32, thus we can use , as separator!
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_assert (mask_count <= element_count);
-
- if (element)
- mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8);
-
- mask_count++;
- begin = ++end;
- }
- while (!exit_loop);
- // +1 to see if we would have more data, which would indicate malformed/superficial input
- GNUNET_assert (mask_count == element_count);
- }
- else
- {
- for (i = 0; i <= mask_length; i++)
- mask[i] = UCHAR_MAX; // all 1's
- }
-
- qe = GNUNET_VECTORPRODUCT_request (peer->vh,
- &key,
- &to_peer->our_id,
- element_count,
- mask_length,
- elements, mask,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60),
- &requester_callback,
- peer);
-
- if (qe == NULL)
- {
- LOG(GNUNET_ERROR_TYPE_WARNING, "Could not send request to vectorproduct service! Exitting!");
- ok = -1;
- return NULL;
- }
-
- return qe;
-}
-
-
-/**
- * Function prepares the message to be sent by peer1 to its vectorproduct service
- * to prepare response, and wait for a request session to be initiated by peer1
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-responder_prepare_response (char * input_elements,
- char * input_mask,
- char * input_key,
- struct PeerData * peer)
-{
- GNUNET_assert (peer->vh != NULL);
-
- unsigned int i;
- uint16_t element_count = 0;
- int32_t * elements = NULL;
- unsigned short mask_length = 0;
- unsigned char * mask = NULL;
- int32_t element;
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
- struct GNUNET_HashCode key;
- int exit_loop;
- char * begin;
- char * end;
-
- GNUNET_CRYPTO_hash_from_string (input_key, &key);
-
- /* Read input_elements, and put in elements array */
- exit_loop = 0;
- begin = input_elements;
- do
- {
- unsigned int mcount = element_count;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_array_append (elements, mcount, element);
- element_count++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count < max_mids);
- GNUNET_assert (elements != NULL);
- GNUNET_assert (element_count >= 1);
-
- /* Read input_mask and read in mask array */
- mask_length = element_count / 8 + (element_count % 8 ? 1 : 0);
- mask = GNUNET_malloc ((element_count / 8) + 2);
- GNUNET_assert (NULL != mask);
- if (NULL != input_mask)
- {
- begin = input_mask;
- unsigned short mask_count = 0;
- int exit_loop = 0;
-
- do
- {
- //ignore empty rows of ,,,,,,
- while (* begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- // gnunet_ascii-armor uses base32, thus we can use , as separator!
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_assert (mask_count <= element_count);
-
- if (element)
- mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8);
-
- mask_count++;
- begin = ++end;
- }
- while (!exit_loop);
- // +1 to see if we would have more data, which would indicate malformed/superficial input
- GNUNET_assert (mask_count == element_count);
- }
- else
- {
- for (i = 0; i <= mask_length; i++)
- mask[i] = UCHAR_MAX; // all 1's
- }
-
- qe = GNUNET_VECTORPRODUCT_prepare_response (peer->vh,
- &key,
- element_count,
- elements,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60),
- &responder_callback,
- peer);
-
- if (qe == NULL)
- {
- LOG(GNUNET_ERROR_TYPE_ERROR, "Could not send request to vectorproduct service! Exitting!");
- ok = -1;
- return NULL;
- }
-
- return qe;
-}
-
-
-static void
-request_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext
- * tc)
-{
- struct PeerData * peer = cls;
-
- requester_request (peer->input_elements, peer->input_mask, peer->input_keys[peer->request_num], peer, peer->peers[peer->request_num]);
- peer->request_num++;
- return;
-}
-
-
-static void
-prepare_response_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext
- * tc)
-{
- struct PeerData * peer = cls;
-
- responder_prepare_response (peer->input_elements, peer->input_mask, peer->input_keys[peer->request_num], peer);
- peer->request_num++;
- return;
-}
-
-
-/**
- * Adapter function called to destroy a connection to
- * a service. This function is called when GNUNET_TESTBED_operation_done is
- * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect
- * operation.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void
-vectorproduct_da (void *cls, void *op_result)
-{
- struct PeerData* peer = (struct PeerData*) cls;
-
- GNUNET_VECTORPRODUCT_disconnect (peer->vh);
- return;
-
- GNUNET_assert (0);
-}
-
-
-/**
- * Adapter function called to establish a connection to
- * a service. This function is called to by GNUNET_TESTBED_service_connect.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- * GNUNET_TESTBED_operation_done() is called on the operation returned
- * from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-vectorproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- struct PeerData *p = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2,
- GNUNET_i2s (&p->our_id));
-
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- /* Connect peer 2 to vectorproduct service */
- {
- peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer2);
- setup_state = PEER2_VECTORPRODUCT_CONNECT;
- }
-
- peer1.vh = GNUNET_VECTORPRODUCT_connect (cfg);
- return peer1.vh;
-
- case PEER2_VECTORPRODUCT_CONNECT:
- /* Connect peer 3 to vectorproduct service */
- {
- peer3.op = GNUNET_TESTBED_service_connect (&peer3, peer3.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer3);
- setup_state = PEER3_VECTORPRODUCT_CONNECT;
- }
-
- peer2.vh = GNUNET_VECTORPRODUCT_connect (cfg);
- return peer2.vh;
-
- case PEER3_VECTORPRODUCT_CONNECT:
- /* Connect peer 4 to vectorproduct service */
- {
- peer4.op = GNUNET_TESTBED_service_connect (&peer4, peer4.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer4);
- setup_state = PEER4_VECTORPRODUCT_CONNECT;
- }
-
- peer3.vh = GNUNET_VECTORPRODUCT_connect (cfg);
- return peer3.vh;
-
- case PEER4_VECTORPRODUCT_CONNECT:
- peer4.vh = GNUNET_VECTORPRODUCT_connect (cfg);
-
- /* Schedule the tasks to issue prepare_response calls from peer1 and peer2
- * for peer3 and peer4.
- */
- GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer1);
- GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer1);
- GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer2);
- GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer2);
-
- /*
- * Schedule the tasks to issue requests calls from peer3 and peer4
- * to peer1 and peer2
- */
- GNUNET_SCHEDULER_add_now (&request_task, &peer3);
- GNUNET_SCHEDULER_add_now (&request_task, &peer3);
- GNUNET_SCHEDULER_add_now (&request_task, &peer4);
- GNUNET_SCHEDULER_add_now (&request_task, &peer4);
-
- return peer2.vh;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed; will be NULL if the
- * operation is successfull
- */
-static void
-peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
- const struct GNUNET_TESTBED_PeerInformation *pinfo,
- const char *emsg)
-{
- GNUNET_assert (NULL == emsg);
- GNUNET_assert (op == op_);
- switch (setup_state)
- {
- case PEER1_GET_IDENTITY:
- {
- memcpy (&peer1.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full
- (&peer1.our_id));
-
- /* Request for peer id of peer 2*/
- op = GNUNET_TESTBED_peer_get_information (peer2.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER2_GET_IDENTITY;
- }
- break;
- case PEER2_GET_IDENTITY:
- {
- memcpy (&peer2.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full
- (&peer2.our_id));
-
- /* Request for peer id of peer 3*/
- op = GNUNET_TESTBED_peer_get_information (peer3.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER3_GET_IDENTITY;
- }
- break;
- case PEER3_GET_IDENTITY:
- {
- memcpy (&peer3.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 3 id: %s\n", GNUNET_i2s_full
- (&peer3.our_id));
-
- /* Request for peer id of peer 4*/
- op = GNUNET_TESTBED_peer_get_information (peer4.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER4_GET_IDENTITY;
- }
- break;
- case PEER4_GET_IDENTITY:
- {
- memcpy (&peer4.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full
- (&peer2.our_id));
-
- /* Connect peer 1 to vectorproduct service */
- peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer1);
- setup_state = PEER1_VECTORPRODUCT_CONNECT;
- }
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Signature of a main function for a testcase.
- *
- * @param cls closure
- * @param num_peers number of peers in 'peers'
- * @param peers handle to peers run in the testbed
- */
-static void
-test_master (void *cls, unsigned int num_peers,
- struct GNUNET_TESTBED_Peer **peers)
-{
- GNUNET_assert (NULL != peers);
- GNUNET_assert (NULL != peers[0]);
- GNUNET_assert (NULL != peers[1]);
- GNUNET_assert (NULL != peers[2]);
- GNUNET_assert (NULL != peers[3]);
- peer1.peer = peers[0];
- peer1.input_elements = input_elements_peer1;
- peer1.input_mask = input_mask_peer1;
- peer1.request_num = 0;
- peer1.callback_num = 0;
- peer1.input_keys[0] = input_key_p1_p3;
- peer1.input_keys[1] = input_key_p1_p4;
-
- peer2.peer = peers[1];
- peer2.input_elements = input_elements_peer2;
- peer2.input_mask = input_mask_peer2;
- peer2.request_num = 0;
- peer2.callback_num = 0;
- peer2.input_keys[0] = input_key_p2_p3;
- peer2.input_keys[1] = input_key_p2_p4;
-
- peer3.peer = peers[2];
- peer3.input_elements = input_elements_peer3;
- peer3.input_mask = input_mask_peer3;
- peer3.request_num = 0;
- peer3.callback_num = 0;
- peer3.input_keys[0] = input_key_p1_p3;
- peer3.input_keys[1] = input_key_p2_p3;
- peer3.peers[0] = &peer1;
- peer3.peers[1] = &peer2;
-
-
- peer4.peer = peers[3];
- peer4.input_elements = input_elements_peer4;
- peer4.input_mask = input_mask_peer4;
- peer4.request_num = 0;
- peer4.callback_num = 0;
- peer4.input_keys[0] = input_key_p1_p4;
- peer4.input_keys[1] = input_key_p2_p4;
- peer4.peers[0] = &peer1;
- peer4.peers[1] = &peer2;
-
- /* Get the peer identity and configuration of peer 1 */
- op = GNUNET_TESTBED_peer_get_information (peer1.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER1_GET_IDENTITY;
- abort_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 120), &do_abort,
- NULL);
-}
-
-
-/**
- * Main function
- */
-int
-main (int argc, char **argv)
-{
- uint64_t event_mask;
-
- ok = GNUNET_NO;
- event_mask = 0;
- event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
- max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader))
- / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
- (void) GNUNET_TESTBED_test_run ("test_vectorproduct_api_4peers",
- "test_vectorproduct_api_data.conf",
- NUM_PEERS, event_mask, &controller_event_cb,
- NULL,
- &test_master, NULL);
- if (GNUNET_SYSERR == ok)
- return 1;
- return 0;
-}
+++ /dev/null
-[arm]
-DEFAULTSERVICES = core transport vectorproduct mesh testbed
-PORT = 12366
-
-[core]
-PORT = 12092
-
-[vectorproduct]
-#AUTOSTART = YES
-BINARY = gnunet-service-vectorproduct
-UNIXPATH = /tmp/gnunet-service-vectorproduct.sock
-HOME = $SERVICEHOME
-HOSTNAME = localhost
-PORT = 2087
-
-[testbed]
-OVERLAY_TOPOLOGY = CLIQUE
-
-[lockmanager]
-AUTOSTART = NO
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 12101
-
-[statistics]
-AUTOSTART = YES
-ACCEPT_FROM = 127.0.0.1;
-PORT = 12102
-
-[fs]
-AUTOSTART = NO
-
-[resolver]
-AUTOSTART = NO
-
-[mesh]
-# AUTOSTART = YES
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 10700
-# PREFIX = valgrind --leak-check=full
-# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
-
-[dht]
-AUTOSTART = YES
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 12100
-
-[block]
-plugins = dht test
-
-[dhtcache]
-QUOTA = 1 MB
-DATABASE = sqlite
-
-[transport]
-PLUGINS = tcp
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-NEIGHBOUR_LIMIT = 50
-PORT = 12365
-
-[ats]
-WAN_QUOTA_OUT = 3932160
-WAN_QUOTA_IN = 3932160
-
-[transport-tcp]
-TIMEOUT = 300 s
-PORT = 12368
-
-[TESTING]
-WEAKRANDOM = YES
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[PATHS]
-SERVICEHOME = /tmp/test-vectorproduct/
-
-[dns]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-[vpn]
-AUTOSTART = NO
-
-[nat]
-RETURN_LOCAL_ADDRESSES = YES
-
-[consensus]
-AUTOSTART = NO
-
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file vectorproduct/test_vectorproduct_api_regression.c
- * @brief VectorProduct API regression test
- * @author Gaurav Kukreja
- * @author Christian Fuchs
- */
-
-/**
- * AIM of the regression test
- *
- * This test tries to check whether the service can handle abrupt client disconnect.
- *
- * 1. We create a responder peer, and ask the service to prepare_response. After this,
- * we disconnect responder peer from service.
- *
- * 2. Then we create a requester peer, and ask service to request another peer. We
- * should check that the service on responder peer is still active and receives
- * request from the requester. We then disconnect requester peer from service. Both
- * the requester and responder service should handle this cleanly.
- */
-
-#include <string.h>
-
-#include <inttypes.h>
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_testbed_service.h"
-#include "gnunet_common.h"
-#include "gnunet_vectorproduct_service.h"
-#include "gnunet_protocols.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "test-vectorproduct-api-regression",__VA_ARGS__)
-#define NUM_PEERS 2
-
-/**
- * Structure for holding peer's sockets and IO Handles
- */
-struct PeerData
-{
- /**
- * Handle to testbed peer
- */
- struct GNUNET_TESTBED_Peer *peer;
-
- /**
- * The service connect operation to stream
- */
- struct GNUNET_TESTBED_Operation *op;
-
- /**
- * Our Peer id
- */
- struct GNUNET_PeerIdentity our_id;
-
- /**
- * Pointer to Vector Product Handle
- */
- struct GNUNET_VECTORPRODUCT_Handle *vh;
-};
-
-/**
- * Different states in test setup
- */
-enum SetupState
-{
- /**
- * Get the identity of peer 1
- */
- PEER1_GET_IDENTITY,
-
- /**
- * Get the identity of peer 2
- */
- PEER2_GET_IDENTITY,
-
- /**
- * Connect to stream service of peer 1
- */
- PEER1_VECTORPRODUCT_CONNECT,
-
- /**
- * Connect to stream service of peer 2
- */
- PEER2_VECTORPRODUCT_CONNECT
-
-};
-
-/******************************************************************************
- *** Global Variables *****************************
- ******************************************************************************/
-
-/**
- * Maximum allowed message-ids we can check in one go (with one GNUNET_message)
- */
-static unsigned int max_mids;
-
-/**
- * Session Key used by both the test peers
- */
-char input_key[103] = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhe";
-
-/**
- * Input elements for peer1
- */
-//char input_elements_peer1[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-char input_elements_peer1[] = "11,11,11";
-
-/**
- * Input Mask for peer 1
- */
-//char input_mask_peer1[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-char input_mask_peer1[] = "1,1,1";
-
-/**
- * the array of converted message IDs to send to our service
- */
-static int32_t * elements_peer1 = NULL;
-
-/**
- * Input elements for peer2
- */
-//char input_elements_peer2[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-char input_elements_peer2[] = "11,11,11";
-/**
- * Input Mask for peer 2
- */
-//char input_mask_peer2[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-char input_mask_peer2[] = "1,1,1";
-/**
- * the array of converted message IDs to send to our service
- */
-static int32_t * elements_peer2 = NULL;
-
-/**
- * the array of converted message IDs to send to our service
- */
-static unsigned char * mask_peer2 = NULL;
-
-/**
- * Data context for peer 1
- */
-static struct PeerData peer1;
-
-/**
- * Data context for peer 2
- */
-static struct PeerData peer2;
-
-/**
- * Various states during test setup
- */
-static enum SetupState setup_state;
-
-/**
- * Testbed operation handle
- */
-static struct GNUNET_TESTBED_Operation *op;
-
-/**
- * Return value of the test.
- */
-static int ok;
-
-/**
- * Abort Task for timeout
- */
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-/******************************************************************************
- *** Static Functions *****************************
- ******************************************************************************/
-
-/**
- * Helper function to shutdown a test peer
- *
- * @param cls void* to struct PeerData of the peer to be disconnected
- * @param tc Task Context
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Helper function to connect a test peer
- *
- * @param cls void* to struct PeerData of the peer to be connected
- * @param tc Task Context
- */
-static void
-connect_peer (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext * tc);
-
-
-/**
- * Close sockets and stop testing deamons nicely
- */
-static void
-do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
- if (peer1.op != NULL)
- do_shutdown (&peer1, NULL);
-
- if (peer2.op != NULL)
- do_shutdown (&peer2, NULL);
-
- if (GNUNET_SCHEDULER_NO_TASK != abort_task)
- GNUNET_SCHEDULER_cancel (abort_task);
-
- GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */
-}
-
-
-/**
- * Helper function to shutdown a test peer
- *
- * @param cls void* to struct PeerData of the peer to be disconnected
- * @param tc Task Context
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- static int shutdown;
- shutdown++;
- struct PeerData* peer = (struct PeerData*) cls;
-
- if (peer == &peer1)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting Peer1\n\n");
- else if (peer == &peer2)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting Peer2\n\n");
-
- // peer->op contains handle to the TESTBED_connect_service operation
- // calling operation done, leads to call to vectorproduct_da
- if (peer->op != NULL)
- {
- GNUNET_TESTBED_operation_done (peer->op);
- peer->op = NULL;
- }
-
- if (shutdown >= 2)
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10), &do_close, NULL);
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n");
- ok = GNUNET_SYSERR;
- abort_task = 0;
- do_close (cls, tc);
-}
-
-
-/**
- * Controller event callback
- *
- * @param cls NULL
- * @param event the controller event
- */
-static void
-controller_event_cb (void *cls,
- const struct GNUNET_TESTBED_EventInformation *event)
-{
- switch (event->type)
- {
- case GNUNET_TESTBED_ET_OPERATION_FINISHED:
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- case PEER2_VECTORPRODUCT_CONNECT:
- GNUNET_assert (NULL == event->details.operation_finished.emsg);
- break;
- default:
- GNUNET_assert (0);
- }
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Callback function called for the responder peer i.e. peer1
- *
- * @param cls
- * @param key Session key
- * @param status Status of the message
- */
-static void
-responder_callback (void *cls,
- const struct GNUNET_HashCode * key,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status)
-{
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status failure\n");
- ok = -1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status invalid response\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received timeout occured\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received service disconnected!!\n");
- ok = 1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Responder Client expected response received!\n");
- ok = -1;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client status = %d!\n", (int) status);
- ok = -1;
- }
-
- // Not shutting down this time, only for this regression test. We have shutdown explicitly earlier.
- // Shutting down again is causing problems.
-
- // if(peer1.vh != NULL)
- // {
- // GNUNET_SCHEDULER_add_now(&do_shutdown, &peer1);
- // }
- return;
-}
-
-
-/**
- * Callback function called for the requester peer i.e. peer2
- *
- * @param cls
- * @param key Session key
- * @param status Status of the message
- */
-static void
-requester_callback (void *cls,
- const struct GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity * peer,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status,
- const struct GNUNET_VECTORPRODUCT_client_response *msg)
-{
- uint32_t product_len;
-
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status failure\n");
- ok = -1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status invalid response\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client timeout occured\n");
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client service disconnected!!\n");
- ok = 1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success != status)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Requester Client Status = %d\n", (int) status);
- ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- product_len = ntohl (msg->product_length);
-
- if (0 < product_len)
- {
- gcry_mpi_t result;
- gcry_error_t ret = 0;
- size_t read = 0;
-
- ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, (void *) &msg[1], product_len, &read);
-
- if (0 != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not convert to mpi to value!\n");
- }
- else
- {
- gcry_mpi_dump (result);
- gcry_mpi_release (result);
- }
- ok = -1;
- }
- else
- { //currently not used, but if we get more info due to MESH we will need this
- LOG (GNUNET_ERROR_TYPE_WARNING, "Error during computation of vector product, return code: %d\n", product_len);
- ok = -1;
- }
- }
-
- // Not shutting down this time, only for this regression test. We have shutdown explicitly earlier.
- // Shutting down again is causing problems.
-
- // if(peer2.vh != NULL)
- // {
- // GNUNET_SCHEDULER_add_now(&do_shutdown, &peer2);
- // }
- return;
-}
-
-
-static void
-requester_request (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext * tc)
-{
- GNUNET_assert (peer2.vh != NULL);
-
- unsigned int i;
- uint16_t element_count = 0;
- uint16_t mask_length = 0;
- char * begin = input_elements_peer2;
- char * end;
- int32_t element;
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
- struct GNUNET_HashCode key;
- int exit_loop = 0;
-
- GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
-
- /* Read input_elements_peer2, and put in elements_peer2 array */
- exit_loop = 0;
- do
- {
- unsigned int mcount = element_count;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return;
- }
-
- GNUNET_array_append (elements_peer2, mcount, element);
- element_count++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count < max_mids);
- GNUNET_assert (elements_peer2 != NULL);
- GNUNET_assert (element_count >= 1);
-
- /* Read input_mask_peer2 and read in mask_peer2 array */
- mask_length = element_count / 8 + (element_count % 8 ? 1 : 0);
- mask_peer2 = GNUNET_malloc ((element_count / 8) + 2);
- GNUNET_assert (NULL != mask_peer2);
- if (NULL != input_mask_peer2)
- {
- begin = input_mask_peer2;
- unsigned short mask_count = 0;
- exit_loop = 0;
-
- do
- {
- //ignore empty rows of ,,,,,,
- while (* begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- // gnunet_ascii-armor uses base32, thus we can use , as separator!
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return;
- }
-
- GNUNET_assert (mask_count <= element_count);
-
- if (element)
- mask_peer2[mask_count / 8] = mask_peer2[mask_count / 8] | 1 << (mask_count % 8);
-
- mask_count++;
- begin = ++end;
- }
- while (!exit_loop);
- // +1 to see if we would have more data, which would indicate malformed/superficial input
- GNUNET_assert (mask_count == element_count);
- }
- else
- {
- for (i = 0; i <= mask_length; i++)
- mask_peer2[i] = UCHAR_MAX; // all 1's
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Responder peer key %s\n", &peer1.our_id);
-
- qe = GNUNET_VECTORPRODUCT_request (peer2.vh,
- &key,
- &peer1.our_id,
- element_count,
- mask_length,
- elements_peer2, mask_peer2,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
- &requester_callback,
- NULL);
-
- if (qe == NULL)
- {
- FPRINTF (stderr, "%s", _ ("Could not send request to vectorproduct service! Exitting!"));
- ok = -1;
- return;
- }
-
- /**
- * For regression, we shutdown the initiator peer, peer2, one second after
- * issuing a request. Hopefully, peer1 notices that the tunnel has been
- * been destroyed, and will shutdown cleanly.
- */
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, &peer2);
-
- return;
-}
-
-
-/**
- * Function prepares the message to be sent by peer1 to its vectorproduct service
- * to prepare response, and wait for a request session to be initiated by peer1
- */
-static void
-responder_prepare_response (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext * tc)
-{
- GNUNET_assert (peer1.vh != NULL);
-
- uint16_t element_count = 0;
- char * begin = input_elements_peer1;
- char * end;
- int32_t element;
-
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
-
- struct GNUNET_HashCode key;
- GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
-
- int exit_loop = 0;
- /* Read input_elements_peer1, and put in elements_peer1 array */
- do
- {
- unsigned int mcount = element_count;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return;
- }
-
- GNUNET_array_append (elements_peer1, mcount, element);
- element_count++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count < max_mids);
-
- GNUNET_assert (elements_peer1 != NULL);
- GNUNET_assert (element_count >= 1);
-
- qe = GNUNET_VECTORPRODUCT_prepare_response (peer1.vh,
- &key,
- element_count,
- elements_peer1,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
- &responder_callback,
- NULL);
-
- if (qe == NULL)
- {
- FPRINTF (stderr, "%s", _ ("Could not send request to vectorproduct service! Exitting!"));
- ok = -1;
- return;
- }
-
- // connect the second peer
- setup_state = PEER2_VECTORPRODUCT_CONNECT;
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &connect_peer, &peer2);
-
- // while the service is waiting for a matching request, disconnect the test client
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, &peer1);
-
- return;
-}
-
-
-/**
- * Adapter function called to destroy a connection to
- * a service. This function is called when GNUNET_TESTBED_operation_done is
- * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect
- * operation.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void
-vectorproduct_da (void *cls, void *op_result)
-{
- struct PeerData* peer = (struct PeerData*) cls;
-
- GNUNET_VECTORPRODUCT_disconnect (peer->vh);
- peer->vh = NULL;
- return;
-}
-
-
-/**
- * Adapter function called to establish a connection to
- * a service. This function is called to by GNUNET_TESTBED_service_connect.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- * GNUNET_TESTBED_operation_done() is called on the operation returned
- * from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-vectorproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- struct PeerData *p = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2,
- GNUNET_i2s (&p->our_id));
-
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- peer1.vh = GNUNET_VECTORPRODUCT_connect (cfg);
-
- if (peer1.vh != NULL)
- {
- /* prepare_response from peer1 */
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &responder_prepare_response, NULL);
- }
- else
- {
- ok = -1;
- return NULL;
- }
-
- return peer1.vh;
-
- case PEER2_VECTORPRODUCT_CONNECT:
- /* Actually connect peer 2 to vectorproduct service */
- peer2.vh = GNUNET_VECTORPRODUCT_connect (cfg);
-
- if (peer2.vh != NULL)
- {
- /* initiate request from peer2 */
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &requester_request, NULL);
- }
- else
- {
- ok = -1;
- return NULL;
- }
-
- return peer2.vh;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Helper function to connect a test peer
- *
- * @param cls void* to struct PeerData of the peer to be connected
- * @param tc Task Context
- */
-static void
-connect_peer (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext * tc)
-{
- struct PeerData *peer = cls;
-
- peer->op = GNUNET_TESTBED_service_connect (peer, peer->peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, peer);
-
-}
-
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed; will be NULL if the
- * operation is successfull
- */
-static void
-peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
- const struct GNUNET_TESTBED_PeerInformation *pinfo,
- const char *emsg)
-{
- GNUNET_assert (NULL == emsg);
- GNUNET_assert (op == op_);
-
- switch (setup_state)
- {
- case PEER1_GET_IDENTITY:
- {
- memcpy (&peer1.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full
- (&peer1.our_id));
-
- /* Request for peer id of peer 2*/
- setup_state = PEER2_GET_IDENTITY;
- op = GNUNET_TESTBED_peer_get_information (peer2.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- }
- break;
- case PEER2_GET_IDENTITY:
- {
- memcpy (&peer2.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full
- (&peer2.our_id));
-
- /* Connect peer 1 to vectorproduct service */
- setup_state = PEER1_VECTORPRODUCT_CONNECT;
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &connect_peer, &peer1);
- }
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Signature of a main function for a testcase.
- *
- * @param cls closure
- * @param num_peers number of peers in 'peers'
- * @param peers handle to peers run in the testbed
- */
-static void
-test_master (void *cls, unsigned int num_peers,
- struct GNUNET_TESTBED_Peer **peers)
-{
- GNUNET_assert (NULL != peers);
- GNUNET_assert (NULL != peers[0]);
- GNUNET_assert (NULL != peers[1]);
- peer1.peer = peers[0];
- peer2.peer = peers[1];
-
- /* Get the peer identity and configuration of peer 1 */
- setup_state = PEER1_GET_IDENTITY;
- op = GNUNET_TESTBED_peer_get_information (peer1.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
-
- abort_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
- NULL);
-}
-
-
-/**
- * Main function
- */
-int
-main (int argc, char **argv)
-{
- uint64_t event_mask;
-
- ok = GNUNET_NO;
- event_mask = 0;
- event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
- max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader))
- / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
-
- (void) GNUNET_TESTBED_test_run ("test_vectorproduct_api_regression",
- "test_vectorproduct_api_data.conf",
- NUM_PEERS, event_mask, &controller_event_cb,
- NULL,
- &test_master, NULL);
-
- if (GNUNET_SYSERR == ok)
- return 1;
- return 0;
-}
-
-
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file vectorproduct/test_vectorproduct_api_regression2.c
- * @brief Regression test, destroys requester service before receiving response
- * responder service
- * @author Gaurav Kukreja
- * @author Christian Fuchs
- */
-
-#include <string.h>
-
-#include <inttypes.h>
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_testbed_service.h"
-#include "gnunet_common.h"
-#include "gnunet_vectorproduct_service.h"
-#include "gnunet_protocols.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "test-vectorproduct-api-regression2",__VA_ARGS__)
-#define NUM_PEERS 2
-
-/**
- * Structure for holding peer's sockets and IO Handles
- */
-struct PeerData
-{
- /**
- * Handle to testbed peer
- */
- struct GNUNET_TESTBED_Peer *peer;
-
- /**
- * The service connect operation to stream
- */
- struct GNUNET_TESTBED_Operation *op;
-
- /**
- * Our Peer id
- */
- struct GNUNET_PeerIdentity our_id;
-
- /**
- * Pointer to Vector Product Handle
- */
- struct GNUNET_VECTORPRODUCT_Handle *vh;
-};
-
-/**
- * Different states in test setup
- */
-enum SetupState
-{
- /**
- * Get the identity of peer 1
- */
- PEER1_GET_IDENTITY,
-
- /**
- * Get the identity of peer 2
- */
- PEER2_GET_IDENTITY,
-
- /**
- * Connect to stream service of peer 1
- */
- PEER1_VECTORPRODUCT_CONNECT,
-
- /**
- * Connect to stream service of peer 2
- */
- PEER2_VECTORPRODUCT_CONNECT
-
-};
-
-/******************************************************************************
- *** Global Variables *****************************
- ******************************************************************************/
-
-/**
- * Maximum allowed message-ids we can check in one go (with one GNUNET_message)
- */
-static unsigned int max_mids;
-
-/**
- * Session Key used by both the test peers
- */
-char input_key[103] = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhe";
-
-/**
- * Input elements for peer1
- */
-char input_elements_peer1[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-//char input_elements_peer1[] = "11,11,11";
-
-/**
- * Input Mask for peer 1
- */
-char input_mask_peer1[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-//char input_mask_peer1[] = "1,1,1";
-
-/**
- * the array of converted message IDs to send to our service
- */
-static int32_t * elements_peer1 = NULL;
-
-/**
- * the array of converted message IDs to send to our service
- */
-static unsigned char * mask_peer1 = NULL;
-
-/**
- * Number of elements
- */
-uint16_t element_count_peer1 = 0;
-
-/**
- * Input elements for peer2
- */
-char input_elements_peer2[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
-//char input_elements_peer2[] = "11,11,11";
-
-/**
- * Input Mask for peer 2
- */
-char input_mask_peer2[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
-//char input_mask_peer2[] = "1,1,1";
-
-/**
- * the array of converted message IDs to send to our service
- */
-static int32_t * elements_peer2 = NULL;
-
-/**
- * the array of converted message IDs to send to our service
- */
-static unsigned char * mask_peer2 = NULL;
-
-/**
- * Number of elements
- */
-uint16_t element_count_peer2 = 0;
-
-/**
- * Data context for peer 1
- */
-static struct PeerData peer1;
-
-/**
- * Data context for peer 2
- */
-static struct PeerData peer2;
-
-/**
- * Various states during test setup
- */
-static enum SetupState setup_state;
-
-/**
- * Testbed operation handle
- */
-static struct GNUNET_TESTBED_Operation *op;
-
-static int ok;
-
-static int responder_ok;
-
-static int requester_ok;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-/******************************************************************************
- *** Static Functions *****************************
- ******************************************************************************/
-
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Close sockets and stop testing deamons nicely
- */
-static void
-do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- static int closed;
-
- if (peer1.op != NULL)
- {
- do_shutdown (&peer1, NULL);
- }
-
- if (peer2.op != NULL)
- {
- do_shutdown (&peer2, NULL);
- }
-
- if (GNUNET_SCHEDULER_NO_TASK != abort_task)
- {
- GNUNET_SCHEDULER_cancel (abort_task);
- abort_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */
- }
-
- if (!closed)
- {
- closed++;
- GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */
- }
-}
-
-/**
- * Shutdown a peer
- *
- * @param cls closure is a pointer to the struct PeerData of the peer to be disconnected
- * @param tc Task Context
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- static int shutdown;
- shutdown++;
- struct PeerData* peer = (struct PeerData*) cls;
-
- // peer->op contains handle to the TESTBED_connect_service operation
- // calling operation done, leads to call to vectorproduct_da
- if (peer->op != NULL)
- {
- if (peer == &peer1)
- LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting Peer1\n\n");
- else if (peer == &peer2)
- LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting Peer2\n\n");
-
- GNUNET_TESTBED_operation_done (peer->op);
- peer->op = NULL;
- }
-
- if (peer1.op == NULL && peer2.op == NULL)
- GNUNET_SCHEDULER_add_now (&do_close, NULL);
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n");
- ok = GNUNET_SYSERR;
- abort_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer1);
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer2);
-}
-
-
-/**
- * Controller event callback
- *
- * @param cls NULL
- * @param event the controller event
- */
-static void
-controller_event_cb (void *cls,
- const struct GNUNET_TESTBED_EventInformation *event)
-{
- switch (event->type)
- {
- case GNUNET_TESTBED_ET_OPERATION_FINISHED:
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- case PEER2_VECTORPRODUCT_CONNECT:
- GNUNET_assert (NULL == event->details.operation_finished.emsg);
- break;
- default:
- GNUNET_assert (0);
- }
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-static void
-responder_callback (void *cls,
- const struct GNUNET_HashCode * key,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status)
-{
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status failure\n");
- responder_ok = -1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status invalid response\n");
- responder_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received timeout occured\n");
- // In this regression test, requester is supposed to fail due to timeout
- // therefore responder_ok is set to 1, to make regression test pass
- responder_ok = 1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received service disconnected!!\n");
- responder_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Responder Client expected response received!\n");
- responder_ok = 1;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client status = %d!\n", (int) status);
- responder_ok = -1;
- }
- // TODO : Responder Session Complete. Shutdown Test Cleanly!!!
- //do_shutdown(&peer1, NULL);
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer1);
- return;
-}
-
-
-static void
-requester_callback (void *cls,
- const struct GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity * peer,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status,
- uint16_t size, struct GNUNET_VECTORPRODUCT_client_response *msg,
- uint16_t type)
-{
- uint32_t product_len;
-
- if (status == GNUNET_VECTORPRODUCT_Status_Failure)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status failure\n");
- // In this regression test, requester is supposed to receive status failure
- // therefore requester_ok is set to 1, to make regression test pass
- requester_ok = 1;
- }
- else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status invalid response\n");
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Timeout == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client timeout occured\n");
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client service disconnected!!\n");
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success != status)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client Status = %d\n", (int) status);
- requester_ok = -1;
- }
- else if (GNUNET_VECTORPRODUCT_Status_Success == status)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Requester Client expected response received!\n");
-
- product_len = ntohl (msg->product_length);
-
- if (0 < product_len)
- {
- gcry_mpi_t result;
- gcry_error_t ret = 0;
- size_t read = 0;
-
- ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, (void *) &msg[1], product_len, &read);
-
- if (0 != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not convert to mpi to value!\n");
- ok = -1;
- }
- else
- {
- uint16_t i = 0;
-
- // calculate expected product
- gcry_mpi_t expected_result;
- gcry_mpi_t v1;
- gcry_mpi_t v2;
- gcry_mpi_t v1_v2_prod;
-
- expected_result = gcry_mpi_new (0);
-
- for (i = 0; i < element_count_peer1; i++)
- {
- uint32_t value;
- v1_v2_prod = gcry_mpi_new (0);
-
- // long to gcry_mpi_t
- value = elements_peer1[i] >= 0 ? elements_peer1[i] : -elements_peer1[i];
- if (elements_peer1[i] < 0)
- {
- v1 = gcry_mpi_new (0);
- gcry_mpi_sub_ui (v1, v1, value);
- }
- else
- v1 = gcry_mpi_set_ui (NULL, value);
-
- // long to gcry_mpi_t
- value = elements_peer2[i] >= 0 ? elements_peer2[i] : -elements_peer2[i];
- if (elements_peer2[i] < 0)
- {
- v2 = gcry_mpi_new (0);
- gcry_mpi_sub_ui (v2, v2, value);
- }
- else
- v2 = gcry_mpi_set_ui (NULL, value);
-
- gcry_mpi_mul (v1_v2_prod, v1, v2);
- gcry_mpi_add (expected_result, expected_result, v1_v2_prod);
-
- gcry_mpi_release (v1);
- gcry_mpi_release (v2);
- gcry_mpi_release (v1_v2_prod);
-
- }
-
- // compare the result
- if (!gcry_mpi_cmp (expected_result, result))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Scalar Product matches expected Result!!\n");
- requester_ok = 1;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Scalar Product DOES NOT match expected Result!!\n");
- requester_ok = -1;
- }
- gcry_mpi_release (result);
- gcry_mpi_release (expected_result);
- }
- }
- else
- { //currently not used, but if we get more info due to MESH we will need this
- LOG (GNUNET_ERROR_TYPE_WARNING, "Error during computation of vector product, return code: %d\n", product_len);
- requester_ok = -1;
- }
- }
-
- //do_shutdown(&peer2, NULL);
- GNUNET_SCHEDULER_add_now (&do_shutdown, &peer2);
- return;
-}
-
-
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-requester_request ()
-{
- GNUNET_assert (peer2.vh != NULL);
-
- unsigned int i;
- //uint16_t element_count_peer2 = 0;
- uint16_t mask_length = 0;
- char * begin = input_elements_peer2;
- char * end;
- int32_t element;
-
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
-
- struct GNUNET_HashCode key;
- GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
-
- int exit_loop = 0;
- /* Read input_elements_peer2, and put in elements_peer2 array */
- do
- {
- unsigned int mcount = element_count_peer2;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_array_append (elements_peer2, mcount, element);
- element_count_peer2++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count_peer2 < max_mids);
-
- GNUNET_assert (elements_peer2 != NULL);
- GNUNET_assert (element_count_peer2 >= 1);
- mask_length = element_count_peer2 / 8 + (element_count_peer2 % 8 ? 1 : 0);
- mask_peer2 = GNUNET_malloc ((element_count_peer2 / 8) + 2);
- GNUNET_assert (NULL != mask_peer2);
-
- /* Read input_mask_peer2 and read in mask_peer2 array */
- if (NULL != input_mask_peer2)
- {
- begin = input_mask_peer2;
- unsigned short mask_count = 0;
- int exit_loop = 0;
-
- do
- {
- //ignore empty rows of ,,,,,,
- while (* begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- // gnunet_ascii-armor uses base32, thus we can use , as separator!
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_assert (mask_count <= element_count_peer2);
-
- if (element)
- mask_peer2[mask_count / 8] = mask_peer2[mask_count / 8] | 1 << (mask_count % 8);
-
- mask_count++;
- begin = ++end;
- }
- while (!exit_loop);
- // +1 to see if we would have more data, which would indicate malformed/superficial input
- GNUNET_assert (mask_count == element_count_peer2);
- }
- else
- {
- for (i = 0; i <= mask_length; i++)
- mask_peer2[i] = UCHAR_MAX; // all 1's
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Responder peer key %s\n", &peer1.our_id);
-
- // TODO : Create the mask array
- qe = GNUNET_VECTORPRODUCT_request (peer2.vh,
- &key,
- &peer1.our_id,
- element_count_peer2,
- mask_length,
- elements_peer2, mask_peer2,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
- &requester_callback,
- NULL);
-
- if (qe == NULL)
- {
- FPRINTF (stderr, "%s", _ ("Could not send request to vectorproduct service! Exitting!"));
- ok = -1;
- return NULL;
- }
-
- return qe;
-}
-
-
-/**
- * Function prepares the message to be sent by peer1 to its vectorproduct service
- * to prepare response, and wait for a request session to be initiated by peer1
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-responder_prepare_response ()
-{
- GNUNET_assert (peer1.vh != NULL);
-
- unsigned int i;
- //uint16_t element_count_peer1 = 0;
- char * begin = input_elements_peer1;
- char * end;
- int32_t element;
-
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
-
- struct GNUNET_HashCode key;
- GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
-
- int exit_loop = 0;
- /* Read input_elements_peer1, and put in elements_peer1 array */
- do
- {
- unsigned int mcount = element_count_peer1;
- //ignore empty rows of ,,,,,,
- while (*begin == ',')
- begin++;
- // get the length of the current element and replace , with null
- for (end = begin; *end && *end != ','; end++);
-
- if (*end == '\0')
- exit_loop = 1;
-
- if (*end == ',')
- *end = '\0';
-
- if (1 != sscanf (begin, "%" SCNd32, &element))
- {
- FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
- ok = -1;
- return NULL;
- }
-
- GNUNET_array_append (elements_peer1, mcount, element);
- element_count_peer1++;
-
- begin = ++end;
- }
- while (!exit_loop && element_count_peer1 < max_mids);
-
- GNUNET_assert (elements_peer1 != NULL);
- GNUNET_assert (element_count_peer1 >= 1);
-
- qe = GNUNET_VECTORPRODUCT_prepare_response (peer1.vh,
- &key,
- element_count_peer1,
- elements_peer1,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
- &responder_callback,
- NULL);
-
- if (qe == NULL)
- {
- FPRINTF (stderr, "%s", _ ("Could not send request to vectorproduct service! Exitting!"));
- ok = -1;
- return NULL;
- }
- return qe;
-}
-
-
-/**
- * Scheduler task to initiate requester client
- *
- * @param cls void* to struct PeerData
- * @param tc Task Context
- */
-static void
-request_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext
- * tc)
-{
- struct PeerData * peer = cls;
-
- requester_request ();
- return;
-}
-
-
-/**
- * Scheduler task to initiate responder client
- *
- * @param cls void* to struct PeerData
- * @param tc Task Context
- */
-static void
-prepare_response_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext
- * tc)
-{
- struct PeerData * peer = cls;
-
- responder_prepare_response ();
- return;
-}
-
-
-static void
-peer_stop_callback (void *cls,
- const char *emsg)
-{
- GNUNET_TESTBED_peer_destroy (peer2.peer);
-}
-
-/**
- * Destroys Peer2 i.e. the initiator peer (Alice) This function is scheduled to
- * run a few milliseconds after the request has been sent to the Responding Peer (Bob).
- * This function tries to emulate a crash of Peer2.
- *
- * @param cls Not used
- * @param tc Task Context - Not used
- */
-static void
-destroy_server (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- LOG (GNUNET_ERROR_TYPE_INFO, "\n***\nKilling the Requesting Client, hopefully before it receives response\n***\n");
- do_shutdown (&peer2, NULL);
- GNUNET_TESTBED_peer_stop (peer2.peer, &peer_stop_callback, NULL);
-}
-
-
-/**
- * Adapter function called to destroy a connection to
- * a service. This function is called when GNUNET_TESTBED_operation_done is
- * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect
- * operation.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void
-vectorproduct_da (void *cls, void *op_result)
-{
- struct PeerData* peer = (struct PeerData*) cls;
-
- GNUNET_VECTORPRODUCT_disconnect (peer->vh);
- return;
-}
-
-
-/**
- * Adapter function called to establish a connection to
- * a service. This function is called to by GNUNET_TESTBED_service_connect.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- * GNUNET_TESTBED_operation_done() is called on the operation returned
- * from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-vectorproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- struct PeerData *p = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2,
- GNUNET_i2s (&p->our_id));
-
- switch (setup_state)
- {
- case PEER1_VECTORPRODUCT_CONNECT:
- /* Connect peer 2 to vectorproduct service */
- /* The connect adapter vectorproduct_ca will be called to perform the actual connection */
- {
- peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer2);
- setup_state = PEER2_VECTORPRODUCT_CONNECT;
- }
-
- /* Actually connect peer 1 to vectorproduct service */
- peer1.vh = GNUNET_VECTORPRODUCT_connect (cfg);
- return peer1.vh;
-
- case PEER2_VECTORPRODUCT_CONNECT:
- /* Actually connect peer 2 to vectorproduct service */
- peer2.vh = GNUNET_VECTORPRODUCT_connect (cfg);
-
-
- if (peer1.vh != NULL && peer2.vh != NULL)
- {
- GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer1);
- GNUNET_SCHEDULER_add_now (&request_task, &peer2);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 6),
- &destroy_server, NULL);
- }
- else
- {
- // TODO : Handle error. One of the peers is not connected. Cleanly shutdown
- ok = -1;
- return NULL;
- }
- return peer2.vh;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed; will be NULL if the
- * operation is successfull
- */
-static void
-peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
- const struct GNUNET_TESTBED_PeerInformation *pinfo,
- const char *emsg)
-{
- GNUNET_assert (NULL == emsg);
- GNUNET_assert (op == op_);
- switch (setup_state)
- {
- case PEER1_GET_IDENTITY:
- {
- memcpy (&peer1.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full
- (&peer1.our_id));
-
- /* Request for peer id of peer 2*/
- op = GNUNET_TESTBED_peer_get_information (peer2.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER2_GET_IDENTITY;
- }
- break;
- case PEER2_GET_IDENTITY:
- {
- memcpy (&peer2.our_id, pinfo->result.id,
- sizeof (struct GNUNET_PeerIdentity));
- GNUNET_TESTBED_operation_done (op);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full
- (&peer2.our_id));
-
- /* Connect peer 1 to vectorproduct service */
- /* The connect adapter vectorproduct_ca will be called to perform the actual connection */
- peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "vectorproduct",
- NULL, NULL, vectorproduct_ca,
- vectorproduct_da, &peer1);
- setup_state = PEER1_VECTORPRODUCT_CONNECT;
- }
- break;
- default:
- GNUNET_assert (0);
- }
-}
-
-
-/**
- * Signature of a main function for a testcase.
- *
- * @param cls closure
- * @param num_peers number of peers in 'peers'
- * @param peers handle to peers run in the testbed
- */
-static void
-test_master (void *cls, unsigned int num_peers,
- struct GNUNET_TESTBED_Peer **peers)
-{
- GNUNET_assert (NULL != peers);
- GNUNET_assert (NULL != peers[0]);
- GNUNET_assert (NULL != peers[1]);
- peer1.peer = peers[0];
- peer2.peer = peers[1];
- /* Get the peer identity and configuration of peer 1 */
- op = GNUNET_TESTBED_peer_get_information (peer1.peer,
- GNUNET_TESTBED_PIT_IDENTITY,
- &peerinfo_cb, NULL);
- setup_state = PEER1_GET_IDENTITY;
- abort_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
- NULL);
-}
-
-
-/**
- * Main function
- */
-int
-main (int argc, char **argv)
-{
- uint64_t event_mask;
-
- ok = GNUNET_NO;
- event_mask = 0;
- event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
- max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader))
- / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
-
- (void) GNUNET_TESTBED_test_run ("test_vectorproduct_api_regression2",
- "test_vectorproduct_api_data.conf",
- NUM_PEERS, event_mask, &controller_event_cb,
- NULL,
- &test_master, NULL);
- if (GNUNET_SYSERR == ok)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error before calling API for request or prepare_response\n");
- return 1;
- }
- else if (GNUNET_SYSERR == responder_ok)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error in response for responding_client\n");
- return 1;
- }
- else if (GNUNET_SYSERR == requester_ok)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error in response for requesting client\n");
- return 1;
- }
- else
- return 0;
-}
-
-
+++ /dev/null
-[vectorproduct]
-BINARY = gnunet-service-vectorproduct
-UNIXPATH = /tmp/gnunet-service-vectorproduct.sock
-HOME = $SERVICEHOME
-# PORT = 2106
-@UNIXONLY@ PORT = 2087
-
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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 2, 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file vectorproduct/vectorproduct_api.c
- * @brief API for the vectorproduct
- * @author Christian Fuchs
- * @author Gaurav Kukreja
- *
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_vectorproduct_service.h"
-#include "gnunet_protocols.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "vectorproduct-api",__VA_ARGS__)
-
-/**************************************************************
- *** Datatype Declarations **********
- **************************************************************/
-
-/**
- * Entry in the request queue per client
- */
-struct GNUNET_VECTORPRODUCT_QueueEntry
-{
- /**
- * This is a linked list.
- */
- struct GNUNET_VECTORPRODUCT_QueueEntry *next;
-
- /**
- * This is a linked list.
- */
- struct GNUNET_VECTORPRODUCT_QueueEntry *prev;
-
- /**
- * Handle to the master context.
- */
- struct GNUNET_VECTORPRODUCT_Handle *h;
-
- /**
- * Size of the message
- */
- uint16_t message_size;
-
- /**
- * Message to be sent to the vectorproduct service
- */
- struct GNUNET_VECTORPRODUCT_client_request* msg;
-
- union
- {
- /**
- * Function to call after transmission of the request.
- */
- GNUNET_VECTORPRODUCT_ContinuationWithStatus cont_status;
-
- /**
- * Function to call after transmission of the request.
- */
- GNUNET_VECTORPRODUCT_DatumProcessor cont_datum;
- };
-
- /**
- * Closure for 'cont'.
- */
- void *cont_cls;
-
- /**
- * Has this message been transmitted to the service?
- * Only ever GNUNET_YES for the head of the queue.
- * Note that the overall struct should end at a
- * multiple of 64 bits.
- */
- int16_t was_transmitted;
-
- /**
- * Timeout for the current operation.
- */
- struct GNUNET_TIME_Absolute timeout;
-
- /**
- * Task for timeout signaling.
- */
- GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
- /**
- * Response Processor for response from the service. This function calls the
- * continuation function provided by the client.
- */
- GNUNET_VECTORPRODUCT_ResponseMessageHandler response_proc;
-};
-
-/**************************************************************
- *** Function Declarations **********
- **************************************************************/
-
-/**
- * Creates a new entry at the tail of the DLL
- *
- * @param h handle to the master context
- *
- * @return pointer to the entry
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-make_queue_entry (struct GNUNET_VECTORPRODUCT_Handle *h);
-
-/**
- * Removes the head entry from the queue
- *
- * @param h Handle to the master context
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-free_queue_head_entry (struct GNUNET_VECTORPRODUCT_Handle * h);
-
-/**
- * Triggered when timeout occurs for a request in queue
- *
- * @param cls The pointer to the QueueEntry
- * @param tc Task Context
- */
-static void
-timeout_queue_entry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
- * Called when a response is received from the service. After basic check
- * handler in qe->response_proc is called. This functions handles the response
- * to the client which used the API.
- *
- * @param cls Pointer to the Master Context
- * @param msg Pointer to the data received in response
- */
-static void
-receive_cb (void *cls, const struct GNUNET_MessageHeader *msg);
-
-/**
- * Transmits the request to the VectorProduct Sevice
- *
- * @param cls Closure
- * @param size Size of the buffer
- * @param buf Pointer to the buffer
- *
- * @return Size of the message sent
- */
-static size_t transmit_request (void *cls, size_t size,
- void *buf);
-
-/**
- * Issues transmit request for the new entries in the queue
- *
- * @param h handle to the master context
- */
-static void
-process_queue (struct GNUNET_VECTORPRODUCT_Handle *h);
-
-/**************************************************************
- *** Static Function Declarations **********
- **************************************************************/
-
-
-/**
- * Creates a new entry at the tail of the DLL
- *
- * @param h handle to the master context
- *
- * @return pointer to the entry
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-make_queue_entry (struct GNUNET_VECTORPRODUCT_Handle *h)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
-
- qe = GNUNET_new (struct GNUNET_VECTORPRODUCT_QueueEntry);
-
- // if queue empty
- if (NULL == h->queue_head && NULL == h->queue_tail)
- {
- qe->next = NULL;
- qe->prev = NULL;
- h->queue_head = qe;
- h->queue_tail = qe;
- }
- else
- {
- qe->prev = h->queue_tail;
- h->queue_tail->next = qe;
- h->queue_tail = qe;
- }
-
- return qe;
-}
-
-
-/**
- * Removes the head entry from the queue
- *
- * @param h Handle to the master context
- */
-static struct GNUNET_VECTORPRODUCT_QueueEntry *
-free_queue_head_entry (struct GNUNET_VECTORPRODUCT_Handle * h)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry * qe = NULL;
-
- GNUNET_assert (NULL != h);
- if (NULL == h->queue_head && NULL == h->queue_tail)
- {
- // The queue is empty. Just return.
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue was empty when free_queue_head_entry was called.\n");
- }
- else if (h->queue_head == h->queue_tail) //only one entry
- {
- qe = h->queue_head;
- qe->next = NULL;
- qe->prev = NULL;
- h->queue_head = NULL;
- h->queue_tail = NULL;
- }
- else
- {
- qe = h->queue_head;
- h->queue_head = h->queue_head->next;
- h->queue_head->prev = NULL;
- qe->next = NULL;
- qe->prev = NULL;
- }
- return qe;
-}
-
-
-/**
- * Triggered when timeout occurs for a request in queue
- *
- * @param cls The pointer to the QueueEntry
- * @param tc Task Context
- */
-static void
-timeout_queue_entry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry * qe = cls;
-
- // Update Statistics
- GNUNET_STATISTICS_update (qe->h->stats,
- gettext_noop ("# queue entry timeouts"), 1,
- GNUNET_NO);
-
- // Clear the timeout_task
- qe->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-
- // transmit_request is supposed to cancel timeout task.
- // If message was not transmitted, there is definitely an error.
- GNUNET_assert (GNUNET_NO == qe->was_transmitted);
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Timeout of request in datastore queue\n");
-
- // remove the queue_entry for the queue
- GNUNET_CONTAINER_DLL_remove (qe->h->queue_head, qe->h->queue_tail, qe);
- qe->response_proc (qe, NULL, GNUNET_VECTORPRODUCT_Status_Timeout);
-}
-
-
-/**
- * Handles the RESULT received in reply of prepare_response from the
- * service
- *
- * @param cls Handle to the Master Context
- * @param msg Pointer to the response received
- */
-static void
-process_status_message (void *cls,
- const struct GNUNET_MessageHeader *msg,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe = cls;
-
- GNUNET_assert (qe != NULL);
-
- if (qe->cont_status != NULL)
- qe->cont_status (qe->cont_cls, &qe->msg->key, status);
-}
-
-
-/**
- * Handles the RESULT received in reply of prepare_response from the
- * service
- *
- * @param cls Handle to the Master Context
- * @param msg Pointer to the response received
- */
-static void
-process_result_message (void *cls,
- const struct GNUNET_MessageHeader *msg,
- enum GNUNET_VECTORPRODUCT_ResponseStatus status)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe = cls;
-
- GNUNET_assert (qe != NULL);
-
- if (msg == NULL && qe->cont_datum != NULL)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout reached or session terminated.\n");
- }
- if (qe->cont_datum != NULL)
- {
- qe->cont_datum (qe->cont_cls, &qe->msg->key, &qe->msg->peer, status, (struct GNUNET_VECTORPRODUCT_client_response *) msg);
- }
-}
-
-
-/**
- * Called when a response is received from the service. After basic check
- * handler in qe->response_proc is called. This functions handles the response
- * to the client which used the API.
- *
- * @param cls Pointer to the Master Context
- * @param msg Pointer to the data received in response
- */
-static void
-receive_cb (void *cls, const struct GNUNET_MessageHeader *msg)
-{
- struct GNUNET_VECTORPRODUCT_Handle *h = cls;
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
- int16_t was_transmitted;
- struct GNUNET_VECTORPRODUCT_client_response *message =
- (struct GNUNET_VECTORPRODUCT_client_response *) msg;
-
- h->in_receive = GNUNET_NO;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Received reply from VectorProduct\n");
-
- if (NULL == (qe = free_queue_head_entry (h)))
- {
- /**
- * The queue head will be NULL if the client disconnected,
- * * In case of Alice, client disconnected after sending request, before receiving response
- * * In case of Bob, client disconnected after preparing response, before getting request from Alice.
- */
- process_queue (h);
- return;
- }
-
- if (h->client == NULL)
- {
- // GKUKREJA : handle this correctly
- /**
- * The queue head will be NULL if the client disconnected,
- * * In case of Alice, client disconnected after sending request, before receiving response
- * * In case of Bob, client disconnected after preparing response, before getting request from Alice.
- */
- process_queue (h);
- return;
- }
-
- was_transmitted = qe->was_transmitted;
- // Control will only come here, when the request was transmitted to service,
- // and service responded.
- GNUNET_assert (was_transmitted == GNUNET_YES);
-
- if (msg == NULL)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Service responded with NULL!\n");
- qe->response_proc (qe, NULL, GNUNET_VECTORPRODUCT_Status_Failure);
- }
- else if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_VECTORPRODUCT_SERVICE_TO_CLIENT))
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "Invalid Message Received\n");
- qe->response_proc (qe, msg, GNUNET_VECTORPRODUCT_Status_InvalidResponse);
- }
- else if (ntohl (message->product_length) == 0)
- {
- // response for the responder client, successful
- GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# SUC responder result messages received"), 1,
- GNUNET_NO);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message from service without product attached.\n");
- qe->response_proc (qe, msg, GNUNET_VECTORPRODUCT_Status_Success);
- }
- else if (ntohl (message->product_length) > 0)
- {
- // response for the requester client, successful
- GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# SUC requester result messages received"), 1,
- GNUNET_NO);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message from requester service for requester client.\n");
- qe->response_proc (qe, msg, GNUNET_VECTORPRODUCT_Status_Success);
- }
-
- GNUNET_free (qe);
- process_queue (h);
-}
-
-
-/**
- * Transmits the request to the VectorProduct Sevice
- *
- * @param cls Closure
- * @param size Size of the buffer
- * @param buf Pointer to the buffer
- *
- * @return Size of the message sent
- */
-static size_t
-transmit_request (void *cls, size_t size,
- void *buf)
-{
- struct GNUNET_VECTORPRODUCT_Handle *h = cls;
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
- size_t msize;
-
- if (NULL == (qe = h->queue_head))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue head is NULL!\n\n");
- return 0;
- }
-
- GNUNET_SCHEDULER_cancel (qe->timeout_task);
- qe->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-
- h->th = NULL;
- if (NULL == (qe = h->queue_head))
- return 0; /* no entry in queue */
- if (buf == NULL)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to VECTORPRODUCT.\n");
- GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# transmission request failures"),
- 1, GNUNET_NO);
- GNUNET_VECTORPRODUCT_disconnect (h);
- return 0;
- }
- if (size < (msize = qe->message_size))
- {
- process_queue (h);
- return 0;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u byte request to VECTORPRODUCT\n",
- msize);
-
- memcpy (buf, qe->msg, size);
- GNUNET_free (qe->msg);
- qe->was_transmitted = GNUNET_YES;
-
- GNUNET_assert (GNUNET_NO == h->in_receive);
- h->in_receive = GNUNET_YES;
-
- GNUNET_CLIENT_receive (h->client, &receive_cb, h,
- GNUNET_TIME_UNIT_FOREVER_REL);
-
-#if INSANE_STATISTICS
- GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# bytes sent to vectorproduct"), 1,
- GNUNET_NO);
-#endif
- return size;
-}
-
-
-/**
- * Issues transmit request for the new entries in the queue
- *
- * @param h handle to the master context
- */
-static void
-process_queue (struct GNUNET_VECTORPRODUCT_Handle *h)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
-
- if (NULL == (qe = h->queue_head))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue empty\n");
- return; /* no entry in queue */
- }
- if (qe->was_transmitted == GNUNET_YES)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Head request already transmitted\n");
- return; /* waiting for replies */
- }
- if (h->th != NULL)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Pending transmission request\n");
- return; /* request pending */
- }
- if (h->client == NULL)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Not connected\n");
- return; /* waiting for reconnect */
- }
- if (GNUNET_YES == h->in_receive)
- {
- /* wait for response to previous query */
- return;
- }
-
- h->th =
- GNUNET_CLIENT_notify_transmit_ready (h->client, qe->message_size,
- GNUNET_TIME_UNIT_FOREVER_REL,
- GNUNET_YES,
- &transmit_request, h);
-
- if (h->th == NULL)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _ ("Failed to send a message to the vectorproduct service\n"));
- return;
- }
-
- GNUNET_assert (GNUNET_NO == h->in_receive);
- GNUNET_break (NULL != h->th);
-}
-
-
-
-/**************************************************************
- *** API **********
- **************************************************************/
-
-
-/**
- * Called by the responder client to prepare response
- *
- * @param h handle to the master context
- * @param key Session key - unique to the requesting client
- * @param element_count Number of elements in the vector
- * @param mask_length number of bytes in the mask
- * @param elements Array of elements of the vector
- * @param mask Array of the mask
- * @param timeout Relative timeout for the operation
- * @param cont Callback function
- * @param cont_cls Closure for the callback function
- */
-struct GNUNET_VECTORPRODUCT_QueueEntry *
-GNUNET_VECTORPRODUCT_prepare_response (struct GNUNET_VECTORPRODUCT_Handle *h,
- const struct GNUNET_HashCode * key,
- uint16_t element_count,
- int32_t * elements,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_VECTORPRODUCT_ContinuationWithStatus cont,
- void *cont_cls)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe = make_queue_entry (h);
- int32_t * vector;
- uint16_t size;
- unsigned int i;
-
- GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_VECTORPRODUCT_client_request)
- +element_count * sizeof (int32_t));
- size = sizeof (struct GNUNET_VECTORPRODUCT_client_request) +element_count * sizeof (int32_t);
-
- qe->message_size = size;
- qe->msg = GNUNET_malloc (size);
- qe->msg->header.size = htons (size);
- qe->msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_CLIENT_TO_BOB);
- qe->msg->element_count = htons (element_count);
- qe->msg->mask_length = htons (0);
- memcpy (&qe->msg->key, key, sizeof (struct GNUNET_HashCode));
- qe->cont_status = cont;
- qe->cont_cls = cont_cls;
- qe->was_transmitted = GNUNET_NO;
- qe->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_queue_entry, qe);
- qe->response_proc = &process_status_message;
- qe->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-
- vector = (int32_t *) & qe->msg[1];
- // copy each element over to the message
- for (i = 0; i < element_count; i++)
- vector[i] = htonl (elements[i]);
-
- process_queue (h);
- return qe;
-}
-
-
-/**
- * Request the Scalar Product Evaluation
- *
- * @param h handle to the master context
- * @param key Session key - unique to the requesting client
- * @param peer PeerID of the other peer
- * @param element_count Number of elements in the vector
- * @param mask_length number of bytes in the mask
- * @param elements Array of elements of the vector
- * @param mask Array of the mask
- * @param timeout Relative timeout for the operation
- * @param cont Callback function
- * @param cont_cls Closure for the callback function
- */
-struct GNUNET_VECTORPRODUCT_QueueEntry *
-GNUNET_VECTORPRODUCT_request (struct GNUNET_VECTORPRODUCT_Handle *h,
- const struct GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity * peer,
- uint16_t element_count,
- uint16_t mask_length,
- int32_t * elements,
- const unsigned char * mask,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_VECTORPRODUCT_DatumProcessor cont,
- void *cont_cls)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry *qe = make_queue_entry (h);
- int32_t * vector;
- uint16_t size;
- unsigned int i;
-
- GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_VECTORPRODUCT_client_request)
- +element_count * sizeof (int32_t)
- + mask_length);
- size = sizeof (struct GNUNET_VECTORPRODUCT_client_request) +element_count * sizeof (int32_t) + mask_length;
-
- qe->message_size = size;
- qe->msg = GNUNET_malloc (size);
- qe->msg->header.size = htons (size);
- qe->msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_CLIENT_TO_ALICE);
- memcpy (&qe->msg->peer, peer, sizeof (struct GNUNET_PeerIdentity));
- qe->msg->element_count = htons (element_count);
- qe->msg->mask_length = htons (mask_length);
- memcpy (&qe->msg->key, key, sizeof (struct GNUNET_HashCode));
- qe->cont_datum = cont;
- qe->cont_cls = cont_cls;
- qe->was_transmitted = GNUNET_NO;
- qe->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_queue_entry, qe);
- qe->response_proc = &process_result_message;
- qe->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-
- vector = (int32_t*) & qe->msg[1];
- // copy each element over to the message
- for (i = 0; i < element_count; i++)
- vector[i] = htonl (elements[i]);
-
- // fill in the mask
- memcpy (&vector[element_count], mask, mask_length);
-
- process_queue (h);
- return qe;
-}
-
-
-/**
- * Connect to the vectorproduct service.
- *
- * @param cfg configuration to use
- * @return handle to use to access the service
- */
-struct GNUNET_VECTORPRODUCT_Handle *
-GNUNET_VECTORPRODUCT_connect (const struct GNUNET_CONFIGURATION_Handle * cfg)
-{
- struct GNUNET_CLIENT_Connection *client;
- struct GNUNET_VECTORPRODUCT_Handle *h;
-
- client = GNUNET_CLIENT_connect ("vectorproduct", cfg);
-
- if (NULL == client)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _ ("Failed to connect to the vectorproduct service\n"));
- return NULL;
- }
-
- h = GNUNET_malloc (sizeof (struct GNUNET_VECTORPRODUCT_Handle) +
- GNUNET_SERVER_MAX_MESSAGE_SIZE - 1);
- h->client = client;
- h->cfg = cfg;
- h->stats = GNUNET_STATISTICS_create ("vectorproduct-api", cfg);
- return h;
-}
-
-
-/**
- * Disconnect from the vectorproduct service.
- *
- * @param h handle to the vectorproduct
- */
-void
-GNUNET_VECTORPRODUCT_disconnect (struct GNUNET_VECTORPRODUCT_Handle * h)
-{
- struct GNUNET_VECTORPRODUCT_QueueEntry * qe;
-
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Disconnecting from VectorProduct\n");
-
- while (NULL != h->queue_head)
- {
- GNUNET_assert (NULL != (qe = free_queue_head_entry (h)));
- qe->response_proc (qe, NULL, GNUNET_VECTORPRODUCT_Status_ServiceDisconnected);
- }
-
- if (h->client != NULL)
- {
- GNUNET_CLIENT_disconnect (h->client);
- h->client = NULL;
- }
-
- GNUNET_STATISTICS_destroy (h->stats, GNUNET_NO);
- h->stats = NULL;
-}
-
-/* end of ext_api.c */
+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
-
- 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-/**
- * @file vectorproduct/vectorproduct_testing.h
- * @brief VectorProduct testcase common declarations
- * @author Gaurav Kukreja
- * @author Christian Fuchs
- *
- * Created on June 29, 2013, 7:39 PM
- */
-
-#ifndef VECTORPRODUCT_TESTING_H
-#define VECTORPRODUCT_TESTING_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct GNUNET_VECTORPRODUCT_TESTING_handle
-{
- /**
- * Testing library system handle
- */
- struct GNUNET_TESTING_System *tl_system;
-
- /**
- * head DLL of peers
- */
- struct PeerContext *p_head;
-
- /**
- * tail DLL of peers
- */
- struct PeerContext *p_tail;
-};
-
-struct PeerContext
-{
- /**
- * Next element in the DLL
- */
- struct PeerContext *next;
-
- /**
- * Previous element in the DLL
- */
- struct PeerContext *prev;
-
- /**
- * Peer's testing handle
- */
- struct GNUNET_TESTING_Peer *peer;
-
- /**
- * Peer identity
- */
- struct GNUNET_PeerIdentity id;
-
- /**
- * Handle for the peer's ARM process
- */
- struct GNUNET_OS_Process *arm_proc;
-
- /**
- * Pointer to Vector Product Handle
- */
- struct GNUNET_VECTORPRODUCT_Handle *vh;
-
- /**
- * Closure for the callbacks
- */
- void *cb_cls;
-
- /**
- * An unique number to identify the peer
- */
- unsigned int no;
-
- /**
- * Peer's configuration
- */
- struct GNUNET_CONFIGURATION_Handle *cfg;
-
- /**
- * Pointer to the master testing handle
- */
- struct GNUNET_VECTORPRODUCT_TESTING_handle * vth;
-
- /**
- * Callback when two peers are connected and both have called the connect callback
- * to notify clients about a new peer
- */
- void (*start_cb) (struct PeerContext * p, void *cls);
-
-// /**
-// * Pointer to function where the test occurs
-// */
-// GNUNET_VECTORPRODUCT_TESTING_start_cb start_cb;
-};
-
-/**
- * Callback when two peers are connected and both have called the connect callback
- * to notify clients about a new peer
- */
-typedef void (*GNUNET_VECTORPRODUCT_TESTING_start_cb) (struct PeerContext * p,
- void *cls);
-
-struct GNUNET_VECTORPRODUCT_TESTING_handle *
-GNUNET_VECTORPRODUCT_TESTING_init();
-
-static void
-GNUNET_VECTORPRODUCT_TESTING_done(struct GNUNET_VECTORPRODUCT_TESTING_handle * vth);
-
-struct PeerContext *
-GNUNET_VECTORPRODUCT_TESTING_start_peer (struct GNUNET_VECTORPRODUCT_TESTING_handle * vth,
- const char *cfgname, int peer_id,
- GNUNET_VECTORPRODUCT_TESTING_start_cb start_cb,
- void *cb_cls);
-
-static void
-GNUNET_VECTORPRODUCT_TESTING_stop_peer
- (struct GNUNET_VECTORPRODUCT_TESTING_handle * vth,
- struct PeerContext *p);
-
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* VECTORPRODUCT_TESTING_H */
-