[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r28817 - gnunet/src/scalarproduct
From: |
gnunet |
Subject: |
[GNUnet-SVN] r28817 - gnunet/src/scalarproduct |
Date: |
Fri, 23 Aug 2013 15:42:15 +0200 |
Author: grothoff
Date: 2013-08-23 15:42:15 +0200 (Fri, 23 Aug 2013)
New Revision: 28817
Added:
gnunet/src/scalarproduct/gnunet-scalarproduct.c
gnunet/src/scalarproduct/gnunet-service-scalarproduct.c
gnunet/src/scalarproduct/gnunet_scalarproduct.h
gnunet/src/scalarproduct/scalarproduct.conf
gnunet/src/scalarproduct/scalarproduct_api.c
gnunet/src/scalarproduct/test_scalarproduct_api.c
gnunet/src/scalarproduct/test_scalarproduct_api_4peers.c
gnunet/src/scalarproduct/test_scalarproduct_api_data.conf
gnunet/src/scalarproduct/test_scalarproduct_api_regression.c
gnunet/src/scalarproduct/test_scalarproduct_api_regression2.c
Removed:
gnunet/src/scalarproduct/gnunet-service-vectorproduct.c
gnunet/src/scalarproduct/gnunet-vectorproduct.c
gnunet/src/scalarproduct/gnunet_vectorproduct.h
gnunet/src/scalarproduct/test_vectorproduct_api.c
gnunet/src/scalarproduct/test_vectorproduct_api_4peers.c
gnunet/src/scalarproduct/test_vectorproduct_api_data.conf
gnunet/src/scalarproduct/test_vectorproduct_api_regression.c
gnunet/src/scalarproduct/test_vectorproduct_api_regression2.c
gnunet/src/scalarproduct/vectorproduct.conf
gnunet/src/scalarproduct/vectorproduct_api.c
Modified:
gnunet/src/scalarproduct/Makefile.am
Log:
-more vector -> scalar renaming
Modified: gnunet/src/scalarproduct/Makefile.am
===================================================================
--- gnunet/src/scalarproduct/Makefile.am 2013-08-23 13:39:32 UTC (rev
28816)
+++ gnunet/src/scalarproduct/Makefile.am 2013-08-23 13:42:15 UTC (rev
28817)
@@ -5,7 +5,7 @@
libexecdir= $(pkglibdir)/libexec/
pkgcfg_DATA = \
- vectorproduct.conf
+ scalarproduct.conf
if MINGW
WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
@@ -16,33 +16,27 @@
endif
bin_PROGRAMS = \
- gnunet-vectorproduct
+ gnunet-scalarproduct
libexec_PROGRAMS = \
- gnunet-service-vectorproduct
+ gnunet-service-scalarproduct
-# FIXME: add option "configure --with-evil"?
-#if HAVE_EXPERIMENTAL
-#libexec_PROGRAMS += \
-# gnunet-service-evil-consensus
-#endif
-
lib_LTLIBRARIES = \
- libgnunetvectorproduct.la
+ libgnunetscalarproduct.la
-gnunet_vectorproduct_SOURCES = \
- gnunet-vectorproduct.c
-gnunet_vectorproduct_LDADD = \
+gnunet_scalarproduct_SOURCES = \
+ gnunet-scalarproduct.c
+gnunet_scalarproduct_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
+ $(top_builddir)/src/scalarproduct/libgnunetscalarproduct.la \
-lgcrypt \
$(GN_LIBINTL)
-gnunet_vectorproduct_DEPENDENCIES = \
- libgnunetvectorproduct.la
+gnunet_scalarproduct_DEPENDENCIES = \
+ libgnunetscalarproduct.la
-gnunet_service_vectorproduct_SOURCES = \
- gnunet-service-vectorproduct.c
-gnunet_service_vectorproduct_LDADD = \
+gnunet_service_scalarproduct_SOURCES = \
+ gnunet-service-scalarproduct.c
+gnunet_service_scalarproduct_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/core/libgnunetcore.la \
$(top_builddir)/src/mesh/libgnunetmesh.la \
@@ -50,22 +44,22 @@
-lgcrypt \
$(GN_LIBINTL)
-libgnunetvectorproduct_la_SOURCES = \
- vectorproduct_api.c
-libgnunetvectorproduct_la_LIBADD = \
+libgnunetscalarproduct_la_SOURCES = \
+ scalarproduct_api.c
+libgnunetscalarproduct_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
-lgcrypt \
$(LTLIBINTL)
-libgnunetvectorproduct_la_LDFLAGS = \
+libgnunetscalarproduct_la_LDFLAGS = \
$(GN_LIB_LDFLAGS)
check_PROGRAMS = \
- test_vectorproduct_api_regression \
- test_vectorproduct_api \
- test_vectorproduct_api_4peers
+ test_scalarproduct_api_regression \
+ test_scalarproduct_api \
+ test_scalarproduct_api_4peers
#FIXME unfinished
-#test_vectorproduct_api_regression2
+#test_scalarproduct_api_regression2
if ENABLE_TEST_RUN
TESTS = $(check_PROGRAMS)
@@ -78,35 +72,35 @@
$(top_builddir)/src/testing/libgnunettesting.la \
$(top_builddir)/src/consensus/libgnunetconsensus.la
-test_vectorproduct_api_SOURCES = \
- test_vectorproduct_api.c
-test_vectorproduct_api_LDADD = \
+test_scalarproduct_api_SOURCES = \
+ test_scalarproduct_api.c
+test_scalarproduct_api_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
+ $(top_builddir)/src/scalarproduct/libgnunetscalarproduct.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 \
+#test_scalarproduct_api_regression2_SOURCES = \
+# test_scalarproduct_api_regression2.c
+#test_scalarproduct_api_regression2_LDADD = \
+# $(top_builddir)/src/scalarproduct/libgnunetscalarproduct.la \
# $(top_builddir)/src/util/libgnunetutil.la \
# -lgcrypt
-test_vectorproduct_api_regression_SOURCES = \
- test_vectorproduct_api_regression.c
-test_vectorproduct_api_regression_LDADD = \
+test_scalarproduct_api_regression_SOURCES = \
+ test_scalarproduct_api_regression.c
+test_scalarproduct_api_regression_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
+ $(top_builddir)/src/scalarproduct/libgnunetscalarproduct.la \
-lgcrypt
-test_vectorproduct_api_4peers_SOURCES = \
- test_vectorproduct_api_4peers.c
-test_vectorproduct_api_4peers_LDADD = \
+test_scalarproduct_api_4peers_SOURCES = \
+ test_scalarproduct_api_4peers.c
+test_scalarproduct_api_4peers_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/vectorproduct/libgnunetvectorproduct.la \
+ $(top_builddir)/src/scalarproduct/libgnunetscalarproduct.la \
-lgcrypt
-
+
EXTRA_DIST = \
- test_vectorproduct.conf
-
+ test_scalarproduct.conf
+
Copied: gnunet/src/scalarproduct/gnunet-scalarproduct.c (from rev 28816,
gnunet/src/scalarproduct/gnunet-vectorproduct.c)
===================================================================
--- gnunet/src/scalarproduct/gnunet-scalarproduct.c
(rev 0)
+++ gnunet/src/scalarproduct/gnunet-scalarproduct.c 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -0,0 +1,410 @@
+/*
+ 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;
+}
+
Copied: gnunet/src/scalarproduct/gnunet-service-scalarproduct.c (from rev
28816, gnunet/src/scalarproduct/gnunet-service-vectorproduct.c)
===================================================================
--- gnunet/src/scalarproduct/gnunet-service-scalarproduct.c
(rev 0)
+++ gnunet/src/scalarproduct/gnunet-service-scalarproduct.c 2013-08-23
13:42:15 UTC (rev 28817)
@@ -0,0 +1,2067 @@
+/*
+ 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 */
Deleted: gnunet/src/scalarproduct/gnunet-service-vectorproduct.c
===================================================================
--- gnunet/src/scalarproduct/gnunet-service-vectorproduct.c 2013-08-23
13:39:32 UTC (rev 28816)
+++ gnunet/src/scalarproduct/gnunet-service-vectorproduct.c 2013-08-23
13:42:15 UTC (rev 28817)
@@ -1,2067 +0,0 @@
-/*
- 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 */
Deleted: gnunet/src/scalarproduct/gnunet-vectorproduct.c
===================================================================
--- gnunet/src/scalarproduct/gnunet-vectorproduct.c 2013-08-23 13:39:32 UTC
(rev 28816)
+++ gnunet/src/scalarproduct/gnunet-vectorproduct.c 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -1,410 +0,0 @@
-/*
- 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;
-}
-
Copied: gnunet/src/scalarproduct/gnunet_scalarproduct.h (from rev 28816,
gnunet/src/scalarproduct/gnunet_vectorproduct.h)
===================================================================
--- gnunet/src/scalarproduct/gnunet_scalarproduct.h
(rev 0)
+++ gnunet/src/scalarproduct/gnunet_scalarproduct.h 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -0,0 +1,274 @@
+/*
+ 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 include/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 */
+
Deleted: gnunet/src/scalarproduct/gnunet_vectorproduct.h
===================================================================
--- gnunet/src/scalarproduct/gnunet_vectorproduct.h 2013-08-23 13:39:32 UTC
(rev 28816)
+++ gnunet/src/scalarproduct/gnunet_vectorproduct.h 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -1,274 +0,0 @@
-/*
- 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 include/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 */
-
Copied: gnunet/src/scalarproduct/scalarproduct.conf (from rev 28816,
gnunet/src/scalarproduct/vectorproduct.conf)
===================================================================
--- gnunet/src/scalarproduct/scalarproduct.conf (rev 0)
+++ gnunet/src/scalarproduct/scalarproduct.conf 2013-08-23 13:42:15 UTC (rev
28817)
@@ -0,0 +1,7 @@
+[vectorproduct]
+BINARY = gnunet-service-vectorproduct
+UNIXPATH = /tmp/gnunet-service-vectorproduct.sock
+HOME = $SERVICEHOME
+# PORT = 2106
+# PORT = 2087
+
Copied: gnunet/src/scalarproduct/scalarproduct_api.c (from rev 28816,
gnunet/src/scalarproduct/vectorproduct_api.c)
===================================================================
--- gnunet/src/scalarproduct/scalarproduct_api.c
(rev 0)
+++ gnunet/src/scalarproduct/scalarproduct_api.c 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -0,0 +1,715 @@
+/*
+ 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 */
Copied: gnunet/src/scalarproduct/test_scalarproduct_api.c (from rev 28816,
gnunet/src/scalarproduct/test_vectorproduct_api.c)
===================================================================
--- gnunet/src/scalarproduct/test_scalarproduct_api.c
(rev 0)
+++ gnunet/src/scalarproduct/test_scalarproduct_api.c 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -0,0 +1,865 @@
+/*
+ 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;
+}
+
+
Copied: gnunet/src/scalarproduct/test_scalarproduct_api_4peers.c (from rev
28816, gnunet/src/scalarproduct/test_vectorproduct_api_4peers.c)
===================================================================
--- gnunet/src/scalarproduct/test_scalarproduct_api_4peers.c
(rev 0)
+++ gnunet/src/scalarproduct/test_scalarproduct_api_4peers.c 2013-08-23
13:42:15 UTC (rev 28817)
@@ -0,0 +1,1084 @@
+
+/*
+ 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;
+}
Copied: gnunet/src/scalarproduct/test_scalarproduct_api_data.conf (from rev
28816, gnunet/src/scalarproduct/test_vectorproduct_api_data.conf)
===================================================================
--- gnunet/src/scalarproduct/test_scalarproduct_api_data.conf
(rev 0)
+++ gnunet/src/scalarproduct/test_scalarproduct_api_data.conf 2013-08-23
13:42:15 UTC (rev 28817)
@@ -0,0 +1,96 @@
+[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
+
Copied: gnunet/src/scalarproduct/test_scalarproduct_api_regression.c (from rev
28816, gnunet/src/scalarproduct/test_vectorproduct_api_regression.c)
===================================================================
--- gnunet/src/scalarproduct/test_scalarproduct_api_regression.c
(rev 0)
+++ gnunet/src/scalarproduct/test_scalarproduct_api_regression.c
2013-08-23 13:42:15 UTC (rev 28817)
@@ -0,0 +1,852 @@
+
+/*
+ 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;
+}
+
+
Copied: gnunet/src/scalarproduct/test_scalarproduct_api_regression2.c (from rev
28816, gnunet/src/scalarproduct/test_vectorproduct_api_regression2.c)
===================================================================
--- gnunet/src/scalarproduct/test_scalarproduct_api_regression2.c
(rev 0)
+++ gnunet/src/scalarproduct/test_scalarproduct_api_regression2.c
2013-08-23 13:42:15 UTC (rev 28817)
@@ -0,0 +1,931 @@
+/*
+ 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;
+}
+
+
Deleted: gnunet/src/scalarproduct/test_vectorproduct_api.c
===================================================================
--- gnunet/src/scalarproduct/test_vectorproduct_api.c 2013-08-23 13:39:32 UTC
(rev 28816)
+++ gnunet/src/scalarproduct/test_vectorproduct_api.c 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -1,865 +0,0 @@
-/*
- 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;
-}
-
-
Deleted: gnunet/src/scalarproduct/test_vectorproduct_api_4peers.c
===================================================================
--- gnunet/src/scalarproduct/test_vectorproduct_api_4peers.c 2013-08-23
13:39:32 UTC (rev 28816)
+++ gnunet/src/scalarproduct/test_vectorproduct_api_4peers.c 2013-08-23
13:42:15 UTC (rev 28817)
@@ -1,1084 +0,0 @@
-
-/*
- 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;
-}
Deleted: gnunet/src/scalarproduct/test_vectorproduct_api_data.conf
===================================================================
--- gnunet/src/scalarproduct/test_vectorproduct_api_data.conf 2013-08-23
13:39:32 UTC (rev 28816)
+++ gnunet/src/scalarproduct/test_vectorproduct_api_data.conf 2013-08-23
13:42:15 UTC (rev 28817)
@@ -1,96 +0,0 @@
-[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
-
Deleted: gnunet/src/scalarproduct/test_vectorproduct_api_regression.c
===================================================================
--- gnunet/src/scalarproduct/test_vectorproduct_api_regression.c
2013-08-23 13:39:32 UTC (rev 28816)
+++ gnunet/src/scalarproduct/test_vectorproduct_api_regression.c
2013-08-23 13:42:15 UTC (rev 28817)
@@ -1,852 +0,0 @@
-
-/*
- 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;
-}
-
-
Deleted: gnunet/src/scalarproduct/test_vectorproduct_api_regression2.c
===================================================================
--- gnunet/src/scalarproduct/test_vectorproduct_api_regression2.c
2013-08-23 13:39:32 UTC (rev 28816)
+++ gnunet/src/scalarproduct/test_vectorproduct_api_regression2.c
2013-08-23 13:42:15 UTC (rev 28817)
@@ -1,931 +0,0 @@
-/*
- 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;
-}
-
-
Deleted: gnunet/src/scalarproduct/vectorproduct.conf
===================================================================
--- gnunet/src/scalarproduct/vectorproduct.conf 2013-08-23 13:39:32 UTC (rev
28816)
+++ gnunet/src/scalarproduct/vectorproduct.conf 2013-08-23 13:42:15 UTC (rev
28817)
@@ -1,7 +0,0 @@
-[vectorproduct]
-BINARY = gnunet-service-vectorproduct
-UNIXPATH = /tmp/gnunet-service-vectorproduct.sock
-HOME = $SERVICEHOME
-# PORT = 2106
-# PORT = 2087
-
Deleted: gnunet/src/scalarproduct/vectorproduct_api.c
===================================================================
--- gnunet/src/scalarproduct/vectorproduct_api.c 2013-08-23 13:39:32 UTC
(rev 28816)
+++ gnunet/src/scalarproduct/vectorproduct_api.c 2013-08-23 13:42:15 UTC
(rev 28817)
@@ -1,715 +0,0 @@
-/*
- 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 */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r28817 - gnunet/src/scalarproduct,
gnunet <=