-fix (C) notices
[oweals/gnunet.git] / src / scalarproduct / gnunet-service-scalarproduct_alice.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013, 2014 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19  */
20 /**
21  * @file scalarproduct/gnunet-service-scalarproduct_alice.c
22  * @brief scalarproduct service implementation
23  * @author Christian M. Fuchs
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include <limits.h>
28 #include <gcrypt.h>
29 #include "gnunet_util_lib.h"
30 #include "gnunet_core_service.h"
31 #include "gnunet_cadet_service.h"
32 #include "gnunet_applications.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_scalarproduct_service.h"
35 #include "gnunet_set_service.h"
36 #include "scalarproduct.h"
37 #include "gnunet-service-scalarproduct.h"
38
39 #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct-alice", __VA_ARGS__)
40
41 /**
42  * An encrypted element key-value pair.
43  */
44 struct MpiElement
45 {
46   /**
47    * Key used to identify matching pairs of values to multiply.
48    * Points into an existing data structure, to avoid copying
49    * and doubling memory use.
50    */
51   const struct GNUNET_HashCode *key;
52
53   /**
54    * Value represented (a).
55    */
56   gcry_mpi_t value;
57 };
58
59
60 /**
61  * A scalarproduct session which tracks
62  * a request form the client to our final response.
63  */
64 struct AliceServiceSession
65 {
66
67   /**
68    * (hopefully) unique transaction ID
69    */
70   struct GNUNET_HashCode session_id;
71
72   /**
73    * Alice or Bob's peerID
74    */
75   struct GNUNET_PeerIdentity peer;
76
77   /**
78    * The client this request is related to.
79    */
80   struct GNUNET_SERVER_Client *client;
81
82   /**
83    * The message queue for the client.
84    */
85   struct GNUNET_MQ_Handle *client_mq;
86
87   /**
88    * The message queue for CADET.
89    */
90   struct GNUNET_MQ_Handle *cadet_mq;
91
92   /**
93    * all non-0-value'd elements transmitted to us.
94    * Values are of type `struct GNUNET_SCALARPRODUCT_Element *`
95    */
96   struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
97
98   /**
99    * Set of elements for which will conduction an intersection.
100    * the resulting elements are then used for computing the scalar product.
101    */
102   struct GNUNET_SET_Handle *intersection_set;
103
104   /**
105    * Set of elements for which will conduction an intersection.
106    * the resulting elements are then used for computing the scalar product.
107    */
108   struct GNUNET_SET_OperationHandle *intersection_op;
109
110   /**
111    * Handle to Alice's Intersection operation listening for Bob
112    */
113   struct GNUNET_SET_ListenHandle *intersection_listen;
114
115   /**
116    * channel-handle associated with our cadet handle
117    */
118   struct GNUNET_CADET_Channel *channel;
119
120   /**
121    * a(Alice), sorted array by key of length @e used_element_count.
122    */
123   struct MpiElement *sorted_elements;
124
125   /**
126    * Bob's permutation p of R
127    */
128   struct GNUNET_CRYPTO_PaillierCiphertext *r;
129
130   /**
131    * Bob's permutation q of R
132    */
133   struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
134
135   /**
136    * Bob's "s"
137    */
138   struct GNUNET_CRYPTO_PaillierCiphertext s;
139
140   /**
141    * Bob's "s'"
142    */
143   struct GNUNET_CRYPTO_PaillierCiphertext s_prime;
144
145   /**
146    * The computed scalar
147    */
148   gcry_mpi_t product;
149
150   /**
151    * How many elements we were supplied with from the client (total
152    * count before intersection).
153    */
154   uint32_t total;
155
156   /**
157    * How many elements actually are used for the scalar product.
158    * Size of the arrays in @e r and @e r_prime.  Sometimes also
159    * reset to 0 and used as a counter!
160    */
161   uint32_t used_element_count;
162
163   /**
164    * Already transferred elements from client to us.
165    * Less or equal than @e total.
166    */
167   uint32_t client_received_element_count;
168
169   /**
170    * Already transferred elements from Bob to us.
171    * Less or equal than @e total.
172    */
173   uint32_t cadet_received_element_count;
174
175   /**
176    * State of this session.   In
177    * #GNUNET_SCALARPRODUCT_STATUS_ACTIVE while operation is
178    * ongoing, afterwards in #GNUNET_SCALARPRODUCT_STATUS_SUCCESS or
179    * #GNUNET_SCALARPRODUCT_STATUS_FAILURE.
180    */
181   enum GNUNET_SCALARPRODUCT_ResponseStatus status;
182
183   /**
184    * Flag to prevent recursive calls to #destroy_service_session() from
185    * doing harm.
186    */
187   int in_destroy;
188
189 };
190
191
192 /**
193  * GNUnet configuration handle
194  */
195 static const struct GNUNET_CONFIGURATION_Handle *cfg;
196
197 /**
198  * Service's own public key
199  */
200 static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey;
201
202 /**
203  * Service's own private key
204  */
205 static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey;
206
207 /**
208  * Service's offset for values that could possibly be negative but are plaintext for encryption.
209  */
210 static gcry_mpi_t my_offset;
211
212 /**
213  * Handle to the CADET service.
214  */
215 static struct GNUNET_CADET_Handle *my_cadet;
216
217
218 /**
219  * Iterator called to free elements.
220  *
221  * @param cls the `struct AliceServiceSession *` (unused)
222  * @param key the key (unused)
223  * @param value value to free
224  * @return #GNUNET_OK (continue to iterate)
225  */
226 static int
227 free_element_cb (void *cls,
228                  const struct GNUNET_HashCode *key,
229                  void *value)
230 {
231   struct GNUNET_SCALARPRODUCT_Element *e = value;
232
233   GNUNET_free (e);
234   return GNUNET_OK;
235 }
236
237
238 /**
239  * Destroy session state, we are done with it.
240  *
241  * @param s the session to free elements from
242  */
243 static void
244 destroy_service_session (struct AliceServiceSession *s)
245 {
246   unsigned int i;
247
248   if (GNUNET_YES == s->in_destroy)
249     return;
250   s->in_destroy = GNUNET_YES;
251   if (NULL != s->client_mq)
252   {
253     GNUNET_MQ_destroy (s->client_mq);
254     s->client_mq = NULL;
255   }
256   if (NULL != s->cadet_mq)
257   {
258     GNUNET_MQ_destroy (s->cadet_mq);
259     s->cadet_mq = NULL;
260   }
261   if (NULL != s->client)
262   {
263     GNUNET_SERVER_client_set_user_context (s->client,
264                                            NULL);
265     GNUNET_SERVER_client_disconnect (s->client);
266     s->client = NULL;
267   }
268   if (NULL != s->channel)
269   {
270     GNUNET_CADET_channel_destroy (s->channel);
271     s->channel = NULL;
272   }
273   if (NULL != s->intersected_elements)
274   {
275     GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
276                                            &free_element_cb,
277                                            s);
278     GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
279     s->intersected_elements = NULL;
280   }
281   if (NULL != s->intersection_listen)
282   {
283     GNUNET_SET_listen_cancel (s->intersection_listen);
284     s->intersection_listen = NULL;
285   }
286   if (NULL != s->intersection_op)
287   {
288     GNUNET_SET_operation_cancel (s->intersection_op);
289     s->intersection_op = NULL;
290   }
291   if (NULL != s->intersection_set)
292   {
293     GNUNET_SET_destroy (s->intersection_set);
294     s->intersection_set = NULL;
295   }
296   if (NULL != s->sorted_elements)
297   {
298     for (i=0;i<s->used_element_count;i++)
299       gcry_mpi_release (s->sorted_elements[i].value);
300     GNUNET_free (s->sorted_elements);
301     s->sorted_elements = NULL;
302   }
303   if (NULL != s->r)
304   {
305     GNUNET_free (s->r);
306     s->r = NULL;
307   }
308   if (NULL != s->r_prime)
309   {
310     GNUNET_free (s->r_prime);
311     s->r_prime = NULL;
312   }
313   if (NULL != s->product)
314   {
315     gcry_mpi_release (s->product);
316     s->product = NULL;
317   }
318   GNUNET_free (s);
319 }
320
321
322 /**
323  * Notify the client that the session has failed.  A message gets sent
324  * to Alice's client if we encountered any error.
325  *
326  * @param session the associated client session to fail or succeed
327  */
328 static void
329 prepare_client_end_notification (struct AliceServiceSession *session)
330 {
331   struct ClientResponseMessage *msg;
332   struct GNUNET_MQ_Envelope *e;
333
334   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
335               "Sending session-end notification with status %d to client for session %s\n",
336               session->status,
337               GNUNET_h2s (&session->session_id));
338   e = GNUNET_MQ_msg (msg,
339                      GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
340   msg->product_length = htonl (0);
341   msg->status = htonl (session->status);
342   GNUNET_MQ_send (session->client_mq,
343                   e);
344 }
345
346
347 /**
348  * Prepare the final (positive) response we will send to Alice's
349  * client.
350  *
351  * @param s the session associated with our client.
352  */
353 static void
354 transmit_client_response (struct AliceServiceSession *s)
355 {
356   struct ClientResponseMessage *msg;
357   struct GNUNET_MQ_Envelope *e;
358   unsigned char *product_exported = NULL;
359   size_t product_length = 0;
360   int32_t range;
361   gcry_error_t rc;
362   int sign;
363   gcry_mpi_t value;
364
365   if (NULL == s->product)
366   {
367     GNUNET_break (0);
368     prepare_client_end_notification (s);
369     return;
370   }
371   value = gcry_mpi_new (0);
372   sign = gcry_mpi_cmp_ui (s->product, 0);
373   if (0 > sign)
374   {
375     range = -1;
376     gcry_mpi_sub (value,
377                   value,
378                   s->product);
379   }
380   else if (0 < sign)
381   {
382     range = 1;
383     gcry_mpi_add (value, value, s->product);
384   }
385   else
386   {
387     /* result is exactly zero */
388     range = 0;
389   }
390   gcry_mpi_release (s->product);
391   s->product = NULL;
392
393   if ( (0 != range) &&
394        (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
395                                     &product_exported,
396                                     &product_length,
397                                     value))))
398   {
399     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
400               "gcry_mpi_scan",
401               rc);
402     prepare_client_end_notification (s);
403     return;
404   }
405   gcry_mpi_release (value);
406   e = GNUNET_MQ_msg_extra (msg,
407                            product_length,
408                            GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
409   msg->status = htonl (GNUNET_SCALARPRODUCT_STATUS_SUCCESS);
410   msg->range = htonl (range);
411   msg->product_length = htonl (product_length);
412   if (NULL != product_exported)
413   {
414     memcpy (&msg[1],
415             product_exported,
416             product_length);
417     GNUNET_free (product_exported);
418   }
419   GNUNET_MQ_send (s->client_mq,
420                   e);
421   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
422               "Sent result to client, session %s has ended!\n",
423               GNUNET_h2s (&s->session_id));
424 }
425
426
427
428 /**
429  * Function called whenever a channel is destroyed.  Should clean up
430  * any associated state.
431  *
432  * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
433  *
434  * @param cls closure (set from #GNUNET_CADET_connect())
435  * @param channel connection to the other end (henceforth invalid)
436  * @param channel_ctx place where local state associated
437  *                   with the channel is stored
438  */
439 static void
440 cb_channel_destruction (void *cls,
441                         const struct GNUNET_CADET_Channel *channel,
442                         void *channel_ctx)
443 {
444   struct AliceServiceSession *s = channel_ctx;
445
446   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
447               "Peer disconnected, terminating session %s with peer %s\n",
448               GNUNET_h2s (&s->session_id),
449               GNUNET_i2s (&s->peer));
450   if (NULL != s->cadet_mq)
451   {
452     GNUNET_MQ_destroy (s->cadet_mq);
453     s->cadet_mq = NULL;
454   }
455   s->channel = NULL;
456   if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
457   {
458     /* We didn't get an answer yet, fail with error */
459     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
460     prepare_client_end_notification (s);
461   }
462 }
463
464
465 /**
466  * Computes the square sum over a vector of a given length.
467  *
468  * @param vector the vector to compute over
469  * @param length the length of the vector
470  * @return an MPI value containing the calculated sum, never NULL
471  */
472 static gcry_mpi_t
473 compute_square_sum_mpi_elements (const struct MpiElement *vector,
474                                  uint32_t length)
475 {
476   gcry_mpi_t elem;
477   gcry_mpi_t sum;
478   uint32_t i;
479
480   GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
481   GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
482   for (i = 0; i < length; i++)
483   {
484     gcry_mpi_mul (elem, vector[i].value, vector[i].value);
485     gcry_mpi_add (sum, sum, elem);
486   }
487   gcry_mpi_release (elem);
488   return sum;
489 }
490
491
492 /**
493  * Computes the square sum over a vector of a given length.
494  *
495  * @param vector the vector to compute over
496  * @param length the length of the vector
497  * @return an MPI value containing the calculated sum, never NULL
498  */
499 static gcry_mpi_t
500 compute_square_sum (const gcry_mpi_t *vector,
501                     uint32_t length)
502 {
503   gcry_mpi_t elem;
504   gcry_mpi_t sum;
505   uint32_t i;
506
507   GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
508   GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
509   for (i = 0; i < length; i++)
510   {
511     gcry_mpi_mul (elem, vector[i], vector[i]);
512     gcry_mpi_add (sum, sum, elem);
513   }
514   gcry_mpi_release (elem);
515   return sum;
516 }
517
518
519 /**
520  * Compute our scalar product, done by Alice
521  *
522  * @param session the session associated with this computation
523  * @return product as MPI, never NULL
524  */
525 static gcry_mpi_t
526 compute_scalar_product (struct AliceServiceSession *session)
527 {
528   uint32_t count;
529   gcry_mpi_t t;
530   gcry_mpi_t u;
531   gcry_mpi_t u_prime;
532   gcry_mpi_t p;
533   gcry_mpi_t p_prime;
534   gcry_mpi_t tmp;
535   gcry_mpi_t r[session->used_element_count];
536   gcry_mpi_t r_prime[session->used_element_count];
537   gcry_mpi_t s;
538   gcry_mpi_t s_prime;
539   unsigned int i;
540
541   count = session->used_element_count;
542   // due to the introduced static offset S, we now also have to remove this
543   // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
544   // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
545   for (i = 0; i < count; i++)
546   {
547     r[i] = gcry_mpi_new (0);
548     GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
549                                     &my_pubkey,
550                                     &session->r[i],
551                                     r[i]);
552     gcry_mpi_sub (r[i],
553                   r[i],
554                   my_offset);
555     gcry_mpi_sub (r[i],
556                   r[i],
557                   my_offset);
558     r_prime[i] = gcry_mpi_new (0);
559     GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
560                                     &my_pubkey,
561                                     &session->r_prime[i],
562                                     r_prime[i]);
563     gcry_mpi_sub (r_prime[i],
564                   r_prime[i],
565                   my_offset);
566     gcry_mpi_sub (r_prime[i],
567                   r_prime[i],
568                   my_offset);
569   }
570
571   // calculate t = sum(ai)
572   t = compute_square_sum_mpi_elements (session->sorted_elements,
573                                        count);
574   // calculate U
575   u = gcry_mpi_new (0);
576   tmp = compute_square_sum (r, count);
577   gcry_mpi_sub (u, u, tmp);
578   gcry_mpi_release (tmp);
579
580   //calculate U'
581   u_prime = gcry_mpi_new (0);
582   tmp = compute_square_sum (r_prime, count);
583   gcry_mpi_sub (u_prime, u_prime, tmp);
584
585   GNUNET_assert (p = gcry_mpi_new (0));
586   GNUNET_assert (p_prime = gcry_mpi_new (0));
587   GNUNET_assert (s = gcry_mpi_new (0));
588   GNUNET_assert (s_prime = gcry_mpi_new (0));
589
590   // compute P
591   GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
592                                   &my_pubkey,
593                                   &session->s,
594                                   s);
595   GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
596                                   &my_pubkey,
597                                   &session->s_prime,
598                                   s_prime);
599
600   // compute P
601   gcry_mpi_add (p, s, t);
602   gcry_mpi_add (p, p, u);
603
604   // compute P'
605   gcry_mpi_add (p_prime, s_prime, t);
606   gcry_mpi_add (p_prime, p_prime, u_prime);
607
608   gcry_mpi_release (t);
609   gcry_mpi_release (u);
610   gcry_mpi_release (u_prime);
611   gcry_mpi_release (s);
612   gcry_mpi_release (s_prime);
613
614   // compute product
615   gcry_mpi_sub (p, p, p_prime);
616   gcry_mpi_release (p_prime);
617   tmp = gcry_mpi_set_ui (tmp, 2);
618   gcry_mpi_div (p, NULL, p, tmp, 0);
619
620   gcry_mpi_release (tmp);
621   for (i = 0; i < count; i++)
622   {
623     gcry_mpi_release (session->sorted_elements[i].value);
624     gcry_mpi_release (r[i]);
625     gcry_mpi_release (r_prime[i]);
626   }
627   GNUNET_free (session->sorted_elements);
628   session->sorted_elements = NULL;
629   GNUNET_free (session->r);
630   session->r = NULL;
631   GNUNET_free (session->r_prime);
632   session->r_prime = NULL;
633
634   return p;
635 }
636
637
638 /**
639  * Handle a multipart chunk of a response we got from another service
640  * we wanted to calculate a scalarproduct with.
641  *
642  * @param cls closure (set from #GNUNET_CADET_connect)
643  * @param channel connection to the other end
644  * @param channel_ctx place to store local state associated with the @a channel
645  * @param message the actual message
646  * @return #GNUNET_OK to keep the connection open,
647  *         #GNUNET_SYSERR to close it (signal serious error)
648  */
649 static int
650 handle_bobs_cryptodata_multipart (void *cls,
651                                   struct GNUNET_CADET_Channel *channel,
652                                   void **channel_ctx,
653                                   const struct GNUNET_MessageHeader *message)
654 {
655   struct AliceServiceSession *s = *channel_ctx;
656   const struct BobCryptodataMultipartMessage *msg;
657   const struct GNUNET_CRYPTO_PaillierCiphertext *payload;
658   size_t i;
659   uint32_t contained;
660   size_t msg_size;
661   size_t required_size;
662
663   if (NULL == s)
664   {
665     GNUNET_break_op (0);
666     return GNUNET_SYSERR;
667   }
668   msg_size = ntohs (message->size);
669   if (sizeof (struct BobCryptodataMultipartMessage) > msg_size)
670   {
671     GNUNET_break_op (0);
672     return GNUNET_SYSERR;
673   }
674   msg = (const struct BobCryptodataMultipartMessage *) message;
675   contained = ntohl (msg->contained_element_count);
676   required_size = sizeof (struct BobCryptodataMultipartMessage)
677     + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
678   if ( (required_size != msg_size) ||
679        (s->cadet_received_element_count + contained > s->used_element_count) )
680   {
681     GNUNET_break (0);
682     return GNUNET_SYSERR;
683   }
684
685   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
686               "Received %u additional crypto values from Bob\n",
687               (unsigned int) contained);
688
689   payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
690   /* Convert each k[][perm] to its MPI_value */
691   for (i = 0; i < contained; i++)
692   {
693     memcpy (&s->r[s->cadet_received_element_count + i],
694             &payload[2 * i],
695             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
696     memcpy (&s->r_prime[s->cadet_received_element_count + i],
697             &payload[2 * i],
698             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
699   }
700   s->cadet_received_element_count += contained;
701   GNUNET_CADET_receive_done (s->channel);
702   if (s->cadet_received_element_count != s->used_element_count)
703     return GNUNET_OK;
704
705   s->product = compute_scalar_product (s);
706   transmit_client_response (s);
707   return GNUNET_OK;
708 }
709
710
711 /**
712  * Handle a response we got from another service we wanted to
713  * calculate a scalarproduct with.
714  *
715  * @param cls closure (set from #GNUNET_CADET_connect)
716  * @param channel connection to the other end
717  * @param channel_ctx place to store local state associated with the channel
718  * @param message the actual message
719  * @return #GNUNET_OK to keep the connection open,
720  *         #GNUNET_SYSERR to close it (we are done)
721  */
722 static int
723 handle_bobs_cryptodata_message (void *cls,
724                                 struct GNUNET_CADET_Channel *channel,
725                                 void **channel_ctx,
726                                 const struct GNUNET_MessageHeader *message)
727 {
728   struct AliceServiceSession *s = *channel_ctx;
729   const struct BobCryptodataMessage *msg;
730   const struct GNUNET_CRYPTO_PaillierCiphertext *payload;
731   uint32_t i;
732   uint32_t contained;
733   uint16_t msg_size;
734   size_t required_size;
735
736   if (NULL == s)
737   {
738     GNUNET_break_op (0);
739     return GNUNET_SYSERR;
740   }
741   msg_size = ntohs (message->size);
742   if (sizeof (struct BobCryptodataMessage) > msg_size)
743   {
744     GNUNET_break_op (0);
745     return GNUNET_SYSERR;
746   }
747   msg = (const struct BobCryptodataMessage *) message;
748   contained = ntohl (msg->contained_element_count);
749   required_size = sizeof (struct BobCryptodataMessage)
750     + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)
751     + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
752   if ( (msg_size != required_size) ||
753        (contained > UINT16_MAX) ||
754        (s->used_element_count < contained) )
755   {
756     GNUNET_break_op (0);
757     return GNUNET_SYSERR;
758   }
759   if (NULL == s->sorted_elements)
760   {
761     /* we're not ready yet, how can Bob be? */
762     GNUNET_break_op (0);
763     return GNUNET_SYSERR;
764   }
765   if (s->total != s->client_received_element_count)
766   {
767     /* we're not ready yet, how can Bob be? */
768     GNUNET_break_op (0);
769     return GNUNET_SYSERR;
770   }
771   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
772               "Received %u crypto values from Bob\n",
773               (unsigned int) contained);
774
775   payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
776   memcpy (&s->s,
777           &payload[0],
778           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
779   memcpy (&s->s_prime,
780           &payload[1],
781           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
782   payload = &payload[2];
783
784   s->r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
785   s->r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
786   for (i = 0; i < contained; i++)
787   {
788     memcpy (&s->r[i],
789             &payload[2 * i],
790             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
791     memcpy (&s->r_prime[i],
792             &payload[2 * i + 1],
793             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
794   }
795   s->cadet_received_element_count = contained;
796   GNUNET_CADET_receive_done (s->channel);
797
798   if (s->cadet_received_element_count != s->used_element_count)
799   {
800     /* More to come */
801     return GNUNET_OK;
802   }
803
804   s->product = compute_scalar_product (s);
805   transmit_client_response (s);
806   return GNUNET_OK;
807 }
808
809
810 /**
811  * Iterator to copy over messages from the hash map
812  * into an array for sorting.
813  *
814  * @param cls the `struct AliceServiceSession *`
815  * @param key the key (unused)
816  * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
817  */
818 static int
819 copy_element_cb (void *cls,
820                  const struct GNUNET_HashCode *key,
821                  void *value)
822 {
823   struct AliceServiceSession *s = cls;
824   struct GNUNET_SCALARPRODUCT_Element *e = value;
825   gcry_mpi_t mval;
826   int64_t val;
827
828   mval = gcry_mpi_new (0);
829   val = (int64_t) GNUNET_ntohll (e->value);
830   if (0 > val)
831     gcry_mpi_sub_ui (mval, mval, -val);
832   else
833     gcry_mpi_add_ui (mval, mval, val);
834   s->sorted_elements [s->used_element_count].value = mval;
835   s->sorted_elements [s->used_element_count].key = &e->key;
836   s->used_element_count++;
837   return GNUNET_OK;
838 }
839
840
841 /**
842  * Compare two `struct MpiValue`s by key for sorting.
843  *
844  * @param a pointer to first `struct MpiValue *`
845  * @param b pointer to first `struct MpiValue *`
846  * @return -1 for a < b, 0 for a=b, 1 for a > b.
847  */
848 static int
849 element_cmp (const void *a,
850              const void *b)
851 {
852   const struct MpiElement *ma = a;
853   const struct MpiElement *mb = b;
854
855   return GNUNET_CRYPTO_hash_cmp (ma->key,
856                                  mb->key);
857 }
858
859
860 /**
861  * Maximum number of elements we can put into a single cryptodata
862  * message
863  */
864 #define ELEMENT_CAPACITY ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 - sizeof (struct AliceCryptodataMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
865
866
867 /**
868  * Send the cryptographic data from Alice to Bob.
869  * Does nothing if we already transferred all elements.
870  *
871  * @param s the associated service session
872  */
873 static void
874 send_alices_cryptodata_message (struct AliceServiceSession *s)
875 {
876   struct AliceCryptodataMessage *msg;
877   struct GNUNET_MQ_Envelope *e;
878   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
879   unsigned int i;
880   uint32_t todo_count;
881   gcry_mpi_t a;
882   uint32_t off;
883
884   s->sorted_elements
885     = GNUNET_malloc (GNUNET_CONTAINER_multihashmap_size (s->intersected_elements) *
886                      sizeof (struct MpiElement));
887   s->used_element_count = 0;
888   GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
889                                          &copy_element_cb,
890                                          s);
891   LOG (GNUNET_ERROR_TYPE_DEBUG,
892        "Finished intersection, %d items remain\n",
893        s->used_element_count);
894   qsort (s->sorted_elements,
895          s->used_element_count,
896          sizeof (struct MpiElement),
897          &element_cmp);
898   off = 0;
899   while (off < s->used_element_count)
900   {
901     todo_count = s->used_element_count - off;
902     if (todo_count > ELEMENT_CAPACITY)
903       todo_count = ELEMENT_CAPACITY;
904     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
905                 "Sending %u/%u crypto values to Bob\n",
906                 (unsigned int) todo_count,
907                 (unsigned int) s->used_element_count);
908
909     e = GNUNET_MQ_msg_extra (msg,
910                              todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext),
911                              GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA);
912     msg->contained_element_count = htonl (todo_count);
913     payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
914     a = gcry_mpi_new (0);
915     for (i = off; i < off + todo_count; i++)
916     {
917       gcry_mpi_add (a,
918                     s->sorted_elements[i].value,
919                     my_offset);
920       GNUNET_assert (3 ==
921                      GNUNET_CRYPTO_paillier_encrypt (&my_pubkey,
922                                                      a,
923                                                      3,
924                                                      &payload[i - off]));
925     }
926     gcry_mpi_release (a);
927     off += todo_count;
928     GNUNET_MQ_send (s->cadet_mq,
929                     e);
930   }
931 }
932
933
934 /**
935  * Callback for set operation results. Called for each element
936  * that should be removed from the result set, and then once
937  * to indicate that the set intersection operation is done.
938  *
939  * @param cls closure with the `struct AliceServiceSession`
940  * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
941  * @param status what has happened with the set intersection?
942  */
943 static void
944 cb_intersection_element_removed (void *cls,
945                                  const struct GNUNET_SET_Element *element,
946                                  enum GNUNET_SET_Status status)
947 {
948   struct AliceServiceSession *s = cls;
949   struct GNUNET_SCALARPRODUCT_Element *se;
950
951   switch (status)
952   {
953   case GNUNET_SET_STATUS_OK:
954     /* this element has been removed from the set */
955     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
956                                             element->data);
957     GNUNET_assert (NULL != se);
958     LOG (GNUNET_ERROR_TYPE_DEBUG,
959          "Intersection removed element with key %s and value %lld\n",
960          GNUNET_h2s (&se->key),
961          (long long) GNUNET_ntohll (se->value));
962     GNUNET_assert (GNUNET_YES ==
963                    GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
964                                                          element->data,
965                                                          se));
966     GNUNET_free (se);
967     return;
968   case GNUNET_SET_STATUS_DONE:
969     s->intersection_op = NULL;
970     if (NULL != s->intersection_set)
971     {
972       GNUNET_SET_destroy (s->intersection_set);
973       s->intersection_set = NULL;
974     }
975     send_alices_cryptodata_message (s);
976     return;
977   case GNUNET_SET_STATUS_HALF_DONE:
978     /* unexpected for intersection */
979     GNUNET_break (0);
980     return;
981   case GNUNET_SET_STATUS_FAILURE:
982     /* unhandled status code */
983     LOG (GNUNET_ERROR_TYPE_DEBUG,
984          "Set intersection failed!\n");
985     if (NULL != s->intersection_listen)
986     {
987       GNUNET_SET_listen_cancel (s->intersection_listen);
988       s->intersection_listen = NULL;
989     }
990     s->intersection_op = NULL;
991     if (NULL != s->intersection_set)
992     {
993       GNUNET_SET_destroy (s->intersection_set);
994       s->intersection_set = NULL;
995     }
996     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
997     prepare_client_end_notification (s);
998     return;
999   default:
1000     GNUNET_break (0);
1001     return;
1002   }
1003 }
1004
1005
1006 /**
1007  * Called when another peer wants to do a set operation with the
1008  * local peer. If a listen error occurs, the @a request is NULL.
1009  *
1010  * @param cls closure with the `struct AliceServiceSession *`
1011  * @param other_peer the other peer
1012  * @param context_msg message with application specific information from
1013  *        the other peer
1014  * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
1015  *        to accept it, otherwise the request will be refused
1016  *        Note that we can't just return value from the listen callback,
1017  *        as it is also necessary to specify the set we want to do the
1018  *        operation with, whith sometimes can be derived from the context
1019  *        message. It's necessary to specify the timeout.
1020  */
1021 static void
1022 cb_intersection_request_alice (void *cls,
1023                                const struct GNUNET_PeerIdentity *other_peer,
1024                                const struct GNUNET_MessageHeader *context_msg,
1025                                struct GNUNET_SET_Request *request)
1026 {
1027   struct AliceServiceSession *s = cls;
1028
1029   if (0 != memcmp (other_peer,
1030                    &s->peer,
1031                    sizeof (struct GNUNET_PeerIdentity)))
1032   {
1033     GNUNET_break_op (0);
1034     return;
1035   }
1036   s->intersection_op
1037     = GNUNET_SET_accept (request,
1038                          GNUNET_SET_RESULT_REMOVED,
1039                          &cb_intersection_element_removed,
1040                          s);
1041   if (NULL == s->intersection_op)
1042   {
1043     GNUNET_break (0);
1044     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1045     prepare_client_end_notification (s);
1046     return;
1047   }
1048   if (GNUNET_OK !=
1049       GNUNET_SET_commit (s->intersection_op,
1050                          s->intersection_set))
1051   {
1052     GNUNET_break (0);
1053     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1054     prepare_client_end_notification (s);
1055     return;
1056   }
1057   GNUNET_SET_destroy (s->intersection_set);
1058   s->intersection_set = NULL;
1059   GNUNET_SET_listen_cancel (s->intersection_listen);
1060   s->intersection_listen = NULL;
1061 }
1062
1063
1064 /**
1065  * Our client has finished sending us its multipart message.
1066  *
1067  * @param session the service session context
1068  */
1069 static void
1070 client_request_complete_alice (struct AliceServiceSession *s)
1071 {
1072   struct ServiceRequestMessage *msg;
1073   struct GNUNET_MQ_Envelope *e;
1074
1075   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1076               "Creating new channel for session with key %s.\n",
1077               GNUNET_h2s (&s->session_id));
1078   s->channel
1079     = GNUNET_CADET_channel_create (my_cadet,
1080                                    s,
1081                                    &s->peer,
1082                                    GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
1083                                    GNUNET_CADET_OPTION_RELIABLE);
1084   if (NULL == s->channel)
1085   {
1086     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1087     prepare_client_end_notification (s);
1088     return;
1089   }
1090   s->cadet_mq = GNUNET_CADET_mq_create (s->channel);
1091   s->intersection_listen
1092     = GNUNET_SET_listen (cfg,
1093                          GNUNET_SET_OPERATION_INTERSECTION,
1094                          &s->session_id,
1095                          &cb_intersection_request_alice,
1096                          s);
1097   if (NULL == s->intersection_listen)
1098   {
1099     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1100     GNUNET_CADET_channel_destroy (s->channel);
1101     s->channel = NULL;
1102     prepare_client_end_notification (s);
1103     return;
1104   }
1105
1106   e = GNUNET_MQ_msg (msg,
1107                      GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION);
1108   msg->session_id = s->session_id;
1109   msg->public_key = my_pubkey;
1110   GNUNET_MQ_send (s->cadet_mq,
1111                   e);
1112 }
1113
1114
1115 /**
1116  * We're receiving additional set data. Add it to our
1117  * set and if we are done, initiate the transaction.
1118  *
1119  * @param cls closure
1120  * @param client identification of the client
1121  * @param message the actual message
1122  */
1123 static void
1124 GSS_handle_alice_client_message_multipart (void *cls,
1125                                            struct GNUNET_SERVER_Client *client,
1126                                            const struct GNUNET_MessageHeader *message)
1127 {
1128   const struct ComputationBobCryptodataMultipartMessage * msg;
1129   struct AliceServiceSession *s;
1130   uint32_t contained_count;
1131   const struct GNUNET_SCALARPRODUCT_Element *elements;
1132   uint32_t i;
1133   uint16_t msize;
1134   struct GNUNET_SET_Element set_elem;
1135   struct GNUNET_SCALARPRODUCT_Element *elem;
1136
1137   s = GNUNET_SERVER_client_get_user_context (client,
1138                                              struct AliceServiceSession);
1139   if (NULL == s)
1140   {
1141     /* session needs to already exist */
1142     GNUNET_break (0);
1143     GNUNET_SERVER_receive_done (client,
1144                                 GNUNET_SYSERR);
1145     return;
1146   }
1147   msize = ntohs (message->size);
1148   if (msize < sizeof (struct ComputationBobCryptodataMultipartMessage))
1149   {
1150     GNUNET_break (0);
1151     GNUNET_SERVER_receive_done (client,
1152                                 GNUNET_SYSERR);
1153     return;
1154   }
1155   msg = (const struct ComputationBobCryptodataMultipartMessage *) message;
1156   contained_count = ntohl (msg->element_count_contained);
1157
1158   if ( (msize != (sizeof (struct ComputationBobCryptodataMultipartMessage) +
1159                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
1160        (0 == contained_count) ||
1161        (s->total == s->client_received_element_count) ||
1162        (s->total < s->client_received_element_count + contained_count) )
1163   {
1164     GNUNET_break_op (0);
1165     GNUNET_SERVER_receive_done (client,
1166                                 GNUNET_SYSERR);
1167     return;
1168   }
1169   s->client_received_element_count += contained_count;
1170   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1171   for (i = 0; i < contained_count; i++)
1172   {
1173     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1174     memcpy (elem,
1175             &elements[i],
1176             sizeof (struct GNUNET_SCALARPRODUCT_Element));
1177     if (GNUNET_SYSERR ==
1178         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1179                                            &elem->key,
1180                                            elem,
1181                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1182     {
1183       GNUNET_break (0);
1184       GNUNET_free (elem);
1185       continue;
1186     }
1187     set_elem.data = &elem->key;
1188     set_elem.size = sizeof (elem->key);
1189     set_elem.element_type = 0;
1190     GNUNET_SET_add_element (s->intersection_set,
1191                             &set_elem,
1192                             NULL, NULL);
1193     s->used_element_count++;
1194   }
1195   GNUNET_SERVER_receive_done (client,
1196                               GNUNET_OK);
1197   if (s->total != s->client_received_element_count)
1198   {
1199     /* more to come */
1200     return;
1201   }
1202   client_request_complete_alice (s);
1203 }
1204
1205
1206 /**
1207  * Handler for Alice's client request message.
1208  * We are doing request-initiation to compute a scalar product with a peer.
1209  *
1210  * @param cls closure
1211  * @param client identification of the client
1212  * @param message the actual message
1213  */
1214 static void
1215 GSS_handle_alice_client_message (void *cls,
1216                                  struct GNUNET_SERVER_Client *client,
1217                                  const struct GNUNET_MessageHeader *message)
1218 {
1219   const struct AliceComputationMessage *msg;
1220   struct AliceServiceSession *s;
1221   uint32_t contained_count;
1222   uint32_t total_count;
1223   const struct GNUNET_SCALARPRODUCT_Element *elements;
1224   uint32_t i;
1225   uint16_t msize;
1226   struct GNUNET_SET_Element set_elem;
1227   struct GNUNET_SCALARPRODUCT_Element *elem;
1228
1229   s = GNUNET_SERVER_client_get_user_context (client,
1230                                              struct AliceServiceSession);
1231   if (NULL != s)
1232   {
1233     /* only one concurrent session per client connection allowed,
1234        simplifies logic a lot... */
1235     GNUNET_break (0);
1236     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1237     return;
1238   }
1239   msize = ntohs (message->size);
1240   if (msize < sizeof (struct AliceComputationMessage))
1241   {
1242     GNUNET_break (0);
1243     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1244     return;
1245   }
1246   msg = (const struct AliceComputationMessage *) message;
1247   total_count = ntohl (msg->element_count_total);
1248   contained_count = ntohl (msg->element_count_contained);
1249   if ( (0 == total_count) ||
1250        (0 == contained_count) ||
1251        (msize != (sizeof (struct AliceComputationMessage) +
1252                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) )
1253   {
1254     GNUNET_break_op (0);
1255     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1256     return;
1257   }
1258
1259   s = GNUNET_new (struct AliceServiceSession);
1260   s->peer = msg->peer;
1261   s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE;
1262   s->client = client;
1263   s->client_mq = GNUNET_MQ_queue_for_server_client (client);
1264   s->total = total_count;
1265   s->client_received_element_count = contained_count;
1266   s->session_id = msg->session_key;
1267   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1268   s->intersected_elements = GNUNET_CONTAINER_multihashmap_create (s->total,
1269                                                                   GNUNET_YES);
1270   s->intersection_set = GNUNET_SET_create (cfg,
1271                                            GNUNET_SET_OPERATION_INTERSECTION);
1272   for (i = 0; i < contained_count; i++)
1273   {
1274     if (0 == GNUNET_ntohll (elements[i].value))
1275       continue;
1276     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1277     memcpy (elem,
1278             &elements[i],
1279             sizeof (struct GNUNET_SCALARPRODUCT_Element));
1280     if (GNUNET_SYSERR ==
1281         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1282                                            &elem->key,
1283                                            elem,
1284                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1285     {
1286       /* element with same key encountered twice! */
1287       GNUNET_break (0);
1288       GNUNET_free (elem);
1289       continue;
1290     }
1291     set_elem.data = &elem->key;
1292     set_elem.size = sizeof (elem->key);
1293     set_elem.element_type = 0;
1294     GNUNET_SET_add_element (s->intersection_set,
1295                             &set_elem,
1296                             NULL, NULL);
1297     s->used_element_count++;
1298   }
1299   GNUNET_SERVER_client_set_user_context (client,
1300                                          s);
1301   GNUNET_SERVER_receive_done (client,
1302                               GNUNET_OK);
1303   if (s->total != s->client_received_element_count)
1304   {
1305     /* wait for multipart msg */
1306     return;
1307   }
1308   client_request_complete_alice (s);
1309 }
1310
1311
1312 /**
1313  * Task run during shutdown.
1314  *
1315  * @param cls unused
1316  * @param tc unused
1317  */
1318 static void
1319 shutdown_task (void *cls,
1320                const struct GNUNET_SCHEDULER_TaskContext *tc)
1321 {
1322   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1323               "Shutting down, initiating cleanup.\n");
1324   // FIXME: we have to cut our connections to CADET first!
1325   if (NULL != my_cadet)
1326   {
1327     GNUNET_CADET_disconnect (my_cadet);
1328     my_cadet = NULL;
1329   }
1330 }
1331
1332
1333 /**
1334  * A client disconnected.
1335  *
1336  * Remove the associated session(s), release data structures
1337  * and cancel pending outgoing transmissions to the client.
1338  *
1339  * @param cls closure, NULL
1340  * @param client identification of the client
1341  */
1342 static void
1343 handle_client_disconnect (void *cls,
1344                           struct GNUNET_SERVER_Client *client)
1345 {
1346   struct AliceServiceSession *s;
1347
1348   if (NULL == client)
1349     return;
1350   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1351               "Client %p disconnected from us.\n",
1352               client);
1353   s = GNUNET_SERVER_client_get_user_context (client,
1354                                              struct AliceServiceSession);
1355   if (NULL == s)
1356     return;
1357   s->client = NULL;
1358   GNUNET_SERVER_client_set_user_context (client,
1359                                          NULL);
1360   destroy_service_session (s);
1361 }
1362
1363
1364 /**
1365  * Initialization of the program and message handlers
1366  *
1367  * @param cls closure
1368  * @param server the initialized server
1369  * @param c configuration to use
1370  */
1371 static void
1372 run (void *cls,
1373      struct GNUNET_SERVER_Handle *server,
1374      const struct GNUNET_CONFIGURATION_Handle *c)
1375 {
1376   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1377     { &handle_bobs_cryptodata_message,
1378       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA,
1379       0},
1380     { &handle_bobs_cryptodata_multipart,
1381       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART,
1382       0},
1383     { NULL, 0, 0}
1384   };
1385   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1386     { &GSS_handle_alice_client_message, NULL,
1387       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE,
1388       0},
1389     { &GSS_handle_alice_client_message_multipart, NULL,
1390       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART_ALICE,
1391       0},
1392     { NULL, NULL, 0, 0}
1393   };
1394
1395   cfg = c;
1396   /*
1397     offset has to be sufficiently small to allow computation of:
1398     m1+m2 mod n == (S + a) + (S + b) mod n,
1399     if we have more complex operations, this factor needs to be lowered */
1400   my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1401   gcry_mpi_set_bit (my_offset,
1402                     GNUNET_CRYPTO_PAILLIER_BITS / 3);
1403
1404   GNUNET_CRYPTO_paillier_create (&my_pubkey,
1405                                  &my_privkey);
1406   GNUNET_SERVER_add_handlers (server,
1407                               server_handlers);
1408   GNUNET_SERVER_disconnect_notify (server,
1409                                    &handle_client_disconnect,
1410                                    NULL);
1411   my_cadet = GNUNET_CADET_connect (cfg, NULL,
1412                                    NULL /* no incoming supported */,
1413                                    &cb_channel_destruction,
1414                                    cadet_handlers,
1415                                    NULL);
1416   if (NULL == my_cadet)
1417   {
1418     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1419                 _("Connect to CADET failed\n"));
1420     GNUNET_SCHEDULER_shutdown ();
1421     return;
1422   }
1423   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1424                                 &shutdown_task,
1425                                 NULL);
1426
1427 }
1428
1429
1430 /**
1431  * The main function for the scalarproduct service.
1432  *
1433  * @param argc number of arguments from the command line
1434  * @param argv command line arguments
1435  * @return 0 ok, 1 on error
1436  */
1437 int
1438 main (int argc,
1439       char *const *argv)
1440 {
1441   return (GNUNET_OK ==
1442           GNUNET_SERVICE_run (argc, argv,
1443                               "scalarproduct-alice",
1444                               GNUNET_SERVICE_OPTION_NONE,
1445                               &run, NULL)) ? 0 : 1;
1446 }
1447
1448 /* end of gnunet-service-scalarproduct_alice.c */