gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r33177 - in gnunet/src: include scalarproduct set


From: gnunet
Subject: [GNUnet-SVN] r33177 - in gnunet/src: include scalarproduct set
Date: Wed, 7 May 2014 10:21:49 +0200

Author: cfuchs
Date: 2014-05-07 10:21:49 +0200 (Wed, 07 May 2014)
New Revision: 33177

Modified:
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/include/gnunet_scalarproduct_service.h
   gnunet/src/scalarproduct/gnunet-scalarproduct.c
   gnunet/src/scalarproduct/gnunet-service-scalarproduct.c
   gnunet/src/scalarproduct/scalarproduct.h
   gnunet/src/scalarproduct/scalarproduct_api.c
   gnunet/src/set/gnunet-service-set_intersection.c
Log:
WIP commit of scalar product 2.0. It is unfinished and does not yet pass tests. 
This commit happens because of the move from mesh->cadet.

- reverted SP API back to the original design from 2012 (using key-value pairs)
- SP now uses set intersection to determine common elements from the set 
provided by the user
- values are sorted based on their keys after intersection
- removed state tracking, as simple tracking is now insufficient. Just checking 
for conditions directly is easier readable and less buggy
- modified/renamed SP message types to reflect the changed behavior of SP


Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2014-05-07 07:32:26 UTC (rev 
33176)
+++ gnunet/src/include/gnunet_protocols.h       2014-05-07 08:21:49 UTC (rev 
33177)
@@ -2056,41 +2056,53 @@
  
******************************************************************************/
 
 /**
- * Client -> Vector-Product Service request message
+ * Client -> Alice
  */
 #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE 640
 
 /**
- * Client -> Vector-Product Service request message
+ * Client -> Bob
  */
 #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB 641
 
 /**
- * Vector-Product Service request -> remote VP Service
+ * Client -> Alice/Bob multipart
  */
-#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB 642
+#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART 642
 
 /**
- * Vector-Product Service request -> remote VP Service Multipart
+ * Alice -> Bob session initialization
  */
-#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART 643
+#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION 643
 
 /**
- * remote Vector-Product Service response -> requesting VP Service
+ * Alice -> Bob SP crypto-data (after intersection)
  */
-#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE 644
+#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA 644
 
 /**
- * remote Vector-Product Service response -> requesting VP Service Multipart
+ * Alice -> Bob SP crypto-data multipart
  */
-#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE_MULTIPART 645
+#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART 645
 
 /**
- * Vector-Product Service response -> Client
+ * Bob -> Alice SP crypto-data
  */
-#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT 646
+#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA 646
 
+/**
+ * Bob -> Alice SP crypto-data multipart
+ */
+#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART 647
 
+/**
+ * Alice/Bob -> Client Result
+ */
+#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT 648
+
+
+
+
 
/*******************************************************************************
  * PSYCSTORE message types
  
******************************************************************************/

Modified: gnunet/src/include/gnunet_scalarproduct_service.h
===================================================================
--- gnunet/src/include/gnunet_scalarproduct_service.h   2014-05-07 07:32:26 UTC 
(rev 33176)
+++ gnunet/src/include/gnunet_scalarproduct_service.h   2014-05-07 08:21:49 UTC 
(rev 33177)
@@ -39,7 +39,7 @@
 /**
  * Version of the scalarproduct API.
  */
-#define GNUNET_SCALARPRODUCT_VERSION 0x00000042
+#define GNUNET_SCALARPRODUCT_VERSION 0x00000043
 
 enum GNUNET_SCALARPRODUCT_ResponseStatus
 {
@@ -55,7 +55,15 @@
  */
 struct GNUNET_SCALARPRODUCT_Handle;
 
+/**
+ * An element key-value pair for scalarproduct
+ */
+struct GNUNET_SCALARPRODUCT_Element {
+    int32_t value;
+    struct GNUNET_HashCode key;
+};
 
+
 /**
  * Continuation called to notify client about result of the
  * operation.
@@ -87,24 +95,21 @@
  * Request by Alice's client for computing a scalar product
  *
  * @param cfg the gnunet configuration handle
- * @param key Session key should be unique to the requesting client
+ * @param session_key Session key should be unique to the requesting client
  * @param peer PeerID of the other peer
  * @param elements Array of elements of the vector
  * @param element_count Number of elements in the vector
- * @param mask Array of the mask
- * @param mask_bytes number of bytes in the mask
  * @param cont Callback function
- * @param cont_cls Closure for @a cont
+ * @param cont_cls Closure for the callback function
+ *
  * @return a new handle for this computation
  */
 struct GNUNET_SCALARPRODUCT_ComputationHandle *
-GNUNET_SCALARPRODUCT_request (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                              const struct GNUNET_HashCode *key,
+GNUNET_SCALARPRODUCT_start_computation (const struct 
GNUNET_CONFIGURATION_Handle * cfg,
+                              const struct GNUNET_HashCode * session_key,
                               const struct GNUNET_PeerIdentity *peer,
-                              const int32_t *elements,
+                              const struct GNUNET_SCALARPRODUCT_Element * 
elements,
                               uint32_t element_count,
-                              const unsigned char *mask,
-                              uint32_t mask_bytes,
                               GNUNET_SCALARPRODUCT_DatumProcessor cont,
                               void * cont_cls);
 
@@ -112,20 +117,21 @@
  * Used by Bob's client to cooperate with Alice,
  *
  * @param cfg the gnunet configuration handle
- * @param key Session key unique to the requesting client
+ * @param session_key Session key unique to the requesting client
  * @param elements Array of elements of the vector
  * @param element_count Number of elements in the vector
  * @param cont Callback function
- * @param cont_cls Closure for @a cont
+ * @param cont_cls Closure for the callback function
+ *
  * @return a new handle for this computation
  */
 struct GNUNET_SCALARPRODUCT_ComputationHandle *
-GNUNET_SCALARPRODUCT_response (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                               const struct GNUNET_HashCode *key,
-                               const int32_t *elements,
+GNUNET_SCALARPRODUCT_accept_computation (const struct 
GNUNET_CONFIGURATION_Handle * cfg,
+                               const struct GNUNET_HashCode * key,
+                               const struct GNUNET_SCALARPRODUCT_Element * 
elements,
                                uint32_t element_count,
                                GNUNET_SCALARPRODUCT_ContinuationWithStatus 
cont,
-                               void *cont_cls);
+                               void * cont_cls);
 
 
 /**
@@ -137,20 +143,6 @@
 void
 GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle *h);
 
-
-/**
- * Cancel ALL ongoing computation or revoke our collaboration offer.
- * Closes ALL connections to the service
- *
- * FIXME: this should take an argument, and we should
- * have an explicit 'connect' API which returns an opaque
- * connection handle.  Avoid (globals) in the library!
- * @deprecated in this form
- */
-void
-GNUNET_SCALARPRODUCT_disconnect ();
-
-
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif

Modified: gnunet/src/scalarproduct/gnunet-scalarproduct.c
===================================================================
--- gnunet/src/scalarproduct/gnunet-scalarproduct.c     2014-05-07 07:32:26 UTC 
(rev 33176)
+++ gnunet/src/scalarproduct/gnunet-scalarproduct.c     2014-05-07 08:21:49 UTC 
(rev 33177)
@@ -44,12 +44,12 @@
   /**
    * the session key identifying this computation
    */
-  struct GNUNET_HashCode key;
+  struct GNUNET_HashCode session_key;
 
   /**
    * PeerID we want to compute a scalar product with
    */
-  struct GNUNET_PeerIdentity peer;
+  struct GNUNET_PeerIdentity peer_id;
 };
 
 /**
@@ -60,7 +60,7 @@
 /**
  * Option -p: destination peer identity for checking message-ids with
  */
-static char *input_key;
+static char *input_session_key;
 
 /**
  * Option -e: vector to calculate a scalarproduct with
@@ -68,16 +68,15 @@
 static char *input_elements;
 
 /**
- * Option -m: message-ids to calculate a scalarproduct with
+ * Global return value
  */
-static char *input_mask;
+static int ret = -1;
 
 /**
- * Global return value
+ * our Scalarproduct Computation handle
  */
-static int ret = -1;
+struct GNUNET_SCALARPRODUCT_ComputationHandle * computation;
 
-
 /**
  * Callback called if we are initiating a new computation session
  *
@@ -96,29 +95,30 @@
     ret = 0;
     LOG (GNUNET_ERROR_TYPE_INFO,
          "Session %s concluded.\n",
-         GNUNET_h2s (&closure->key));
+         GNUNET_h2s (&closure->session_key));
     break;
   case GNUNET_SCALARPRODUCT_Status_InvalidResponse:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s failed: invalid response\n",
-         GNUNET_h2s (&closure->key));
+         GNUNET_h2s (&closure->session_key));
     break;
   case GNUNET_SCALARPRODUCT_Status_Failure:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s failed: service failure\n",
-         GNUNET_h2s (&closure->key));
+         GNUNET_h2s (&closure->session_key));
     break;
   case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s failed: service disconnect!\n",
-         GNUNET_h2s (&closure->key));
+         GNUNET_h2s (&closure->session_key));
     break;
   default:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s failed: return code %d\n",
-         GNUNET_h2s (&closure->key),
+         GNUNET_h2s (&closure->session_key),
          status);
   }
+  computation = NULL;
   GNUNET_SCHEDULER_shutdown();
 }
 
@@ -155,28 +155,29 @@
   case GNUNET_SCALARPRODUCT_Status_InvalidResponse:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s with peer %s failed: invalid response received\n",
-         GNUNET_h2s (&closure->key),
-         GNUNET_i2s (&closure->peer));
+         GNUNET_h2s (&closure->session_key),
+         GNUNET_i2s (&closure->peer_id));
     break;
   case GNUNET_SCALARPRODUCT_Status_Failure:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s with peer %s failed: API failure\n",
-         GNUNET_h2s (&closure->key),
-         GNUNET_i2s (&closure->peer));
+         GNUNET_h2s (&closure->session_key),
+         GNUNET_i2s (&closure->peer_id));
     break;
   case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s with peer %s was disconnected from service.\n",
-         GNUNET_h2s (&closure->key),
-         GNUNET_i2s (&closure->peer));
+         GNUNET_h2s (&closure->session_key),
+         GNUNET_i2s (&closure->peer_id));
     break;
   default:
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Session %s with peer %s failed: return code %d\n",
-         GNUNET_h2s (&closure->key),
-         GNUNET_i2s (&closure->peer),
+         GNUNET_h2s (&closure->session_key),
+         GNUNET_i2s (&closure->peer_id),
          status);
   }
+  computation = NULL;
   GNUNET_SCHEDULER_shutdown();
 }
 
@@ -191,7 +192,8 @@
 shutdown_task (void *cls,
                const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  GNUNET_SCALARPRODUCT_disconnect ();
+  if (NULL != computation)
+    GNUNET_SCALARPRODUCT_cancel(computation);
 }
 
 
@@ -211,11 +213,8 @@
 {
   char *begin = input_elements;
   char *end;
-  int32_t element;
   int i;
-  int32_t *elements;
-  unsigned char *mask;
-  uint32_t mask_bytes;
+  struct GNUNET_SCALARPRODUCT_Element * elements;
   uint32_t element_count = 0;
   struct ScalarProductCallbackClosure * closure;
 
@@ -226,27 +225,27 @@
     return;
   }
 
-  if (NULL == input_key)
+  if (NULL == input_session_key)
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          _ ("This program needs a session identifier for comparing 
vectors.\n"));
     return;
   }
 
-  if (1 > strnlen (input_key, sizeof (struct GNUNET_HashCode)))
+  if (1 > strnlen (input_session_key, sizeof (struct GNUNET_HashCode)))
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          _ ("Please give a session key for --input_key!\n"));
     return;
   }
   closure = GNUNET_new (struct ScalarProductCallbackClosure);
-  GNUNET_CRYPTO_hash (input_key, strlen (input_key), &closure->key);
+  GNUNET_CRYPTO_hash (input_session_key, strlen (input_session_key), 
&closure->session_key);
 
   if (input_peer_id &&
       (GNUNET_OK !=
        GNUNET_CRYPTO_eddsa_public_key_from_string (input_peer_id,
                                                    strlen (input_peer_id),
-                                                   (struct 
GNUNET_CRYPTO_EddsaPublicKey *) &closure->peer))) {
+                                                   (struct 
GNUNET_CRYPTO_EddsaPublicKey *) &closure->peer_id))) {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          _ ("Tried to set initiator mode, as peer ID was given. "
             "However, `%s' is not a valid peer identifier.\n"),
@@ -254,136 +253,75 @@
     return;
   }
 
-  /* Count input_elements_peer1, and put in elements_peer1 array */
-  do
-  {
-    // get the length of the current element
-    for (end = begin; *end && *end != ','; end++);
-
-    if (0 == *begin)
-    {
-      break;
-    }
-    else if (1 == sscanf (begin, "%" SCNd32 ",", &element))
-    {
-      //element in the middle
+  for (end = begin; 0 != *end; end++)
+    if (*end == ';')
       element_count++;
-      begin = end;
-      if (',' == *end)
-        begin += 1;
-    }
-    else
-    {
-      LOG (GNUNET_ERROR_TYPE_ERROR,
-           _ ("Could not convert `%s' to int32_t.\n"), begin);
-      return;
-    }
-  }
-  while (1);
-  if (0 == element_count)
-  {
+  if (0 == element_count) {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          _ ("Need elements to compute the vectorproduct, got none.\n"));
     return;
   }
-
-  begin = input_elements;
-  elements = GNUNET_malloc (sizeof (int32_t) * element_count);
-  element_count = 0;
-  /* Read input_elements_peer1, and put in elements_peer1 array */
-  do
+  
+  elements = (struct GNUNET_SCALARPRODUCT_Element *) 
+          GNUNET_malloc(sizeof(struct 
GNUNET_SCALARPRODUCT_Element)*element_count);
+  
+  for (i = 0; i < element_count;i++)
   {
-    // get the length of the current element
-    for (end = begin; *end && *end != ','; end++);
-
-    if (0 == *begin)
-    {
-      break;
+    struct GNUNET_SCALARPRODUCT_Element element;
+    char* separator=NULL;
+    
+    // get the length of the current key,value; tupel
+    for (end = begin; *end != ';'; end++)
+      if (*end == ',')
+        separator = end;
+    
+    // final element
+    if ((NULL == separator) 
+         || (begin == separator)
+             || (separator == end - 1 )) {
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           _ ("Malformed input, could not parse `%s'\n"), begin);
+      GNUNET_free(elements);
+      return;
     }
-    else if (1 == sscanf (begin, "%" SCNd32 ",", &elements[element_count]))
+    
+    // read the element's key
+    *separator = 0;
+    GNUNET_CRYPTO_hash (begin, strlen (begin), &element.key);
+    
+    // read the element's value
+    if (1 != sscanf (separator+1, "%" SCNd32 ";", &element.value))
     {
-      //element in the middle
-      element_count++;
-      begin = end;
-      if (',' == *end)
-        begin += 1;
-    }
-    else
-    {
       LOG (GNUNET_ERROR_TYPE_ERROR,
            _ ("Could not convert `%s' to int32_t.\n"), begin);
+      GNUNET_free(elements);
       return;
     }
+    
+    elements[i]=element;
+    begin = end+1;
   }
-  while (1);
 
-  mask_bytes = element_count / 8 + ( (element_count % 8) ? 1 : 0);
-  mask = GNUNET_malloc ((element_count / 8) + 1);
-
-  /* Read input_mask_peer1 and read in mask_peer1 array */
-  if ((NULL != input_peer_id) && (NULL != input_mask))
-  {
-    begin = input_mask;
-    unsigned short mask_count = 0;
-
-    do
-    {
-      // get the length of the current element and replace , with null
-      for (end = begin; *end && *end != ','; end++);
-
-      if (1 == sscanf (begin, "%" SCNd32 ",", &element))
-      {
-        //element in the middle
-        begin = end + 1;
-      }
-      else if (*begin == 0)
-      {
-        break;
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_ERROR,
-             _ ("Could not convert `%s' to integer.\n"), begin);
-        return;
-      }
-
-      if (element)
-        mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8);
-      mask_count++;
-    }
-    while (mask_count < element_count);
-  }
-  else if (NULL != input_peer_id)
-    for (i = 0; i <= mask_bytes; i++)
-      mask[i] = UCHAR_MAX; // all 1's
-
-  if (input_peer_id &&
-      (NULL == GNUNET_SCALARPRODUCT_request (cfg,
-                                             &closure->key,
-                                             &closure->peer,
+  if (((NULL != input_peer_id) &&
+     (NULL == (computation = GNUNET_SCALARPRODUCT_start_computation (cfg,
+                                             &closure->session_key,
+                                             &closure->peer_id,
                                              elements, element_count,
-                                             mask, mask_bytes,
                                              &requester_callback,
-                                             (void *) &closure)))
-  {
-    GNUNET_free (elements);
-    GNUNET_free (mask);
-    return;
-  }
-
-  if ((NULL == input_peer_id) &&
-      (NULL == GNUNET_SCALARPRODUCT_response (cfg,
-                                              &closure->key,
+                                             (void *) &closure))))
+      ||
+      ((NULL == input_peer_id) &&
+      (NULL == (computation = GNUNET_SCALARPRODUCT_accept_computation (cfg,
+                                              &closure->session_key,
                                               elements, element_count,
                                               &responder_callback,
-                                              (void *) &closure)))
+                                              (void *) &closure)))))
   {
     GNUNET_free (elements);
-    GNUNET_free (mask);
     return;
   }
+
   GNUNET_free (elements);
-  GNUNET_free (mask);
   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                                 &shutdown_task,
                                 NULL);
@@ -403,18 +341,15 @@
 main (int argc, char *const *argv)
 {
   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'e', "elements", "\"val1,val2,...,valn\"",
+    {'e', "elements", "\"key1,val1;key2,val2;...,keyn,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 scalarproduct 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},
+      1, &GNUNET_GETOPT_set_string, &input_session_key},
     GNUNET_GETOPT_OPTION_END
   };
 

Modified: gnunet/src/scalarproduct/gnunet-service-scalarproduct.c
===================================================================
--- gnunet/src/scalarproduct/gnunet-service-scalarproduct.c     2014-05-07 
07:32:26 UTC (rev 33176)
+++ gnunet/src/scalarproduct/gnunet-service-scalarproduct.c     2014-05-07 
08:21:49 UTC (rev 33177)
@@ -32,6 +32,7 @@
 #include "gnunet_applications.h"
 #include "gnunet_protocols.h"
 #include "gnunet_scalarproduct_service.h"
+#include "gnunet_set_service.h"
 #include "scalarproduct.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct", __VA_ARGS__)
@@ -42,23 +43,6 @@
 
 
 /**
- * state a session can be in
- */
-enum SessionState
-{
-  CLIENT_REQUEST_RECEIVED,
-  WAITING_FOR_BOBS_CONNECT,
-  CLIENT_RESPONSE_RECEIVED,
-  WAITING_FOR_SERVICE_REQUEST,
-  WAITING_FOR_MULTIPART_TRANSMISSION,
-  WAITING_FOR_SERVICE_RESPONSE,
-  SERVICE_REQUEST_RECEIVED,
-  SERVICE_RESPONSE_RECEIVED,
-  FINALIZED
-};
-
-
-/**
  * role a peer in a session can assume
  */
 enum PeerRole
@@ -68,6 +52,15 @@
 };
 
 
+struct SortedValue
+{
+  struct SortedValue * next;
+  struct SortedValue * prev;
+  struct GNUNET_SCALARPRODUCT_Element * elem;
+  gcry_mpi_t val;
+};
+
+
 /**
  * A scalarproduct session which tracks:
  *
@@ -95,14 +88,9 @@
   /**
    * (hopefully) unique transaction ID
    */
-  struct GNUNET_HashCode key;
+  struct GNUNET_HashCode session_id;
 
   /**
-   * state of the session
-   */
-  enum SessionState state;
-
-  /**
    * Alice or Bob's peerID
    */
   struct GNUNET_PeerIdentity peer;
@@ -123,47 +111,63 @@
   uint32_t total;
 
   /**
-   * how many elements actually are used after applying the mask
+   * how many elements we used for intersection
    */
-  uint32_t used;
+  uint32_t intersected_elements_count;
 
   /**
-   * already transferred elements (sent/received) for multipart messages, less 
or equal than used_element_count for
+   * all non-0-value'd elements transmitted to us
    */
-  uint32_t transferred;
+  struct GNUNET_CONTAINER_MultiHashMap * intersected_elements;
 
   /**
-   * index of the last transferred element for multipart messages
+   * how many elements actually are used for the scalar product
    */
-  uint32_t last_processed;
+  uint32_t used_elements_count;
 
   /**
-   * how many bytes the mask is long.
-   * just for convenience so we don't have to re-re-re calculate it each time
+   * already transferred elements (sent/received) for multipart messages, less 
or equal than used_element_count for
    */
-  uint32_t mask_length;
+  uint32_t transferred_element_count;
 
   /**
-   * all the vector elements we received
+   * Set of elements for which will conduction an intersection. 
+   * the resulting elements are then used for computing the scalar product.
    */
-  int32_t * vector;
+  struct GNUNET_SET_Handle * intersection_set;
 
   /**
-   * mask of which elements to check
+   * Set of elements for which will conduction an intersection. 
+   * the resulting elements are then used for computing the scalar product.
    */
-  unsigned char * mask;
+  struct GNUNET_SET_OperationHandle * intersection_op;
 
   /**
+   * Handle to Alice's Intersection operation listening for Bob
+   */
+  struct GNUNET_SET_ListenHandle * intersection_listen;
+
+  /**
    * Public key of the remote service, only used by bob
    */
-  struct GNUNET_CRYPTO_PaillierPublicKey * remote_pubkey;
+  struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey;
 
   /**
-   * ai(Alice) after applying the mask
+   * DLL for sorting elements after intersection
    */
-  gcry_mpi_t * a;
+  struct SortedValue * a_head;
 
   /**
+   * a(Alice)
+   */
+  struct SortedValue * a_tail;
+
+  /**
+   * a(Alice)
+   */
+  gcry_mpi_t * sorted_elements;
+
+  /**
    * E(ai)(Bob) after applying the mask
    */
   struct GNUNET_CRYPTO_PaillierCiphertext * e_a;
@@ -217,11 +221,6 @@
    * Handle to a task that sends a msg to the our client
    */
   GNUNET_SCHEDULER_TaskIdentifier client_notification_task;
-
-  /**
-   * Handle to a task that sends a msg to the our peer
-   */
-  GNUNET_SCHEDULER_TaskIdentifier service_request_task;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -238,7 +237,7 @@
  * @param cls the associated service session
  */
 static void
-prepare_service_request_multipart (void *cls);
+prepare_alices_cyrptodata_message_multipart (void *cls);
 
 /**
  * Send a multi part chunk of a service response from bob to alice.
@@ -247,7 +246,7 @@
  * @param cls the associated service session
  */
 static void
-prepare_service_response_multipart (void *cls);
+prepare_bobs_cryptodata_message_multipart (void *cls);
 
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -256,6 +255,11 @@
 
 
 /**
+ * Gnunet configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle * cfg;
+
+/**
  * Handle to the core service (NULL until we've connected to it).
  */
 static struct GNUNET_MESH_Handle *my_mesh;
@@ -350,7 +354,7 @@
  * 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 cls the session containing 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
@@ -358,43 +362,42 @@
 static size_t
 do_send_message (void *cls, size_t size, void *buf)
 {
-  struct ServiceSession * session = cls;
+  struct ServiceSession * s = cls;
   uint16_t type;
 
   GNUNET_assert (buf);
 
-  if (ntohs (session->msg->size) != size) {
+  if (ntohs (s->msg->size) != size) {
     GNUNET_break (0);
     return 0;
   }
 
-  type = ntohs (session->msg->type);
-  memcpy (buf, session->msg, size);
+  type = ntohs (s->msg->type);
+  memcpy (buf, s->msg, size);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Sent a message of type %hu.\n",
               type);
-  GNUNET_free (session->msg);
-  session->msg = NULL;
+  GNUNET_free (s->msg);
+  s->msg = NULL;
 
   switch (type)
   {
-  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT:
-    session->state = FINALIZED;
-    session->client_transmit_handle = NULL;
+  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT:
+    s->client_transmit_handle = NULL;
     break;
 
-  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB:
-  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART:
-    session->service_transmit_handle = NULL;
-    if (session->state == WAITING_FOR_MULTIPART_TRANSMISSION)
-      prepare_service_request_multipart (session);
+  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA:
+  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART:
+    s->service_transmit_handle = NULL;
+    if (s->used_elements_count != s->transferred_element_count)
+      prepare_alices_cyrptodata_message_multipart (s);
     break;
 
-  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE:
-  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE_MULTIPART:
-    session->service_transmit_handle = NULL;
-    if (session->state == WAITING_FOR_MULTIPART_TRANSMISSION)
-      prepare_service_response_multipart (session);
+  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA:
+  case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART:
+    s->service_transmit_handle = NULL;
+    if (s->used_elements_count != s->transferred_element_count)
+      prepare_bobs_cryptodata_message_multipart (s);
     break;
 
   default:
@@ -406,31 +409,12 @@
 
 
 /**
- * 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 (uint32_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;
-}
-
-
-/**
  * 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 key - the key we want to search for
  * @param element_count - the total element count of the dataset 
(session->total)
- * @param state - a pointer to the state the session should be in, NULL to 
ignore
  * @param peerid - a pointer to the peer ID of the associated peer, NULL to 
ignore
  * @return a pointer to a matching session, or NULL
  */
@@ -438,23 +422,19 @@
 find_matching_session (struct ServiceSession * tail,
                        const struct GNUNET_HashCode * key,
                        uint32_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)))
+    if ((!memcmp (&curr->session_id, key, sizeof (struct GNUNET_HashCode)))
         && (curr->total == 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;
-      }
+      // 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;
     }
   }
 
@@ -470,22 +450,42 @@
 static void
 free_session_variables (struct ServiceSession * session)
 {
-  unsigned int i;
-
-  if (session->a) {
-    for (i = 0; i < session->used; i++)
-      if (session->a[i]) gcry_mpi_release (session->a[i]);
-    GNUNET_free (session->a);
-    session->a = NULL;
+  while (NULL != session->a_head) {
+    struct SortedValue * e = session->a_head;
+    GNUNET_free (e->elem);
+    gcry_mpi_release (e->val);
+    GNUNET_CONTAINER_DLL_remove (session->a_head, session->a_tail, e);
+    GNUNET_free (e);
   }
   if (session->e_a) {
     GNUNET_free (session->e_a);
     session->e_a = NULL;
   }
-  if (session->mask) {
-    GNUNET_free (session->mask);
-    session->mask = NULL;
+  if (session->sorted_elements) {
+    GNUNET_free (session->sorted_elements);
+    session->sorted_elements = NULL;
   }
+  if (session->intersected_elements) {
+    GNUNET_CONTAINER_multihashmap_destroy (session->intersected_elements);
+    //elements are freed independently in session->a_head/tail
+    session->intersected_elements = NULL;
+  }
+  if (session->intersection_listen) {
+    GNUNET_SET_listen_cancel (session->intersection_listen);
+    session->intersection_listen = NULL;
+  }
+  if (session->intersection_op) {
+    GNUNET_SET_operation_cancel (session->intersection_op);
+    session->intersection_op = NULL;
+  }
+  if (session->intersection_set) {
+    GNUNET_SET_destroy (session->intersection_set);
+    session->intersection_set = NULL;
+  }
+  if (session->msg) {
+    GNUNET_free (session->msg);
+    session->msg = NULL;
+  }
   if (session->r) {
     GNUNET_free (session->r);
     session->r = NULL;
@@ -506,14 +506,6 @@
     gcry_mpi_release (session->product);
     session->product = NULL;
   }
-  if (session->remote_pubkey) {
-    GNUNET_free (session->remote_pubkey);
-    session->remote_pubkey = NULL;
-  }
-  if (session->vector) {
-    GNUNET_free_non_null (session->vector);
-    session->s = NULL;
-  }
 }
 ///////////////////////////////////////////////////////////////////////////////
 //                      Event and Message Handlers
@@ -547,21 +539,17 @@
     return;
   GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
 
-  if (!(session->role == BOB && session->state == FINALIZED)) {
+  if (!(session->role == BOB && 0/*//TODO: if session concluded*/)) {
     //we MUST terminate any client message underway
     if (session->service_transmit_handle && session->channel)
       GNUNET_MESH_notify_transmit_ready_cancel 
(session->service_transmit_handle);
-    if (session->channel && session->state == WAITING_FOR_SERVICE_RESPONSE)
+    if (session->channel && 0/* //TODO: waiting for service response */)
       GNUNET_MESH_channel_destroy (session->channel);
   }
   if (GNUNET_SCHEDULER_NO_TASK != session->client_notification_task) {
     GNUNET_SCHEDULER_cancel (session->client_notification_task);
     session->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
   }
-  if (GNUNET_SCHEDULER_NO_TASK != session->service_request_task) {
-    GNUNET_SCHEDULER_cancel (session->service_request_task);
-    session->service_request_task = GNUNET_SCHEDULER_NO_TASK;
-  }
   if (NULL != session->client_transmit_handle) {
     GNUNET_SERVER_notify_transmit_ready_cancel 
(session->client_transmit_handle);
     session->client_transmit_handle = NULL;
@@ -590,13 +578,13 @@
   session->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
 
   msg = GNUNET_new (struct GNUNET_SCALARPRODUCT_client_response);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT);
-  memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
+  memcpy (&msg->key, &session->session_id, sizeof (struct GNUNET_HashCode));
   memcpy (&msg->peer, &session->peer, sizeof ( struct GNUNET_PeerIdentity));
   msg->header.size = htons (sizeof (struct 
GNUNET_SCALARPRODUCT_client_response));
   // signal error if not signalized, positive result-range field but zero 
length.
   msg->product_length = htonl (0);
-  msg->range = (session->state == FINALIZED) ? 0 : -1;
+  msg->range = (session /* //TODO: if finalized */) ? 0 : -1;
 
   session->msg = &msg->header;
 
@@ -616,103 +604,77 @@
     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));
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Sending session-end notification 
to client (%p) for session %s\n"), &session->client, GNUNET_h2s 
(&session->session_id));
 
   free_session_variables (session);
 }
 
 
 /**
- * prepare the response we will send to alice or bobs' clients.
- * in Bobs case the product will be NULL.
+ * Executed by Alice, fills in a service-request message and sends it to the 
given peer
  *
- * @param cls the session associated with our client.
- * @param tc the task context handed to us by the scheduler, unused
+ * @param cls the session associated with this request
  */
 static void
-prepare_client_response (void *cls,
-                         const struct GNUNET_SCHEDULER_TaskContext *tc)
+prepare_alices_cyrptodata_message (void *cls)
 {
   struct ServiceSession * session = cls;
-  struct GNUNET_SCALARPRODUCT_client_response * msg;
-  unsigned char * product_exported = NULL;
-  size_t product_length = 0;
-  uint32_t msg_length = 0;
-  int8_t range = -1;
-  gcry_error_t rc;
-  int sign;
+  struct GNUNET_SCALARPRODUCT_alices_cryptodata_message * msg;
+  struct GNUNET_CRYPTO_PaillierCiphertext * payload;
+  unsigned int i;
+  uint32_t msg_length;
+  gcry_mpi_t a;
 
-  session->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new channel to 
peer (%s)!\n"), GNUNET_i2s (&session->peer));
 
-  if (session->product) {
-    gcry_mpi_t value = gcry_mpi_new (0);
+  msg_length = sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message)
+          +session->used_elements_count * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext);
 
-    sign = gcry_mpi_cmp_ui (session->product, 0);
-    // libgcrypt can not handle a print of a negative number
-    // if (a->sign) return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it 
yet. */
-    if (0 > sign) {
-      gcry_mpi_sub (value, value, session->product);
-    }
-    else if (0 < sign) {
-      range = 1;
-      gcry_mpi_add (value, value, session->product);
-    }
-    else
-      range = 0;
-
-    gcry_mpi_release (session->product);
-    session->product = NULL;
-
-    // get representation as string
-    if (range
-        && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
-                                        &product_exported,
-                                        &product_length,
-                                        value)))) {
-      LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
-      product_length = 0;
-      range = -1; // signal error with product-length = 0 and range = -1
-    }
-    gcry_mpi_release (value);
+  if (GNUNET_SERVER_MAX_MESSAGE_SIZE > msg_length) {
+    session->transferred_element_count = session->used_elements_count;
   }
+  else {
+    //create a multipart msg, first we calculate a new msg size for the head 
msg
+    session->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - 
sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message))
+            / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
+    msg_length = sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message)
+            +session->transferred_element_count * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext);
+  }
 
-  msg_length = sizeof (struct GNUNET_SCALARPRODUCT_client_response) 
+product_length;
   msg = GNUNET_malloc (msg_length);
-  msg->key = session->key;
-  msg->peer = session->peer;
-  if (product_exported != NULL) {
-    memcpy (&msg[1], product_exported, product_length);
-    GNUNET_free (product_exported);
-  }
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT);
   msg->header.size = htons (msg_length);
-  msg->range = range;
-  msg->product_length = htonl (product_length);
+  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA);
+  msg->contained_element_count = htonl (session->transferred_element_count);
 
+  // fill in the payload
+  payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
+
+  // now copy over the sorted element vector
+  a = gcry_mpi_new (0);
+  for (i = 0; i < session->transferred_element_count; i++) {
+    gcry_mpi_add (a, session->sorted_elements[i], my_offset);
+    GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i]);
+  }
+  gcry_mpi_release (a);
+
   session->msg = (struct GNUNET_MessageHeader *) msg;
-  //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,
-                                               session);
-  if (NULL == session->client_transmit_handle) {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _ ("Could not send message to client (%p)!\n"),
-                session->client);
-    session->client = NULL;
-    // callback was not called!
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n"));
+
+  //transmit via mesh messaging
+  session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready 
(session->channel, GNUNET_YES,
+                                                                        
GNUNET_TIME_UNIT_FOREVER_REL,
+                                                                        
msg_length,
+                                                                        
&do_send_message,
+                                                                        
session);
+  if (NULL == session->service_transmit_handle) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send message to 
channel!\n"));
     GNUNET_free (msg);
     session->msg = NULL;
+    session->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session);
+    return;
   }
-  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_variables (session);
 }
 
 
@@ -723,7 +685,7 @@
  * @param cls the associated service session
  */
 static void
-prepare_service_response_multipart (void *cls)
+prepare_bobs_cryptodata_message_multipart (void *cls)
 {
   struct ServiceSession * session = cls;
   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
@@ -734,7 +696,7 @@
   uint32_t todo_count;
 
   msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message);
-  todo_count = session->used - session->transferred;
+  todo_count = session->used_elements_count - 
session->transferred_element_count;
 
   if (todo_count > MULTIPART_ELEMENT_CAPACITY / 2)
     // send the currently possible maximum chunk, we always transfer both 
permutations
@@ -742,17 +704,17 @@
 
   msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) 
* 2;
   msg = GNUNET_malloc (msg_length);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART);
+  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART);
   msg->header.size = htons (msg_length);
-  msg->multipart_element_count = htonl (todo_count);
+  msg->contained_element_count = htonl (todo_count);
 
   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
-  for (i = session->transferred, j=0; i < session->transferred + todo_count; 
i++) {
+  for (i = session->transferred_element_count, j = 0; i < 
session->transferred_element_count + todo_count; i++) {
     //r[i][p] and r[i][q]
     memcpy (&payload[j++], &session->r[i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
     memcpy (&payload[j++], &session->r_prime[i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
   }
-  session->transferred += todo_count;
+  session->transferred_element_count += todo_count;
   session->msg = (struct GNUNET_MessageHeader *) msg;
   session->service_transmit_handle =
           GNUNET_MESH_notify_transmit_ready (session->channel,
@@ -764,19 +726,17 @@
   //disconnect our client
   if (NULL == session->service_transmit_handle) {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response 
message via mesh!)\n"));
-    session->state = FINALIZED;
 
     session->response->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                       session->response);
     return;
   }
-  if (session->transferred != session->used)
+  if (session->transferred_element_count != session->used_elements_count) {
     // more multiparts
-    session->state = WAITING_FOR_MULTIPART_TRANSMISSION;
+  }
   else {
     // final part
-    session->state = FINALIZED;
     GNUNET_free (session->r_prime);
     GNUNET_free (session->r);
     session->r_prime = NULL;
@@ -795,12 +755,13 @@
  *     S': $S' := E_A(sum r_i^2)$
  *
  * @param session  the associated requesting session with alice
- * @return #GNUNET_NO if we could not send our message
- *         #GNUNET_OK if the operation succeeded
  */
-static int
-prepare_service_response (struct ServiceSession * session)
+static void
+prepare_bobs_cryptodata_message (void *cls,
+                          const struct GNUNET_SCHEDULER_TaskContext
+                          * tc)
 {
+  struct ServiceSession * session = (struct ServiceSession *) cls;
   struct GNUNET_SCALARPRODUCT_service_response * msg;
   uint32_t msg_length = 0;
   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
@@ -810,22 +771,21 @@
           + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); // s, stick
 
   if (GNUNET_SERVER_MAX_MESSAGE_SIZE >
-      msg_length + 2 * session->used * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext)) { //r, r'
-    msg_length += 2 * session->used * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext);
-    session->transferred = session->used;
+      msg_length + 2 * session->used_elements_count * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext)) { //r, r'
+    msg_length += 2 * session->used_elements_count * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext);
+    session->transferred_element_count = session->used_elements_count;
   }
   else
-    session->transferred = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - msg_length) /
+    session->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - 
msg_length) /
     (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2);
 
   msg = GNUNET_malloc (msg_length);
-
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE);
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA);
   msg->header.size = htons (msg_length);
   msg->total_element_count = htonl (session->total);
-  msg->used_element_count = htonl (session->used);
-  msg->contained_element_count = htonl (session->transferred);
-  memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode));
+  msg->used_element_count = htonl (session->used_elements_count);
+  msg->contained_element_count = htonl (session->transferred_element_count);
+  memcpy (&msg->key, &session->session_id, sizeof (struct GNUNET_HashCode));
 
   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
   memcpy (&payload[0], session->s, sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
@@ -834,12 +794,13 @@
   session->s_prime = NULL;
   GNUNET_free (session->s);
   session->s = NULL;
-  
+
+  payload = &payload[2];
   // convert k[][]
-  for (i = 0; i < session->transferred; i++) {
+  for (i = 0; i < session->transferred_element_count; i++) {
     //k[i][p] and k[i][q]
-    memcpy (&payload[2 + i*2], &session->r[i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
-    memcpy (&payload[3 + i*2], &session->r_prime[i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+    memcpy (&payload[i * 2], &session->r[i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+    memcpy (&payload[i * 2 + 1], &session->r_prime[i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
   }
 
   session->msg = (struct GNUNET_MessageHeader *) msg;
@@ -853,26 +814,21 @@
   //disconnect our client
   if (NULL == session->service_transmit_handle) {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response 
message via mesh!)\n"));
-    session->state = FINALIZED;
 
     session->response->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                       session->response);
-    return GNUNET_NO;
   }
-  if (session->transferred != session->used)
+  if (session->transferred_element_count != session->used_elements_count) {
     // multipart
-    session->state = WAITING_FOR_MULTIPART_TRANSMISSION;
+  }
   else {
     //singlepart
-    session->state = FINALIZED;
     GNUNET_free (session->r);
     session->r = NULL;
     GNUNET_free (session->r_prime);
     session->r_prime = NULL;
   }
-
-  return GNUNET_OK;
 }
 
 
@@ -885,17 +841,11 @@
  *     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)
+static void
+compute_service_response (struct ServiceSession * session)
 {
   int i;
-  int j;
-  int ret = GNUNET_SYSERR;
   unsigned int * p;
   unsigned int * q;
   uint32_t count;
@@ -907,34 +857,20 @@
   struct GNUNET_CRYPTO_PaillierCiphertext * r_prime;
   struct GNUNET_CRYPTO_PaillierCiphertext * s;
   struct GNUNET_CRYPTO_PaillierCiphertext * s_prime;
-  uint32_t value;
 
-  count = request->used;
-  a = request->e_a;
-  b = initialize_mpi_vector (count);
+  count = session->used_elements_count;
+  a = session->e_a;
+  b = session->sorted_elements;
   q = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count);
   p = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count);
-  rand = initialize_mpi_vector (count);
+
+  for (i = 0; i < count; i++)
+    GNUNET_assert (NULL != (rand[i] = gcry_mpi_new (0)));
   r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
   r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 
count);
   s = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
   s_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
 
-  // convert responder session to from long to mpi
-  for (i = 0, j = 0; i < response->total && 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])
-        gcry_mpi_sub_ui (b[j], b[j], value);
-      else
-        b[j] = gcry_mpi_set_ui (b[j], value);
-      j++;
-    }
-  }
-  GNUNET_free (response->vector);
-  response->vector = NULL;
-
   for (i = 0; i < count; i++) {
     int32_t svalue;
 
@@ -959,13 +895,13 @@
     // E(S - r_pi - b_pi)
     gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
     gcry_mpi_sub (tmp, tmp, b[p[i]]);
-    GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey,
+    GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
                                     tmp,
                                     2,
                                     &r[i]);
 
     // E(S - r_pi - b_pi) * E(S + a_pi) ==  E(2*S + a - r - b)
-    GNUNET_CRYPTO_paillier_hom_add (request->remote_pubkey,
+    GNUNET_CRYPTO_paillier_hom_add (&session->remote_pubkey,
                                     &r[i],
                                     &a[p[i]],
                                     &r[i]);
@@ -975,13 +911,13 @@
   for (i = 0; i < count; i++) {
     // E(S - r_qi)
     gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
-    GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey,
+    GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt 
(&session->remote_pubkey,
                                                         tmp,
                                                         2,
                                                         &r_prime[i]));
 
     // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
-    GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (request->remote_pubkey,
+    GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add 
(&session->remote_pubkey,
                                                         &r_prime[i],
                                                         &a[q[i]],
                                                         &r_prime[i]));
@@ -989,7 +925,7 @@
 
   // Calculate S' =  E(SUM( r_i^2 ))
   tmp = compute_square_sum (rand, count);
-  GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey,
+  GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
                                   tmp,
                                   1,
                                   s_prime);
@@ -998,43 +934,356 @@
   for (i = 0; i < count; i++)
     gcry_mpi_add (rand[i], rand[i], b[i]);
   tmp = compute_square_sum (rand, count);
-  GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey,
+  GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
                                   tmp,
                                   1,
                                   s);
 
-  request->r = r;
-  request->r_prime = r_prime;
-  request->s = s;
-  request->s_prime = s_prime;
-  request->response = response;
+  session->r = r;
+  session->r_prime = r_prime;
+  session->s = s;
+  session->s_prime = s_prime;
 
   // release rand, b and a
   for (i = 0; i < count; i++) {
     gcry_mpi_release (rand[i]);
     gcry_mpi_release (b[i]);
-    gcry_mpi_release (request->a[i]);
   }
   gcry_mpi_release (tmp);
-  GNUNET_free (request->a);
-  request->a = NULL;
+  GNUNET_free (session->e_a);
+  session->e_a = NULL;
   GNUNET_free (p);
   GNUNET_free (q);
   GNUNET_free (b);
   GNUNET_free (rand);
 
   // copy the r[], r_prime[], S and Stick into a new message, 
prepare_service_response frees these
-  if (GNUNET_YES != prepare_service_response (request))
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Failed to communicate with `%s', 
scalar product calculation aborted.\n"),
-                GNUNET_i2s (&request->peer));
+  GNUNET_SCHEDULER_add_now (&prepare_bobs_cryptodata_message, session);
+}
+
+
+/**
+ * Iterator over all hash map entries in session->intersected_elements.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return #GNUNET_YES if we should continue to
+ *         iterate,
+ *         #GNUNET_NO if not.
+ */
+int
+cb_insert_element_sorted (void *cls,
+                          const struct GNUNET_HashCode *key,
+                          void *value)
+{
+  struct ServiceSession * session = (struct ServiceSession*) cls;
+  struct SortedValue * e = GNUNET_new (struct SortedValue);
+  struct SortedValue * o = session->a_head;
+
+  e->elem = value;
+  e->val = gcry_mpi_new (0);
+  if (0 > e->elem->value)
+    gcry_mpi_sub_ui (e->val, e->val, abs (e->elem->value));
   else
-    ret = GNUNET_OK;
+    gcry_mpi_add_ui (e->val, e->val, e->elem->value);
 
-  return ret;
+  // insert as first element with the lowest key
+  if (NULL == session->a_head
+      || (0 <= GNUNET_CRYPTO_hash_cmp (&session->a_head->elem->key, 
&e->elem->key))) {
+    GNUNET_CONTAINER_DLL_insert (session->a_head, session->a_tail, e);
+    return GNUNET_YES;
+  }
+  // insert as last element with the highest key
+  if (0 >= GNUNET_CRYPTO_hash_cmp (&session->a_tail->elem->key, 
&e->elem->key)) {
+    GNUNET_CONTAINER_DLL_insert_tail (session->a_head, session->a_tail, e);
+    return GNUNET_YES;
+  }
+  // insert before the first higher/equal element
+  do {
+    if (0 <= GNUNET_CRYPTO_hash_cmp (&o->elem->key, &e->elem->key)) {
+      GNUNET_CONTAINER_DLL_insert_before (session->a_head, session->a_tail, o, 
e);
+      return GNUNET_YES;
+    }
+    o = o->next;
+  }
+  while (NULL != o);
+  // broken DLL
+  GNUNET_assert (0);
+  return GNUNET_NO;
 }
 
 
 /**
+ * Callback for set operation results. Called for each element
+ * in the result set.
+ *
+ * @param cls closure
+ * @param element a result element, only valid if status is 
#GNUNET_SET_STATUS_OK
+ * @param status see `enum GNUNET_SET_Status`
+ */
+static void
+cb_intersection_element_removed (void *cls,
+                                 const struct GNUNET_SET_Element *element,
+                                 enum GNUNET_SET_Status status)
+{
+  struct ServiceSession * session = (struct ServiceSession*) cls;
+  struct GNUNET_SCALARPRODUCT_Element * se;
+  int i;
+
+  switch (status)
+  {
+  case GNUNET_SET_STATUS_OK:
+    //this element has been removed from the set
+    se = GNUNET_CONTAINER_multihashmap_get (session->intersected_elements,
+                                            element->data);
+
+    GNUNET_CONTAINER_multihashmap_remove (session->intersected_elements,
+                                          element->data,
+                                          se);
+    session->used_elements_count--;
+    return;
+
+  case GNUNET_SET_STATUS_DONE:
+    if (2 > session->used_elements_count) {
+      // failed! do not leak information about our single remaining element!
+      // continue after the loop
+      break;
+    }
+
+    GNUNET_CONTAINER_multihashmap_iterate (session->intersected_elements,
+                                           &cb_insert_element_sorted,
+                                           session);
+
+    session->sorted_elements = GNUNET_malloc (session->used_elements_count * 
sizeof (gcry_mpi_t));
+    for (i = 0; NULL != session->a_head; i++) {
+      struct SortedValue* a = session->a_head;
+      if (i > session->used_elements_count) {
+        GNUNET_assert (0);
+        return;
+      }
+      session->sorted_elements[i] = a->val;
+      GNUNET_CONTAINER_DLL_remove (session->a_head, session->a_tail, a);
+      GNUNET_free (a->elem);
+    }
+    if (i != session->used_elements_count)
+      GNUNET_assert (0);
+
+    if (ALICE == session->role) {
+      prepare_alices_cyrptodata_message (session);
+      return;
+    }
+    else {
+      if (session->used_elements_count == session->transferred_element_count)
+        compute_service_response (session);
+
+      return;
+    }
+  default:
+    break;
+  }
+
+  //failed if we go here
+  if (ALICE == session->role) {
+    session->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session);
+  }
+  else {
+    //TODO: Fail service session, exit tunnel
+
+
+    session->response->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session->response);
+
+  }
+}
+
+
+/**
+ * Called when another peer wants to do a set operation with the
+ * local peer. If a listen error occurs, the @a request is NULL.
+ *
+ * @param cls closure
+ * @param other_peer the other peer
+ * @param context_msg message with application specific information from
+ *        the other peer
+ * @param request request from the other peer (never NULL), use 
GNUNET_SET_accept()
+ *        to accept it, otherwise the request will be refused
+ *        Note that we can't just return value from the listen callback,
+ *        as it is also necessary to specify the set we want to do the
+ *        operation with, whith sometimes can be derived from the context
+ *        message. It's necessary to specify the timeout.
+ */
+static void
+cb_intersection_request_alice (void *cls,
+                               const struct GNUNET_PeerIdentity *other_peer,
+                               const struct GNUNET_MessageHeader *context_msg,
+                               struct GNUNET_SET_Request *request)
+{
+  struct ServiceSession * session = (struct ServiceSession *) cls;
+
+  // check the peer-id, the app-id=session-id is compared by SET
+  if (0 != memcmp (&session->peer, &other_peer, sizeof (struct 
GNUNET_PeerIdentity)))
+    return;
+
+  session->intersection_op = GNUNET_SET_accept (request,
+                                                GNUNET_SET_RESULT_REMOVED,
+                                                
cb_intersection_element_removed,
+                                                session);
+
+  if (NULL == session->intersection_op) {
+    session->response->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session);
+    return;
+  }
+  if (GNUNET_OK != GNUNET_SET_commit (session->intersection_op, 
session->intersection_set)) {
+    session->response->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session);
+    return;
+  }
+  session->intersection_set = NULL;
+  session->intersection_listen = NULL;
+}
+
+
+/**
+ * prepare the response we will send to alice or bobs' clients.
+ * in Bobs case the product will be NULL.
+ *
+ * @param cls the session associated with our client.
+ * @param tc the task context handed to us by the scheduler, unused
+ */
+static void
+prepare_client_response (void *cls,
+                         const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct ServiceSession * session = cls;
+  struct GNUNET_SCALARPRODUCT_client_response * msg;
+  unsigned char * product_exported = NULL;
+  size_t product_length = 0;
+  uint32_t msg_length = 0;
+  int8_t range = -1;
+  gcry_error_t rc;
+  int sign;
+
+  session->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
+
+  if (session->product) {
+    gcry_mpi_t value = gcry_mpi_new (0);
+
+    sign = gcry_mpi_cmp_ui (session->product, 0);
+    // libgcrypt can not handle a print of a negative number
+    // if (a->sign) return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it 
yet. */
+    if (0 > sign) {
+      gcry_mpi_sub (value, value, session->product);
+    }
+    else if (0 < sign) {
+      range = 1;
+      gcry_mpi_add (value, value, session->product);
+    }
+    else
+      range = 0;
+
+    gcry_mpi_release (session->product);
+    session->product = NULL;
+
+    // get representation as string
+    if (range
+        && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
+                                        &product_exported,
+                                        &product_length,
+                                        value)))) {
+      LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
+      product_length = 0;
+      range = -1; // signal error with product-length = 0 and range = -1
+    }
+    gcry_mpi_release (value);
+  }
+
+  msg_length = sizeof (struct GNUNET_SCALARPRODUCT_client_response) 
+product_length;
+  msg = GNUNET_malloc (msg_length);
+  msg->key = session->session_id;
+  msg->peer = session->peer;
+  if (product_exported != NULL) {
+    memcpy (&msg[1], product_exported, product_length);
+    GNUNET_free (product_exported);
+  }
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
+  msg->header.size = htons (msg_length);
+  msg->range = range;
+  msg->product_length = htonl (product_length);
+
+  session->msg = (struct GNUNET_MessageHeader *) msg;
+  //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,
+                                               session);
+  if (NULL == session->client_transmit_handle) {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _ ("Could not send message to client (%p)!\n"),
+                session->client);
+    session->client = NULL;
+    // callback was not called!
+    GNUNET_free (msg);
+    session->msg = NULL;
+  }
+  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->session_id));
+  free_session_variables (session);
+}
+
+
+/**
+ * Executed by Alice, fills in a service-request message and sends it to the 
given peer
+ *
+ * @param session the session associated with this request
+ */
+static void
+prepare_alices_computation_request (struct ServiceSession * session)
+{
+  struct GNUNET_SCALARPRODUCT_service_request * msg;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new channel to 
peer (%s)!\n"), GNUNET_i2s (&session->peer));
+
+  msg = GNUNET_new (struct GNUNET_SCALARPRODUCT_service_request);
+  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA);
+  msg->total_element_count = htonl (session->used_elements_count);
+  memcpy (&msg->session_id, &session->session_id, sizeof (struct 
GNUNET_HashCode));
+  msg->header.size = htons (sizeof (struct 
GNUNET_SCALARPRODUCT_service_request));
+
+  session->msg = (struct GNUNET_MessageHeader *) msg;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n"));
+
+  //transmit via mesh messaging
+  session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready 
(session->channel, GNUNET_YES,
+                                                                        
GNUNET_TIME_UNIT_FOREVER_REL,
+                                                                        sizeof 
(struct GNUNET_SCALARPRODUCT_service_request),
+                                                                        
&do_send_message,
+                                                                        
session);
+  if (!session->service_transmit_handle) {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send message to 
channel!\n"));
+    GNUNET_free (msg);
+    session->msg = NULL;
+    session->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session);
+    return;
+  }
+}
+
+
+/**
  * Send a multi part chunk of a service request from alice to bob.
  * This element only contains a part of the elements-vector (session->a[]),
  * mask and public key set have to be contained within the first message
@@ -1044,56 +1293,39 @@
  * @param cls the associated service session
  */
 static void
-prepare_service_request_multipart (void *cls)
+prepare_alices_cyrptodata_message_multipart (void *cls)
 {
   struct ServiceSession * session = cls;
   struct GNUNET_SCALARPRODUCT_multipart_message * msg;
   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
   unsigned int i;
-  unsigned int j;
   uint32_t msg_length;
   uint32_t todo_count;
   gcry_mpi_t a;
-  uint32_t value;
 
   msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message);
-  todo_count = session->used - session->transferred;
+  todo_count = session->used_elements_count - 
session->transferred_element_count;
 
   if (todo_count > MULTIPART_ELEMENT_CAPACITY)
     // send the currently possible maximum chunk
     todo_count = MULTIPART_ELEMENT_CAPACITY;
 
-  msg_length += todo_count * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
+  msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
   msg = GNUNET_malloc (msg_length);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART);
+  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART);
   msg->header.size = htons (msg_length);
-  msg->multipart_element_count = htonl (todo_count);
+  msg->contained_element_count = htonl (todo_count);
 
-  a = gcry_mpi_new (0);
   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
-  // encrypt our vector and generate string representations
-  for (i = session->last_processed, j = 0; i < session->total; i++) {
-    // is this a used element?
-    if (session->mask[i / 8] & 1 << (i % 8)) {
-      if (todo_count <= j)
-        break; //reached end of this message, can't include more
 
-      value = session->vector[i] >= 0 ? session->vector[i] : 
-session->vector[i];
-
-      a = gcry_mpi_set_ui (a, 0);
-      // long to gcry_mpi_t
-      if (session->vector[i] < 0)
-        gcry_mpi_sub_ui (a, a, value);
-      else
-        gcry_mpi_add_ui (a, a, value);
-
-      session->a[session->transferred + j] = gcry_mpi_set (NULL, a);
-      gcry_mpi_add (a, a, my_offset);
-      GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[j++]);
-    }
+  // now copy over the sorted element vector
+  a = gcry_mpi_new (0);
+  for (i = session->transferred_element_count; i < todo_count; i++) {
+    gcry_mpi_add (a, session->sorted_elements[i], my_offset);
+    GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i - 
session->transferred_element_count]);
   }
   gcry_mpi_release (a);
-  session->transferred += todo_count;
+  session->transferred_element_count += todo_count;
 
   session->msg = (struct GNUNET_MessageHeader *) msg;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n"));
@@ -1113,122 +1345,154 @@
                                       session);
     return;
   }
-  if (session->transferred != session->used) {
-    session->last_processed = i;
-  }
-  else
-    //final part
-    session->state = WAITING_FOR_SERVICE_RESPONSE;
 }
 
 
 /**
- * Executed by Alice, fills in a service-request message and sends it to the 
given peer
- *
- * @param cls the session associated with this request
- * @param tc task context handed over by scheduler, unsued
+ * Our client has finished sending us its multipart message.
+ * 
+ * @param session the service session context
  */
 static void
-prepare_service_request (void *cls,
-                         const struct GNUNET_SCHEDULER_TaskContext *tc)
+client_request_complete_bob (struct ServiceSession * client_session)
 {
-  struct ServiceSession * session = cls;
-  unsigned char * current;
-  struct GNUNET_SCALARPRODUCT_service_request * msg;
-  struct GNUNET_CRYPTO_PaillierCiphertext * payload;
-  unsigned int i;
-  unsigned int j;
-  uint32_t msg_length;
-  gcry_mpi_t a;
-  uint32_t value;
+  struct ServiceSession * session;
 
-  session->service_request_task = GNUNET_SCHEDULER_NO_TASK;
+  //check if service queue contains a matching request
+  session = find_matching_session (from_service_tail,
+                                   &client_session->session_id,
+                                   client_session->total, NULL);
+  if (NULL != 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 (&client_session->session_id));
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new channel to 
peer (%s)!\n"), GNUNET_i2s (&session->peer));
+    session->response = client_session;
+    session->intersected_elements = client_session->intersected_elements;
+    client_session->intersected_elements = NULL;
+    session->intersection_set = client_session->intersection_set;
+    client_session->intersection_set = NULL;
 
-  msg_length = sizeof (struct GNUNET_SCALARPRODUCT_service_request)
-          + session->mask_length
-          + sizeof(struct GNUNET_CRYPTO_PaillierPublicKey);
+    session->intersection_op = GNUNET_SET_prepare (&session->peer,
+                                                   &session->session_id,
+                                                   NULL,
+                                                   GNUNET_CRYPTO_random_u32 
(GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX),
+                                                   GNUNET_SET_RESULT_REMOVED,
+                                                   
cb_intersection_element_removed,
+                                                   session);
 
-  if (GNUNET_SERVER_MAX_MESSAGE_SIZE > msg_length + session->used * 
sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)) {
-    msg_length += session->used * sizeof(struct 
GNUNET_CRYPTO_PaillierCiphertext);
-    session->transferred = session->used;
+    GNUNET_SET_commit (session->intersection_op, session->intersection_set);
   }
   else {
-    //create a multipart msg, first we calculate a new msg size for the head 
msg
-    session->transferred = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - msg_length) / 
sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
+    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 (&client_session->session_id));
+    // no matching session exists yet, store the response
+    // for later processing by handle_service_request()
   }
+}
 
-  msg = GNUNET_malloc (msg_length);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB);
-  msg->total_element_count = htonl (session->used);
-  msg->contained_element_count = htonl (session->transferred);
-  memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode));
-  msg->mask_length = htonl (session->mask_length);
-  msg->element_count = htonl (session->total);
-  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, sizeof(struct GNUNET_CRYPTO_PaillierPublicKey));
-  current += sizeof(struct GNUNET_CRYPTO_PaillierPublicKey);
-  payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) current;
+/**
+ * Our client has finished sending us its multipart message.
+ * 
+ * @param session the service session context
+ */
+static void
+client_request_complete_alice (struct ServiceSession * session)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Creating new channel for session with key %s.\n"),
+              GNUNET_h2s (&session->session_id));
+  session->channel = GNUNET_MESH_channel_create (my_mesh, session,
+                                                 &session->peer,
+                                                 
GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
+                                                 GNUNET_MESH_OPTION_RELIABLE);
+  if (NULL == session->channel) {
+    session->response->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session);
+    return;
+  }
+  session->intersection_listen = GNUNET_SET_listen (cfg,
+                                                    
GNUNET_SET_OPERATION_INTERSECTION,
+                                                    &session->session_id,
+                                                    
cb_intersection_request_alice,
+                                                    session);
+  if (NULL == session->intersection_listen) {
+    session->response->client_notification_task =
+            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                      session);
+    return;
+  }
+  prepare_alices_computation_request (session);
+}
 
-  // now copy over the element vector
-  session->a = GNUNET_malloc (sizeof (gcry_mpi_t) * session->used);
-  a = gcry_mpi_new (0);
-  // encrypt our vector and generate string representations
-  for (i = 0, j = 0; i < session->total; i++) {
-    // if this is a used element...
-    if (session->mask[i / 8] & 1 << (i % 8)) {
-      if (session->transferred <= j)
-        break; //reached end of this message, can't include more
 
-      value = session->vector[i] >= 0 ? session->vector[i] : 
-session->vector[i];
+static void
+handle_client_message_multipart (void *cls,
+                                 struct GNUNET_SERVER_Client *client,
+                                 const struct GNUNET_MessageHeader *message)
+{
+  const struct GNUNET_SCALARPRODUCT_computation_message_multipart * msg = 
(const struct GNUNET_SCALARPRODUCT_computation_message_multipart *) message;
+  struct ServiceSession * session;
+  uint32_t contained_count;
+  struct GNUNET_SCALARPRODUCT_Element * elements;
+  uint32_t i;
 
-      a = gcry_mpi_set_ui (a, 0);
-      // long to gcry_mpi_t
-      if (session->vector[i] < 0)
-        gcry_mpi_sub_ui (a, a, value);
-      else
-        gcry_mpi_add_ui (a, a, value);
+  // only one concurrent session per client connection allowed, simplifies 
logics a lot...
+  session = GNUNET_SERVER_client_get_user_context (client, struct 
ServiceSession);
+  if (NULL == session) {
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
 
-      session->a[j] = gcry_mpi_set (NULL, a);
-      gcry_mpi_add (a, a, my_offset);
-      GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[j++]);
+  contained_count = ntohl (msg->element_count_contained);
+
+  //sanity check: is the message as long as the message_count fields suggests?
+  if ((ntohs (msg->header.size) != (sizeof (struct 
GNUNET_SCALARPRODUCT_computation_message_multipart) +contained_count * sizeof 
(struct GNUNET_SCALARPRODUCT_Element)))
+      || (0 == contained_count) || (session->total < 
session->transferred_element_count + contained_count)) {
+    GNUNET_break_op (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+  session->transferred_element_count += contained_count;
+
+  elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
+  for (i = 0; i < contained_count; i++) {
+    struct GNUNET_SET_Element set_elem;
+    struct GNUNET_SCALARPRODUCT_Element * elem;
+
+    if (0 == ntohl (elements[i].value))
+      continue;
+
+    elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
+    memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
+
+    if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put 
(session->intersected_elements,
+                                                            &elem->key,
+                                                            elem,
+                                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) {
+      GNUNET_free (elem);
+      continue;
     }
+    set_elem.data = &elements[i].key;
+    set_elem.size = htons (sizeof (elements[i].key));
+    set_elem.type = htons (0); /* do we REALLY need this? */
+    GNUNET_SET_add_element (session->intersection_set, &set_elem, NULL, NULL);
+    session->used_elements_count++;
   }
-  gcry_mpi_release (a);
 
-  session->msg = (struct GNUNET_MessageHeader *) msg;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n"));
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
 
-  //transmit via mesh messaging
-  session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready 
(session->channel, GNUNET_YES,
-                                                                        
GNUNET_TIME_UNIT_FOREVER_REL,
-                                                                        
msg_length,
-                                                                        
&do_send_message,
-                                                                        
session);
-  if (!session->service_transmit_handle) {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send message to 
channel!\n"));
-    GNUNET_free (msg);
-    session->msg = NULL;
-    session->client_notification_task =
-            GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
-                                      session);
+  if (session->total != session->transferred_element_count)
+    // multipart msg
     return;
-  }
-  if (session->transferred != session->used) {
-    session->state = WAITING_FOR_MULTIPART_TRANSMISSION;
-    session->last_processed = i;
-  }
+
+  if (ALICE == session->role)
+    client_request_complete_alice (session);
   else
-    //singlepart message
-    session->state = WAITING_FOR_SERVICE_RESPONSE;
+    client_request_complete_bob (session);
 }
 
 
@@ -1243,176 +1507,111 @@
  * @param message the actual message
  */
 static void
-handle_client_request (void *cls,
+handle_client_message (void *cls,
                        struct GNUNET_SERVER_Client *client,
                        const struct GNUNET_MessageHeader *message)
 {
-  const struct GNUNET_SCALARPRODUCT_client_request * msg = (const struct 
GNUNET_SCALARPRODUCT_client_request *) message;
+  const struct GNUNET_SCALARPRODUCT_computation_message * msg = (const struct 
GNUNET_SCALARPRODUCT_computation_message *) message;
   struct ServiceSession * session;
-  uint32_t element_count;
-  uint32_t mask_length;
+  uint32_t contained_count;
+  uint32_t total_count;
   uint32_t msg_type;
-  int32_t * vector;
+  struct GNUNET_SCALARPRODUCT_Element * elements;
   uint32_t i;
 
   // only one concurrent session per client connection allowed, simplifies 
logics a lot...
   session = GNUNET_SERVER_client_get_user_context (client, struct 
ServiceSession);
-  if ((NULL != session) && (session->state != FINALIZED)) {
+  if (NULL != session) {
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
-  else if (NULL != session) {
-    // old session is already completed, clean it up
-    GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session);
-    free_session_variables (session);
-    GNUNET_free (session);
-  }
 
-  //we need at least a peer and one message id to compare
-  if (sizeof (struct GNUNET_SCALARPRODUCT_client_request) > ntohs 
(msg->header.size)) {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _ ("Too short message received from client!\n"));
+  msg_type = ntohs (msg->header.type);
+  total_count = ntohl (msg->element_count_total);
+  contained_count = ntohl (msg->element_count_contained);
+
+  if ((GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type)
+      && (!memcmp (&msg->peer, &me, sizeof (struct GNUNET_PeerIdentity)))) {
+    //session with ourself makes no sense!
+    GNUNET_break_op (0);
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
 
-  msg_type = ntohs (msg->header.type);
-  element_count = ntohl (msg->element_count);
-  mask_length = ntohl (msg->mask_length);
-
   //sanity check: is the message as long as the message_count fields suggests?
-  if ((ntohs (msg->header.size) != (sizeof (struct 
GNUNET_SCALARPRODUCT_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"));
+  if ((ntohs (msg->header.size) != (sizeof (struct 
GNUNET_SCALARPRODUCT_computation_message) +contained_count * sizeof (struct 
GNUNET_SCALARPRODUCT_Element)))
+      || (0 == total_count)) {
+    GNUNET_break_op (0);
     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)) {
+                                     &msg->session_key,
+                                     total_count, NULL)) {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _ ("Duplicate session information received, cannot create new 
session with key `%s'\n"),
-                GNUNET_h2s (&msg->key));
+                _ ("Duplicate session information received, can not create new 
session with key `%s'\n"),
+                GNUNET_h2s (&msg->session_key));
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
 
   session = GNUNET_new (struct ServiceSession);
-  session->service_request_task = GNUNET_SCHEDULER_NO_TASK;
   session->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
   session->client = client;
-  session->total = element_count;
-  session->mask_length = mask_length;
+  session->total = total_count;
+  session->transferred_element_count = contained_count;
   // 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];
+  memcpy (&session->session_id, &msg->session_key, sizeof (struct 
GNUNET_HashCode));
 
-  if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type) {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                _ ("Got client-request-session with key %s, preparing channel 
to remote service.\n"),
-                GNUNET_h2s (&session->key));
+  elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
+  session->intersected_elements = GNUNET_CONTAINER_multihashmap_create 
(session->total, GNUNET_NO);
+  session->intersection_set = GNUNET_SET_create (cfg, 
GNUNET_SET_OPERATION_INTERSECTION);
+  for (i = 0; i < contained_count; i++) {
+    struct GNUNET_SET_Element set_elem;
+    struct GNUNET_SCALARPRODUCT_Element * elem;
 
-    session->role = ALICE;
-    // fill in the mask
-    session->mask = GNUNET_malloc (mask_length);
-    memcpy (session->mask, &vector[element_count], mask_length);
+    if (0 == ntohl (elements[i].value))
+      continue;
 
-    // copy over the elements
-    session->used = 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++;
+    elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
+    memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
+
+    if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put 
(session->intersected_elements,
+                                                            &elem->key,
+                                                            elem,
+                                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) {
+      GNUNET_free (elem);
+      continue;
     }
+    set_elem.data = &elements[i].key;
+    set_elem.size = htons (sizeof (elements[i].key));
+    set_elem.type = htons (0); /* do we REALLY need this? */
+    GNUNET_SET_add_element (session->intersection_set, &set_elem, NULL, NULL);
+    session->used_elements_count++;
+  }
 
-    if (0 == session->used) {
-      GNUNET_break_op (0);
-      GNUNET_free (session->vector);
-      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);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    // get our peer ID
+  if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type) {
+    session->role = ALICE;
     memcpy (&session->peer, &msg->peer, sizeof (struct GNUNET_PeerIdentity));
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _ ("Creating new channel for session with key %s.\n"),
-                GNUNET_h2s (&session->key));
-    session->channel = GNUNET_MESH_channel_create (my_mesh, session,
-                                                   &session->peer,
-                                                   
GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
-                                                   
GNUNET_MESH_OPTION_RELIABLE);
-    //prepare_service_request, channel_peer_disconnect_handler,
-    if (!session->channel) {
-      GNUNET_break (0);
-      GNUNET_free (session->vector);
-      GNUNET_free (session);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    GNUNET_SERVER_client_set_user_context (client, session);
-    GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session);
-
-    session->state = CLIENT_REQUEST_RECEIVED;
-    session->service_request_task =
-            GNUNET_SCHEDULER_add_now (&prepare_service_request,
-                                      session);
-
   }
   else {
-    struct ServiceSession * requesting_session;
-    enum SessionState needed_state = SERVICE_REQUEST_RECEIVED;
-
     session->role = BOB;
-    session->mask = NULL;
-    // copy over the elements
-    session->used = element_count;
-    for (i = 0; i < element_count; i++)
-      session->vector[i] = ntohl (vector[i]);
-    session->state = CLIENT_RESPONSE_RECEIVED;
+  }
 
-    GNUNET_SERVER_client_set_user_context (client, session);
-    GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session);
+  GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session);
+  GNUNET_SERVER_client_set_user_context (client, 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->total,
-                                                &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))
-        session->client_notification_task =
-              GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
-                                        session);
+  if (session->total != session->transferred_element_count)
+    // multipart msg
+    return;
 
-    }
-    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()
-    }
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_YES);
+  if (ALICE == session->role)
+    client_request_complete_alice (session);
+  else
+    client_request_complete_bob (session);
 }
 
 
@@ -1428,7 +1627,7 @@
  * @return session associated with the channel
  */
 static void *
-channel_incoming_handler (void *cls,
+cb_channel_incoming (void *cls,
                           struct GNUNET_MESH_Channel *channel,
                           const struct GNUNET_PeerIdentity *initiator,
                           uint32_t port, enum GNUNET_MESH_ChannelOption 
options)
@@ -1442,7 +1641,6 @@
   c->peer = *initiator;
   c->channel = channel;
   c->role = BOB;
-  c->state = WAITING_FOR_SERVICE_REQUEST;
   return c;
 }
 
@@ -1459,7 +1657,7 @@
  *                   with the channel is stored
  */
 static void
-channel_destruction_handler (void *cls,
+cb_channel_destruction (void *cls,
                              const struct GNUNET_MESH_Channel *channel,
                              void *channel_ctx)
 {
@@ -1469,12 +1667,12 @@
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               _ ("Peer disconnected, terminating session %s with peer (%s)\n"),
-              GNUNET_h2s (&session->key),
+              GNUNET_h2s (&session->session_id),
               GNUNET_i2s (&session->peer));
   if (ALICE == session->role) {
     // as we have only one peer connected in each session, just remove the 
session
 
-    if ((SERVICE_RESPONSE_RECEIVED > session->state) && (!do_shutdown)) {
+    if ((0/*//TODO: only for complete session*/) && (!do_shutdown)) {
       session->channel = NULL;
       // if this happened before we received the answer, we must terminate the 
session
       session->client_notification_task =
@@ -1494,16 +1692,14 @@
     // 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,
-                                            &session->key,
-                                            session->total,
-                                            NULL, NULL);
+                                            &session->session_id,
+                                            session->total, NULL);
     free_session_variables (session);
     GNUNET_free (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)) {
-      client_session->state = FINALIZED;
       client_session->client_notification_task =
               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                         client_session);
@@ -1528,13 +1724,13 @@
   gcry_mpi_t p;
   gcry_mpi_t p_prime;
   gcry_mpi_t tmp;
-  gcry_mpi_t r[session->used];
-  gcry_mpi_t r_prime[session->used];
+  gcry_mpi_t r[session->used_elements_count];
+  gcry_mpi_t r_prime[session->used_elements_count];
   gcry_mpi_t s;
   gcry_mpi_t s_prime;
   unsigned int i;
 
-  count = session->used;
+  count = session->used_elements_count;
   // due to the introduced static offset S, we now also have to remove this
   // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
   // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
@@ -1550,7 +1746,7 @@
   }
 
   // calculate t = sum(ai)
-  t = compute_square_sum (session->a, count);
+  t = compute_square_sum (session->sorted_elements, count);
 
   // calculate U
   u = gcry_mpi_new (0);
@@ -1570,9 +1766,9 @@
 
   // compute P
   GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
-                                    session->s, s);
+                                  session->s, s);
   GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
-                                    session->s_prime, s_prime);
+                                  session->s_prime, s_prime);
 
   // compute P
   gcry_mpi_add (p, s, t);
@@ -1595,13 +1791,13 @@
   gcry_mpi_div (p, NULL, p, tmp, 0);
 
   gcry_mpi_release (tmp);
-  for (i = 0; i < count; i++){
-    gcry_mpi_release (session->a[i]);
+  for (i = 0; i < count; i++) {
+    gcry_mpi_release (session->sorted_elements[i]);
     gcry_mpi_release (r[i]);
     gcry_mpi_release (r_prime[i]);
   }
-  GNUNET_free (session->a);
-  session->a = NULL;
+  GNUNET_free (session->a_head);
+  session->a_head = NULL;
   GNUNET_free (session->s);
   session->s = NULL;
   GNUNET_free (session->s_prime);
@@ -1626,64 +1822,49 @@
  *         #GNUNET_SYSERR to close it (signal serious error)
  */
 static int
-handle_service_request_multipart (void *cls,
-                                  struct GNUNET_MESH_Channel * channel,
-                                  void **channel_ctx,
-                                  const struct GNUNET_MessageHeader * message)
+handle_alices_cyrptodata_message_multipart (void *cls,
+                                            struct GNUNET_MESH_Channel * 
channel,
+                                            void **channel_ctx,
+                                            const struct GNUNET_MessageHeader 
* message)
 {
   struct ServiceSession * session;
   const struct GNUNET_SCALARPRODUCT_multipart_message * msg = (const struct 
GNUNET_SCALARPRODUCT_multipart_message *) message;
   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
-  uint32_t used_elements;
-  uint32_t contained_elements = 0;
+  uint32_t contained_elements;
   uint32_t msg_length;
 
   // are we in the correct state?
   session = (struct ServiceSession *) * channel_ctx;
-  if ((BOB != session->role) || (WAITING_FOR_MULTIPART_TRANSMISSION != 
session->state)) {
+  //we are not bob
+  if ((NULL == session->e_a) || //or we did not expect this message yet 
+      (session->used_elements_count == session->transferred_element_count)) { 
//we not expecting multipart messages
     goto except;
   }
   // shorter than minimum?
   if (ntohs (msg->header.size) <= sizeof (struct 
GNUNET_SCALARPRODUCT_multipart_message)) {
     goto except;
   }
-  used_elements = session->used;
-  contained_elements = ntohl (msg->multipart_element_count);
+  contained_elements = ntohl (msg->contained_element_count);
   msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)
-          + contained_elements * sizeof(struct 
GNUNET_CRYPTO_PaillierCiphertext);
+          +contained_elements * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext);
   //sanity check
   if ((ntohs (msg->header.size) != msg_length)
-      || (used_elements < contained_elements + session->transferred)) {
+      || (session->used_elements_count < contained_elements + 
session->transferred_element_count)
+      || (0 == contained_elements)) {
     goto except;
   }
   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
-  if (contained_elements != 0) {
-    // Convert each vector element to MPI_value
-    memcpy(&session->e_a[session->transferred], payload, 
-           sizeof(struct GNUNET_CRYPTO_PaillierCiphertext) * 
contained_elements);
-    
-    session->transferred += contained_elements;
+  // Convert each vector element to MPI_value
+  memcpy (&session->e_a[session->transferred_element_count], payload,
+          sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 
contained_elements);
 
-    if (session->transferred == used_elements) {
-      // single part finished
-      session->state = SERVICE_REQUEST_RECEIVED;
-      if (session->response) {
-        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, 
session->response)) {
-          //something went wrong, remove it again...
-          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));
-    }
-    else {
-      // multipart message
-    }
+  session->transferred_element_count += contained_elements;
+
+  if (contained_elements == session->used_elements_count) {
+    // single part finished
+    if (NULL == session->intersection_op)
+      // intersection has already finished, so we can proceed
+      compute_service_response (session);
   }
 
   return GNUNET_OK;
@@ -1712,24 +1893,98 @@
  *         #GNUNET_SYSERR to close it (signal serious error)
  */
 static int
-handle_service_request (void *cls,
+handle_alices_cyrptodata_message (void *cls,
+                                  struct GNUNET_MESH_Channel * channel,
+                                  void **channel_ctx,
+                                  const struct GNUNET_MessageHeader * message)
+{
+  struct ServiceSession * session;
+  const struct GNUNET_SCALARPRODUCT_alices_cryptodata_message * msg = (const 
struct GNUNET_SCALARPRODUCT_alices_cryptodata_message *) message;
+  struct GNUNET_CRYPTO_PaillierCiphertext *payload;
+  uint32_t contained_elements = 0;
+  uint32_t msg_length;
+
+  session = (struct ServiceSession *) * channel_ctx;
+  //we are not bob
+  if ((BOB != session->role)
+      //we are expecting multipart messages instead
+      || (NULL != session->e_a)
+      //or we did not expect this message yet
+      || //intersection OP has not yet finished
+      !((NULL != session->intersection_op)
+        //intersection OP done
+        || (session->response->sorted_elements)
+        )) {
+    goto invalid_msg;
+  }
+
+  // shorter than minimum?
+  if (ntohs (msg->header.size) <= sizeof (struct 
GNUNET_SCALARPRODUCT_multipart_message)) {
+    goto invalid_msg;
+  }
+
+  contained_elements = ntohl (msg->contained_element_count);
+  msg_length = sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message)
+          +contained_elements * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext);
+
+  //sanity check: is the message as long as the message_count fields suggests?
+  if ((ntohs (msg->header.size) != msg_length) ||
+      (session->used_elements_count < session->transferred_element_count + 
contained_elements) ||
+      (0 == contained_elements)) {
+    goto invalid_msg;
+  }
+
+  session->transferred_element_count = contained_elements;
+  payload = (struct GNUNET_CRYPTO_PaillierCiphertext*) &msg[1];
+
+  session->e_a = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext) * session->used_elements_count);
+  memcpy (&session->e_a[0], payload, contained_elements * sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+  if (contained_elements == session->used_elements_count) {
+    // single part finished
+    if (NULL == session->intersection_op)
+      // intersection has already finished, so we can proceed
+      compute_service_response (session);
+  }
+  return GNUNET_OK;
+invalid_msg:
+  GNUNET_break_op (0);
+  if ((NULL != session->next) || (NULL != session->prev) || (from_service_head 
== session))
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, 
session);
+  // and notify our client-session that we could not complete the session
+  if (session->response)
+    // we just found the responder session in this queue
+    session->response->client_notification_task =
+          GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                    session->response);
+  free_session_variables (session);
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Handle a request from another service to calculate a scalarproduct with us.
+ *
+ * @param cls closure (set from #GNUNET_MESH_connect)
+ * @param channel connection to the other end
+ * @param channel_ctx place to store local state associated with the channel
+ * @param message the actual message
+ * @return #GNUNET_OK to keep the connection open,
+ *         #GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_alices_computation_request (void *cls,
                         struct GNUNET_MESH_Channel * channel,
                         void **channel_ctx,
                         const struct GNUNET_MessageHeader * message)
 {
   struct ServiceSession * session;
+  struct ServiceSession * client_session;
   const struct GNUNET_SCALARPRODUCT_service_request * msg = (const struct 
GNUNET_SCALARPRODUCT_service_request *) message;
-  uint32_t mask_length;
-  struct GNUNET_CRYPTO_PaillierCiphertext *payload;
-  uint32_t used_elements;
-  uint32_t contained_elements = 0;
-  uint32_t element_count;
-  uint32_t msg_length;
-  unsigned char * current;
-  enum SessionState needed_state;
+  uint32_t total_elements;
 
   session = (struct ServiceSession *) * channel_ctx;
-  if (WAITING_FOR_SERVICE_REQUEST != session->state) {
+  if (session->total != 0) {
+    // must be a fresh session
     goto invalid_msg;
   }
   // Check if message was sent by me, which would be bad!
@@ -1739,91 +1994,71 @@
     return GNUNET_SYSERR;
   }
   // shorter than expected?
-  if (ntohs (msg->header.size) < sizeof (struct 
GNUNET_SCALARPRODUCT_service_request)) {
+  if (ntohs (msg->header.size) != sizeof (struct 
GNUNET_SCALARPRODUCT_service_request)) {
     GNUNET_free (session);
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  mask_length = ntohl (msg->mask_length);
-  used_elements = ntohl (msg->total_element_count);
-  contained_elements = ntohl (msg->contained_element_count);
-  element_count = ntohl (msg->element_count);
-  msg_length = sizeof (struct GNUNET_SCALARPRODUCT_service_request)
-          + mask_length + sizeof(struct GNUNET_CRYPTO_PaillierPublicKey) 
-          + contained_elements * sizeof(struct 
GNUNET_CRYPTO_PaillierCiphertext);
+  total_elements = ntohl (msg->total_element_count);
 
   //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 < contained_elements) ||
-      (0 == used_elements) ||
-      (mask_length != (element_count / 8 + ((element_count % 8) ? 1 : 0)))) {
+  if (1 > total_elements) {
     GNUNET_free (session);
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   if (find_matching_session (from_service_tail,
-                             &msg->key,
-                             element_count,
-                             NULL,
+                             &msg->session_id,
+                             total_elements,
                              NULL)) {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 _ ("Got message with duplicate session key (`%s'), ignoring 
service request.\n"),
-                (const char *) &(msg->key));
+                (const char *) &(msg->session_id));
     GNUNET_free (session);
     return GNUNET_SYSERR;
   }
 
-  session->total = element_count;
-  session->used = used_elements;
-  session->transferred = contained_elements;
+  session->total = total_elements;
   session->channel = channel;
 
   // 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;
+  memcpy (&session->session_id, &msg->session_id, sizeof (struct 
GNUNET_HashCode));
 
-  //convert the publickey to sexp
-  session->remote_pubkey = GNUNET_malloc(sizeof(struct 
GNUNET_CRYPTO_PaillierPublicKey));
-  memcpy(session->remote_pubkey, current, sizeof(struct 
GNUNET_CRYPTO_PaillierPublicKey));
-  current += sizeof(struct GNUNET_CRYPTO_PaillierPublicKey);
-  
-  payload = (struct GNUNET_CRYPTO_PaillierCiphertext*) current;
+  // public key
+  memcpy (&session->remote_pubkey, &msg->public_key, sizeof (struct 
GNUNET_CRYPTO_PaillierPublicKey));
+
   //check if service queue contains a matching request
-  needed_state = CLIENT_RESPONSE_RECEIVED;
-  session->response = find_matching_session (from_client_tail,
-                                             &session->key,
-                                             session->total,
-                                             &needed_state, NULL);
-  session->state = WAITING_FOR_MULTIPART_TRANSMISSION;
+  client_session = find_matching_session (from_client_tail,
+                                          &session->session_id,
+                                          session->total, NULL);
+
   GNUNET_CONTAINER_DLL_insert (from_service_head, from_service_tail, session);
-  
-  session->e_a = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext) * used_elements);
-  if (contained_elements != 0) {
-    // Convert each vector element to MPI_value
-    memcpy(session->e_a, payload, sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext) * used_elements);
-    if (contained_elements == used_elements) {
-      // single part finished
-      session->state = SERVICE_REQUEST_RECEIVED;
-      if (session->response) {
-        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, 
session->response)) {
-          //something went wrong, remove it again...
-          goto invalid_msg;
-        }
-      }
-      else
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s 
without a matching element set, queueing.\n"), GNUNET_h2s (&session->key));
-    }
-    else {
-      // multipart message
-    }
+
+  if ((NULL != client_session)
+      && (client_session->transferred_element_count == client_session->total)) 
{
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s and a 
matching element set, processing.\n"), GNUNET_h2s (&session->session_id));
+
+    session->response = client_session;
+    session->intersected_elements = client_session->intersected_elements;
+    client_session->intersected_elements = NULL;
+    session->intersection_set = client_session->intersection_set;
+    client_session->intersection_set = NULL;
+
+    session->intersection_op = GNUNET_SET_prepare (&session->peer,
+                                                   &session->session_id,
+                                                   NULL,
+                                                   GNUNET_CRYPTO_random_u32 
(GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX),
+                                                   GNUNET_SET_RESULT_REMOVED,
+                                                   
cb_intersection_element_removed,
+                                                   session);
+
+    GNUNET_SET_commit (session->intersection_op, session->intersection_set);
   }
+  else {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a 
matching element set, queueing.\n"), GNUNET_h2s (&session->session_id));
+  }
+
   return GNUNET_OK;
 invalid_msg:
   GNUNET_break_op (0);
@@ -1851,7 +2086,7 @@
  *         #GNUNET_SYSERR to close it (signal serious error)
  */
 static int
-handle_service_response_multipart (void *cls,
+handle_bobs_cryptodata_multipart (void *cls,
                                    struct GNUNET_MESH_Channel * channel,
                                    void **channel_ctx,
                                    const struct GNUNET_MessageHeader * message)
@@ -1867,33 +2102,32 @@
   GNUNET_assert (NULL != message);
   // are we in the correct state?
   session = (struct ServiceSession *) * channel_ctx;
-  if ((ALICE != session->role) || (WAITING_FOR_MULTIPART_TRANSMISSION != 
session->state)) {
+  if ((ALICE != session->role) || (NULL == session->sorted_elements)) {
     goto invalid_msg;
   }
   msg_size = ntohs (msg->header.size);
-  required_size = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message) 
-                  + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
+  required_size = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)
+          + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
   // shorter than minimum?
   if (required_size > msg_size) {
     goto invalid_msg;
   }
-  contained = ntohl (msg->multipart_element_count);
+  contained = ntohl (msg->contained_element_count);
   required_size = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)
           + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
   //sanity check: is the message as long as the message_count fields suggests?
-  if ((required_size != msg_size) || (session->used < session->transferred + 
contained)) {
+  if ((required_size != msg_size) || (session->used_elements_count < 
session->transferred_element_count + contained)) {
     goto invalid_msg;
   }
   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
   // Convert each k[][perm] to its MPI_value
   for (i = 0; i < contained; i++) {
-    memcpy(&session->r[session->transferred+i], &payload[2*i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
-    memcpy(&session->r_prime[session->transferred+i], &payload[2*i], sizeof 
(struct GNUNET_CRYPTO_PaillierCiphertext));
+    memcpy (&session->r[session->transferred_element_count + i], &payload[2 * 
i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
+    memcpy (&session->r_prime[session->transferred_element_count + i], 
&payload[2 * i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
   }
-  session->transferred += contained;
-  if (session->transferred != session->used)
+  session->transferred_element_count += contained;
+  if (session->transferred_element_count != session->used_elements_count)
     return GNUNET_OK;
-  session->state = SERVICE_RESPONSE_RECEIVED;
   session->product = compute_scalar_product (session); //never NULL
 
 invalid_msg:
@@ -1901,7 +2135,6 @@
 
   // send message with product to client
   if (ALICE == session->role) {
-    session->state = FINALIZED;
     session->channel = NULL;
     session->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_response,
@@ -1925,7 +2158,7 @@
  *         #GNUNET_SYSERR to close it (we are done)
  */
 static int
-handle_service_response (void *cls,
+handle_bobs_cryptodata_message (void *cls,
                          struct GNUNET_MESH_Channel * channel,
                          void **channel_ctx,
                          const struct GNUNET_MessageHeader * message)
@@ -1941,7 +2174,7 @@
   GNUNET_assert (NULL != message);
   session = (struct ServiceSession *) * channel_ctx;
   // are we in the correct state?
-  if (WAITING_FOR_SERVICE_RESPONSE != session->state) {
+  if (0 /*//TODO: correct state*/) {
     goto invalid_msg;
   }
   //we need at least a full message without elements attached
@@ -1956,38 +2189,34 @@
           + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)
           + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
   //sanity check: is the message as long as the message_count fields suggests?
-  if ((msg_size != required_size) || (session->used < contained)) {
+  if ((msg_size != required_size) || (session->used_elements_count < 
contained)) {
     goto invalid_msg;
   }
-  session->state = WAITING_FOR_MULTIPART_TRANSMISSION;
-  session->transferred = contained;
+  session->transferred_element_count = contained;
   //convert s
   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
-  
-  session->s = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
-  session->s_prime = GNUNET_malloc(sizeof(struct 
GNUNET_CRYPTO_PaillierCiphertext));
-  memcpy(session->s,&payload[0],sizeof(struct 
GNUNET_CRYPTO_PaillierCiphertext));
-  memcpy(session->s_prime,&payload[1],sizeof(struct 
GNUNET_CRYPTO_PaillierCiphertext));
-  
-  session->r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) 
* session->used);
-  session->r_prime = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext) * session->used);
-  
+
+  session->s = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+  session->s_prime = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+  memcpy (session->s, &payload[0], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+  memcpy (session->s_prime, &payload[1], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+
+  session->r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) 
* session->used_elements_count);
+  session->r_prime = GNUNET_malloc (sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext) * session->used_elements_count);
+
   // Convert each k[][perm] to its MPI_value
   for (i = 0; i < contained; i++) {
-    memcpy(&session->r[i], &payload[2 + 2*i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
-    memcpy(&session->r_prime[i], &payload[3 + 2*i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+    memcpy (&session->r[i], &payload[2 + 2 * i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
+    memcpy (&session->r_prime[i], &payload[3 + 2 * i], sizeof (struct 
GNUNET_CRYPTO_PaillierCiphertext));
   }
-  if (session->transferred != session->used)
+  if (session->transferred_element_count != session->used_elements_count)
     return GNUNET_OK; //wait for the other multipart chunks
-
-  session->state = SERVICE_RESPONSE_RECEIVED;
   session->product = compute_scalar_product (session); //never NULL
 
 invalid_msg:
   GNUNET_break_op (NULL != session->product);
   // send message with product to client
   if (ALICE == session->role) {
-    session->state = FINALIZED;
     session->channel = NULL;
     session->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_response,
@@ -2017,7 +2246,7 @@
 
   // terminate all owned open channels.
   for (session = from_client_head; NULL != session; session = session->next) {
-    if ((FINALIZED != session->state) && (NULL != session->channel)) {
+    if ((0/*//TODO: not finalized*/) && (NULL != session->channel)) {
       GNUNET_MESH_channel_destroy (session->channel);
       session->channel = NULL;
     }
@@ -2025,10 +2254,6 @@
       GNUNET_SCHEDULER_cancel (session->client_notification_task);
       session->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
     }
-    if (GNUNET_SCHEDULER_NO_TASK != session->service_request_task) {
-      GNUNET_SCHEDULER_cancel (session->service_request_task);
-      session->service_request_task = GNUNET_SCHEDULER_NO_TASK;
-    }
     if (NULL != session->client) {
       GNUNET_SERVER_client_disconnect (session->client);
       session->client = NULL;
@@ -2060,15 +2285,17 @@
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
-    {&handle_client_request, NULL, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE, 0},
-    {&handle_client_request, NULL, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB, 0},
+    {&handle_client_message, NULL, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE, 0},
+    {&handle_client_message, NULL, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB, 0},
+    {&handle_client_message_multipart, NULL, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART, 0},
     {NULL, NULL, 0, 0}
   };
   static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
-    { &handle_service_request, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB, 
0},
-    { &handle_service_request_multipart, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART, 0},
-    { &handle_service_response, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE, 0},
-    { &handle_service_response_multipart, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE_MULTIPART, 0},
+    { &handle_alices_computation_request, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA, 0},
+    { &handle_alices_cyrptodata_message, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA, 0},
+    { &handle_alices_cyrptodata_message_multipart, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART, 0},
+    { &handle_bobs_cryptodata_message, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA, 0},
+    { &handle_bobs_cryptodata_multipart, 
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART, 0},
     {NULL, 0, 0}
   };
   static const uint32_t ports[] = {
@@ -2077,13 +2304,13 @@
   };
   //generate private/public key set
   GNUNET_CRYPTO_paillier_create (&my_pubkey, &my_privkey);
-  
+
   // offset has to be sufficiently small to allow computation of:
   // m1+m2 mod n == (S + a) + (S + b) mod n,
   // if we have more complex operations, this factor needs to be lowered
   my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
   gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
-  
+
   // register server callbacks and disconnect handler
   GNUNET_SERVER_add_handlers (server, server_handlers);
   GNUNET_SERVER_disconnect_notify (server,
@@ -2093,8 +2320,8 @@
                 GNUNET_CRYPTO_get_peer_identity (c,
                                                  &me));
   my_mesh = GNUNET_MESH_connect (c, NULL,
-                                 &channel_incoming_handler,
-                                 &channel_destruction_handler,
+                                 &cb_channel_incoming,
+                                 &cb_channel_destruction,
                                  mesh_handlers, ports);
   if (!my_mesh) {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to MESH failed\n"));

Modified: gnunet/src/scalarproduct/scalarproduct.h
===================================================================
--- gnunet/src/scalarproduct/scalarproduct.h    2014-05-07 07:32:26 UTC (rev 
33176)
+++ gnunet/src/scalarproduct/scalarproduct.h    2014-05-07 08:21:49 UTC (rev 
33177)
@@ -57,7 +57,7 @@
  * Message type passed from client to service
  * to initiate a request or responder role
  */
-struct GNUNET_SCALARPRODUCT_client_request
+struct GNUNET_SCALARPRODUCT_computation_message
 {
   /**
    * GNUNET message header
@@ -67,17 +67,17 @@
   /**
    * how many elements the vector in payload contains
    */
-  uint32_t element_count GNUNET_PACKED;
-
+  uint32_t element_count_total GNUNET_PACKED;
+  
   /**
-   * how many bytes the mask has
+   * contained elements the vector in payload contains
    */
-  uint32_t mask_length GNUNET_PACKED;
+  uint32_t element_count_contained GNUNET_PACKED;
 
   /**
    * the transaction/session key used to identify a session
    */
-  struct GNUNET_HashCode key;
+  struct GNUNET_HashCode session_key;
 
   /**
    * the identity of a remote peer we want to communicate with
@@ -85,11 +85,32 @@
   struct GNUNET_PeerIdentity peer;
 
   /**
-   * followed by long vector[element_count] | [unsigned char mask[mask_bytes]]
+   * followed by struct GNUNET_SCALARPRODUCT_Element[]
    */
 };
 
 /**
+ * multipart messages following GNUNET_SCALARPRODUCT_client_request
+ */
+struct GNUNET_SCALARPRODUCT_computation_message_multipart
+{
+  /**
+   * GNUNET message header
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * contained elements the vector in payload contains
+   */
+  uint32_t element_count_contained GNUNET_PACKED;
+
+  /**
+   * followed by struct GNUNET_SCALARPRODUCT_Element[]
+   */
+};
+
+
+/**
  * Message type passed from requesting service Alice to responding service Bob
  * to initiate a request and make bob participate in our protocol
  */
@@ -104,28 +125,36 @@
    */
   uint32_t total_element_count GNUNET_PACKED;
 
-    /**
-   * how many elements are actually included after the mask was applied.
+  /**
+   * the transaction/session key used to identify a session
    */
-  uint32_t contained_element_count GNUNET_PACKED;
+  struct GNUNET_HashCode session_id;
 
   /**
-   * how many bytes the mask has
+   * Alice's public key
    */
-  uint32_t mask_length GNUNET_PACKED;
+  struct GNUNET_CRYPTO_PaillierPublicKey public_key;
 
+};
+
+
+/**
+ * Message type passed from requesting service Alice to responding service Bob
+ * to initiate a request and make bob participate in our protocol
+ */
+struct GNUNET_SCALARPRODUCT_alices_cryptodata_message {
   /**
-   * the transaction/session key used to identify a session
+   * GNUNET message header
    */
-  struct GNUNET_HashCode key;
+  struct GNUNET_MessageHeader header;
 
   /**
-   * how many elements the vector in payload contains
+   * how many elements we appended to this message
    */
-  uint32_t element_count GNUNET_PACKED;
+  uint32_t contained_element_count GNUNET_PACKED;
 
   /**
-   * followed by mask | public_key | vector[used_element_count]
+   * struct GNUNET_CRYPTO_PaillierCiphertext[contained_element_count]
    */
 };
 
@@ -141,9 +170,9 @@
   /**
    * how many elements we supply within this message
    */
-  uint32_t multipart_element_count GNUNET_PACKED;
+  uint32_t contained_element_count GNUNET_PACKED;
 
-  // followed by vector[multipart_element_count] or k[i][perm]
+  // struct GNUNET_CRYPTO_PaillierCiphertext[multipart_element_count]
 };
 
 /**

Modified: gnunet/src/scalarproduct/scalarproduct_api.c
===================================================================
--- gnunet/src/scalarproduct/scalarproduct_api.c        2014-05-07 07:32:26 UTC 
(rev 33176)
+++ gnunet/src/scalarproduct/scalarproduct_api.c        2014-05-07 08:21:49 UTC 
(rev 33177)
@@ -46,21 +46,11 @@
                                                              enum 
GNUNET_SCALARPRODUCT_ResponseStatus status);
 
 /**
- * Entry in the request queue per client
+ * A handle returned for each computation
  */
 struct GNUNET_SCALARPRODUCT_ComputationHandle
 {
   /**
-   * This is a linked list.
-   */
-  struct GNUNET_SCALARPRODUCT_ComputationHandle *next;
-
-  /**
-   * This is a linked list.
-   */
-  struct GNUNET_SCALARPRODUCT_ComputationHandle *prev;
-
-  /**
    * Our configuration.
    */
   const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -86,27 +76,37 @@
   struct GNUNET_CLIENT_TransmitHandle *th;
 
   /**
-   * Size of the message
+   * count of all elements we offer for computation
    */
-  uint16_t message_size;
+  uint32_t element_count_total;
 
   /**
+   * count of the transfered elements we offer for computation
+   */
+  uint32_t element_count_transfered;
+  
+  /**
+   * the client's elements which 
+   */
+  struct GNUNET_SCALARPRODUCT_Element * elements;
+  
+  /**
    * Message to be sent to the scalarproduct service
    */
-  struct GNUNET_SCALARPRODUCT_client_request * msg;
+  void * msg;
 
   /**
-   * The msg handler callback
+   * The client's msg handler callback
    */
   union
   {
   /**
-   * Function to call after transmission of the request.
+   * Function to call after transmission of the request (Bob).
    */
   GNUNET_SCALARPRODUCT_ContinuationWithStatus cont_status;
 
   /**
-   * Function to call after transmission of the request.
+   * Function to call after transmission of the request (Alice).
    */
   GNUNET_SCALARPRODUCT_DatumProcessor cont_datum;
   };
@@ -117,31 +117,24 @@
   void *cont_cls;
 
   /**
-   * Response Processor for response from the service. This function calls the
-   * continuation function provided by the client.
+   * API internal callback for results and failures to be forwarded to the 
client
    */
   GNUNET_SCALARPRODUCT_ResponseMessageHandler response_proc;
+  
+  /**
+   * 
+   */
+  GNUNET_SCHEDULER_TaskIdentifier cont_multipart;
 };
 
 /**************************************************************
- ***  Global Variables                               **********
+ ***  Forward Function Declarations                          **********
  **************************************************************/
-/**
- * Head of the active sessions queue
- */
-static struct GNUNET_SCALARPRODUCT_ComputationHandle *head;
-/**
- * Tail of the active sessions queue
- */
-static struct GNUNET_SCALARPRODUCT_ComputationHandle *tail;
 
-/**************************************************************
- ***  Function Declarations                          **********
- **************************************************************/
-
 void
 GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle * 
h);
 
+static size_t do_send_message (void *cls, size_t size, void *buf);
 /**************************************************************
  ***  Static Function Declarations                   **********
  **************************************************************/
@@ -225,7 +218,7 @@
 static void
 receive_cb (void *cls, const struct GNUNET_MessageHeader *msg)
 {
-  struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls;
+  struct GNUNET_SCALARPRODUCT_ComputationHandle *h = cls;
   const struct GNUNET_SCALARPRODUCT_client_response *message =
           (const struct GNUNET_SCALARPRODUCT_client_response *) msg;
   enum GNUNET_SCALARPRODUCT_ResponseStatus status = 
GNUNET_SCALARPRODUCT_Status_InvalidResponse;
@@ -235,28 +228,76 @@
       LOG (GNUNET_ERROR_TYPE_WARNING, "Disconnected by Service.\n");
       status = GNUNET_SCALARPRODUCT_Status_ServiceDisconnected;
     }
-  else if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT != ntohs 
(msg->type))
+  else if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT != ntohs (msg->type))
     {
       LOG (GNUNET_ERROR_TYPE_WARNING, "Invalid message type received\n");
     }
   else if (0 < ntohl (message->product_length) || (0 == message->range))
     {
       // response for the responder client, successful
-      GNUNET_STATISTICS_update (qe->stats,
+      GNUNET_STATISTICS_update (h->stats,
                                 gettext_noop ("# SUC responder result messages 
received"), 1,
                                 GNUNET_NO);
 
       status = GNUNET_SCALARPRODUCT_Status_Success;
     }
 
-  if (qe->cont_datum != NULL)
-    qe->response_proc (qe, msg, status);
+  if (h->cont_status != NULL)
+    h->response_proc (h, msg, status);
 
-  GNUNET_CONTAINER_DLL_remove (head, tail, qe);
-  GNUNET_free (qe);
+  GNUNET_free (h);
 }
 
 
+static void
+send_multipart (void * cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
+{
+  struct GNUNET_SCALARPRODUCT_ComputationHandle *h = (struct 
GNUNET_SCALARPRODUCT_ComputationHandle *) cls;
+  struct GNUNET_SCALARPRODUCT_computation_message_multipart *msg;
+  uint32_t size;
+  uint32_t todo;
+
+  h->cont_multipart = GNUNET_SCHEDULER_NO_TASK;
+
+  todo = h->element_count_total - h->element_count_transfered;
+  size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message_multipart) 
+todo * sizeof (struct GNUNET_SCALARPRODUCT_Element);
+  if (GNUNET_SERVER_MAX_MESSAGE_SIZE <= size) {
+    //create a multipart msg, first we calculate a new msg size for the head 
msg
+    todo = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct 
GNUNET_SCALARPRODUCT_computation_message_multipart)) / sizeof (struct 
GNUNET_SCALARPRODUCT_Element);
+    size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message_multipart) 
+todo * sizeof (struct GNUNET_SCALARPRODUCT_Element);
+  }
+
+  msg = (struct GNUNET_SCALARPRODUCT_computation_message_multipart*) 
GNUNET_malloc (size);
+  h->msg = msg;
+  msg->header.size = htons (size);
+  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART);
+  msg->element_count_contained = htonl (todo);
+
+  memcpy (&msg[1], &h->elements[h->element_count_transfered], todo);
+  h->element_count_transfered += todo;
+
+  h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size,
+                                               GNUNET_TIME_UNIT_FOREVER_REL,
+                                               GNUNET_YES, // retry is OK in 
the initial stage
+                                               &do_send_message, h);
+
+  if (!h->th) {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         _ ("Failed to send a multipart message to the scalarproduct 
service\n"));
+    GNUNET_STATISTICS_update (h->stats,
+                              gettext_noop ("# transmission request failures"),
+                              1, GNUNET_NO);
+    GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES);
+    GNUNET_CLIENT_disconnect (h->client);
+    GNUNET_free (h->msg);
+    h->msg = NULL;
+    if (h->cont_status != NULL)
+      h->response_proc (h, NULL, GNUNET_SCALARPRODUCT_Status_Failure);
+
+    GNUNET_SCALARPRODUCT_cancel (cls);
+  }
+}
+
 /**
  * Transmits the request to the VectorProduct Service
  *
@@ -267,39 +308,45 @@
  * @return Size of the message sent
  */
 static size_t
-transmit_request (void *cls, size_t size,
-                  void *buf)
+do_send_message (void *cls, size_t size,
+                 void *buf)
 {
-  struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls;
+  struct GNUNET_SCALARPRODUCT_ComputationHandle *h = cls;
 
-  if (NULL == buf)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to 
SCALARPRODUCT.\n");
-      GNUNET_STATISTICS_update (qe->stats,
-                                gettext_noop ("# transmission request 
failures"),
-                                1, GNUNET_NO);
+  if (NULL == buf) {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to 
SCALARPRODUCT.\n");
+    GNUNET_STATISTICS_update (h->stats,
+                              gettext_noop ("# transmission request failures"),
+                              1, GNUNET_NO);
 
-      // notify caller about the error, done here.
-      if (qe->cont_datum != NULL)
-        qe->response_proc (qe, NULL, GNUNET_SCALARPRODUCT_Status_Failure);
+    // notify caller about the error, done here.
+    if (h->cont_status != NULL)
+      h->response_proc (h, NULL, GNUNET_SCALARPRODUCT_Status_Failure);
 
-      GNUNET_SCALARPRODUCT_cancel (cls);
-      return 0;
-    }
-  memcpy (buf, qe->msg, size);
+    GNUNET_SCALARPRODUCT_cancel (cls);
+    return 0;
+  }
+  memcpy (buf, h->msg, size);
 
-  GNUNET_free (qe->msg);
-  qe->msg = NULL;
-  qe->th = NULL;
+  GNUNET_free (h->msg);
+  h->msg = NULL;
+  h->th = NULL;
 
-  GNUNET_CLIENT_receive (qe->client, &receive_cb, qe,
-                         GNUNET_TIME_UNIT_FOREVER_REL);
-
 #if INSANE_STATISTICS
-  GNUNET_STATISTICS_update (qe->stats,
+  GNUNET_STATISTICS_update (h->stats,
                             gettext_noop ("# bytes sent to scalarproduct"), 1,
                             GNUNET_NO);
 #endif
+
+  /* done sending */
+  if (h->element_count_total == h->element_count_transfered) {
+    GNUNET_CLIENT_receive (h->client, &receive_cb, h,
+                           GNUNET_TIME_UNIT_FOREVER_REL);
+    return size;
+  }
+  
+  h->cont_multipart = GNUNET_SCHEDULER_add_now (&send_multipart, h);
+  
   return size;
 }
 
@@ -322,20 +369,19 @@
  * @return a new handle for this computation
  */
 struct GNUNET_SCALARPRODUCT_ComputationHandle *
-GNUNET_SCALARPRODUCT_response (const struct GNUNET_CONFIGURATION_Handle * cfg,
-                               const struct GNUNET_HashCode * key,
-                               const int32_t * elements,
+GNUNET_SCALARPRODUCT_accept_computation (const struct 
GNUNET_CONFIGURATION_Handle * cfg,
+                               const struct GNUNET_HashCode * session_key,
+                               const struct GNUNET_SCALARPRODUCT_Element * 
elements,
                                uint32_t element_count,
                                GNUNET_SCALARPRODUCT_ContinuationWithStatus 
cont,
                                void * cont_cls)
 {
   struct GNUNET_SCALARPRODUCT_ComputationHandle *h;
-  struct GNUNET_SCALARPRODUCT_client_request *msg;
-  int32_t * vector;
-  uint16_t size;
-  uint64_t i;
+  struct GNUNET_SCALARPRODUCT_computation_message *msg;
+  uint32_t size;
+  uint16_t possible;
 
-  GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct 
GNUNET_SCALARPRODUCT_client_request)
+  GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct 
GNUNET_SCALARPRODUCT_computation_message)
                  + element_count * sizeof (int32_t));
   h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle);
   h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg);
@@ -356,42 +402,56 @@
       return NULL;
     }
 
-  size = sizeof (struct GNUNET_SCALARPRODUCT_client_request) + element_count * 
sizeof (int32_t);
+  h->element_count_total = element_count;
+  size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + 
element_count * sizeof (struct GNUNET_SCALARPRODUCT_Element);
+  if (GNUNET_SERVER_MAX_MESSAGE_SIZE > size) {
+    possible = element_count;
+    h->element_count_transfered = element_count;
+  }
+  else {
+    //create a multipart msg, first we calculate a new msg size for the head 
msg
+    possible = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct 
GNUNET_SCALARPRODUCT_computation_message)) / sizeof (struct 
GNUNET_SCALARPRODUCT_Element);
+    h->element_count_transfered = possible;
+    size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + 
possible*sizeof (struct GNUNET_SCALARPRODUCT_Element);
+    h->elements = (struct GNUNET_SCALARPRODUCT_Element*) 
+            GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element) * 
element_count);
+    memcpy (h->elements, elements, sizeof (struct 
GNUNET_SCALARPRODUCT_Element)*element_count);
+  }
 
   h->cont_status = cont;
   h->cont_cls = cont_cls;
   h->response_proc = &process_status_message;
   h->cfg = cfg;
-  memcpy (&h->key, key, sizeof (struct GNUNET_HashCode));
+  memcpy (&h->key, session_key, sizeof (struct GNUNET_HashCode));
 
-  msg = (struct GNUNET_SCALARPRODUCT_client_request*) GNUNET_malloc (size);
+  msg = (struct GNUNET_SCALARPRODUCT_computation_message*) GNUNET_malloc 
(size);
   h->msg = msg;
   msg->header.size = htons (size);
   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB);
-  msg->element_count = htonl (element_count);
+  msg->element_count_total = htonl (element_count);
+  msg->element_count_contained = htonl (possible);
 
-  vector = (int32_t*) & msg[1];
-  // copy each element over to the message
-  for (i = 0; i < element_count; i++)
-    vector[i] = htonl (elements[i]);
+  memcpy (&msg->session_key, session_key, sizeof (struct GNUNET_HashCode));
+  memcpy (&msg[1], elements, possible);
 
-  memcpy (&msg->key, key, sizeof (struct GNUNET_HashCode));
-
   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size,
                                                GNUNET_TIME_UNIT_FOREVER_REL,
                                                GNUNET_YES, // retry is OK in 
the initial stage
-                                               &transmit_request, h);
+                                               &do_send_message, h);
   if (!h->th)
     {
       LOG (GNUNET_ERROR_TYPE_ERROR,
            _ ("Failed to send a message to the scalarproduct service\n"));
+      GNUNET_STATISTICS_update (h->stats,
+                              gettext_noop ("# transmission request failures"),
+                              1, GNUNET_NO);
       GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES);
       GNUNET_CLIENT_disconnect (h->client);
       GNUNET_free (h->msg);
+      GNUNET_free_non_null (h->elements);
       GNUNET_free (h);
       return NULL;
     }
-  GNUNET_CONTAINER_DLL_insert (head, tail, h);
   return h;
 }
 
@@ -400,38 +460,29 @@
  * Request by Alice's client for computing a scalar product
  *
  * @param cfg the gnunet configuration handle
- * @param key Session key should be unique to the requesting client
+ * @param session_key Session key should be unique to the requesting client
  * @param peer PeerID of the other peer
  * @param elements Array of elements of the vector
  * @param element_count Number of elements in the vector
- * @param mask Array of the mask
- * @param mask_bytes number of bytes in the mask
  * @param cont Callback function
  * @param cont_cls Closure for the callback function
  *
  * @return a new handle for this computation
  */
 struct GNUNET_SCALARPRODUCT_ComputationHandle *
-GNUNET_SCALARPRODUCT_request (const struct GNUNET_CONFIGURATION_Handle * cfg,
-                              const struct GNUNET_HashCode * key,
+GNUNET_SCALARPRODUCT_start_computation (const struct 
GNUNET_CONFIGURATION_Handle * cfg,
+                              const struct GNUNET_HashCode * session_key,
                               const struct GNUNET_PeerIdentity *peer,
-                              const int32_t * elements,
+                              const struct GNUNET_SCALARPRODUCT_Element * 
elements,
                               uint32_t element_count,
-                              const unsigned char * mask,
-                              uint32_t mask_bytes,
                               GNUNET_SCALARPRODUCT_DatumProcessor cont,
                               void * cont_cls)
 {
   struct GNUNET_SCALARPRODUCT_ComputationHandle *h;
-  struct GNUNET_SCALARPRODUCT_client_request *msg;
-  int32_t * vector;
-  uint16_t size;
-  uint64_t i;
+  struct GNUNET_SCALARPRODUCT_computation_message *msg;
+  uint32_t size;
+  uint16_t possible;
 
-  GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct 
GNUNET_SCALARPRODUCT_client_request)
-                 +element_count * sizeof (int32_t)
-                 + mask_bytes);
-
   h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle);
   h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg);
   if (!h->client)
@@ -451,49 +502,60 @@
       return NULL;
     }
 
-  size = sizeof (struct GNUNET_SCALARPRODUCT_client_request) + element_count * 
sizeof (int32_t) + mask_bytes;
-
+  h->element_count_total = element_count;
+  size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + 
element_count * sizeof (struct GNUNET_SCALARPRODUCT_Element);
+  if (GNUNET_SERVER_MAX_MESSAGE_SIZE > size) {
+    possible = element_count;
+    h->element_count_transfered = element_count;
+  }
+  else {
+    //create a multipart msg, first we calculate a new msg size for the head 
msg
+    possible = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct 
GNUNET_SCALARPRODUCT_computation_message)) / sizeof (struct 
GNUNET_SCALARPRODUCT_Element);
+    h->element_count_transfered = possible;
+    size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + 
possible*sizeof (struct GNUNET_SCALARPRODUCT_Element);
+    h->elements = (struct GNUNET_SCALARPRODUCT_Element*) 
+            GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element) * 
element_count);
+    memcpy (h->elements, elements, sizeof (struct 
GNUNET_SCALARPRODUCT_Element)*element_count);
+  }
+  
   h->cont_datum = cont;
   h->cont_cls = cont_cls;
   h->response_proc = &process_result_message;
   h->cfg = cfg;
-  memcpy (&h->key, key, sizeof (struct GNUNET_HashCode));
+  memcpy (&h->key, session_key, sizeof (struct GNUNET_HashCode));
 
-  msg = (struct GNUNET_SCALARPRODUCT_client_request*) GNUNET_malloc (size);
+  msg = (struct GNUNET_SCALARPRODUCT_computation_message*) GNUNET_malloc 
(size);
   h->msg = msg;
   msg->header.size = htons (size);
   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE);
-  msg->element_count = htonl (element_count);
-  msg->mask_length = htonl (mask_bytes);
+  msg->element_count_total = htonl (element_count);
+  msg->element_count_contained = htonl (possible);
 
-  vector = (int32_t*) & msg[1];
-  // copy each element over to the message
-  for (i = 0; i < element_count; i++)
-    vector[i] = htonl (elements[i]);
-
   memcpy (&msg->peer, peer, sizeof (struct GNUNET_PeerIdentity));
-  memcpy (&msg->key, key, sizeof (struct GNUNET_HashCode));
-  memcpy (&vector[element_count], mask, mask_bytes);
+  memcpy (&msg->session_key, session_key, sizeof (struct GNUNET_HashCode));
+  memcpy (&msg[1], elements, possible);
 
   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size,
                                                GNUNET_TIME_UNIT_FOREVER_REL,
                                                GNUNET_YES, // retry is OK in 
the initial stage
-                                               &transmit_request, h);
+                                               &do_send_message, h);
   if (!h->th)
     {
       LOG (GNUNET_ERROR_TYPE_ERROR,
            _ ("Failed to send a message to the scalarproduct service\n"));
+      GNUNET_STATISTICS_update (h->stats,
+                              gettext_noop ("# transmission request failures"),
+                              1, GNUNET_NO);
       GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES);
       GNUNET_CLIENT_disconnect (h->client);
       GNUNET_free (h->msg);
+      GNUNET_free_non_null (h->elements);
       GNUNET_free (h);
       return NULL;
     }
-  GNUNET_CONTAINER_DLL_insert (head, tail, h);
   return h;
 }
 
-
 /**
  * Cancel an ongoing computation or revoke our collaboration offer.
  * Closes the connection to the service
@@ -503,43 +565,16 @@
 void
 GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle * h)
 {
-  struct GNUNET_SCALARPRODUCT_ComputationHandle * qe;
-
-  for (qe = head; head != NULL; qe = head)
-    {
-      if (qe == h)
-        {
-          GNUNET_CONTAINER_DLL_remove (head, tail, qe);
-          if (NULL != qe->th)
-            GNUNET_CLIENT_notify_transmit_ready_cancel (qe->th);
-          GNUNET_CLIENT_disconnect (qe->client);
-          GNUNET_STATISTICS_destroy (qe->stats, GNUNET_YES);
-          GNUNET_free_non_null (qe->msg);
-          GNUNET_free (qe);
-          break;
-        }
-    }
+  if (NULL != h->th)
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+  if (GNUNET_SCHEDULER_NO_TASK != h->cont_multipart)
+    GNUNET_SCHEDULER_cancel (h->cont_multipart);
+  GNUNET_free_non_null (h->elements);
+  GNUNET_free_non_null (h->msg);
+  GNUNET_CLIENT_disconnect (h->client);
+  GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES);
+  GNUNET_free (h);
 }
-/**
- * Cancel ALL ongoing computation or revoke our collaboration offer.
- * Closes ALL connections to the service
- */
-void
-GNUNET_SCALARPRODUCT_disconnect ()
-{
-    struct GNUNET_SCALARPRODUCT_ComputationHandle * qe;
 
-    LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting from VectorProduct\n");
-    for (qe = head; head != NULL; qe = head)
-    {
-        GNUNET_CONTAINER_DLL_remove (head, tail, qe);
-        if (NULL != qe->th)
-            GNUNET_CLIENT_notify_transmit_ready_cancel (qe->th);
-        GNUNET_CLIENT_disconnect (qe->client);
-        GNUNET_STATISTICS_destroy (qe->stats, GNUNET_YES);
-        GNUNET_free_non_null (qe->msg);
-        GNUNET_free (qe);
-    }
-}
 
 /* end of scalarproduct_api.c */

Modified: gnunet/src/set/gnunet-service-set_intersection.c
===================================================================
--- gnunet/src/set/gnunet-service-set_intersection.c    2014-05-07 07:32:26 UTC 
(rev 33176)
+++ gnunet/src/set/gnunet-service-set_intersection.c    2014-05-07 08:21:49 UTC 
(rev 33177)
@@ -766,7 +766,7 @@
 
 
 /**
- * Send our element to the peer, in case our element count is lower than his
+ * Send our element count to the peer, in case our element count is lower than 
his
  *
  * @param op intersection operation
  */




reply via email to

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