gnunet-svn
[Top][All Lists]
Advanced

[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,
+                               &current[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,
-                               &current[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 */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]