2 This file is part of GNUnet.
3 Copyright (C) 2013-2017 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
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 Affero General Public License for more details.
16 * @file scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
17 * @brief scalarproduct service implementation
18 * @author Christian M. Fuchs
19 * @author Christian Grothoff
24 #include "gnunet_util_lib.h"
25 #include "gnunet_core_service.h"
26 #include "gnunet_cadet_service.h"
27 #include "gnunet_applications.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_scalarproduct_service.h"
30 #include "gnunet_set_service.h"
31 #include "scalarproduct.h"
32 #include "gnunet-service-scalarproduct-ecc.h"
34 #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct-bob", __VA_ARGS__)
38 * An encrypted element key-value pair.
43 * Key used to identify matching pairs of values to multiply.
44 * Points into an existing data structure, to avoid copying
45 * and doubling memory use.
47 const struct GNUNET_HashCode *key;
50 * Value represented (a).
57 * A scalarproduct session which tracks an offer for a
58 * multiplication service by a local client.
60 struct BobServiceSession
64 * The client this request is related to.
66 struct GNUNET_SERVICE_Client *client;
69 * Client message queue.
71 struct GNUNET_MQ_Handle *client_mq;
74 * All non-0-value'd elements transmitted to us.
76 struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
79 * Set of elements for which we will be conducting an intersection.
80 * The resulting elements are then used for computing the scalar product.
82 struct GNUNET_SET_Handle *intersection_set;
85 * Set of elements for which will conduction an intersection.
86 * the resulting elements are then used for computing the scalar product.
88 struct GNUNET_SET_OperationHandle *intersection_op;
93 struct GNUNET_CADET_Port *port;
98 struct MpiElement *sorted_elements;
101 * Product of the g_i^{b_i}
103 gcry_mpi_point_t prod_g_i_b_i;
106 * Product of the h_i^{b_i}
108 gcry_mpi_point_t prod_h_i_b_i;
111 * How many elements will be supplied in total from the client.
116 * Already transferred elements (received) for multipart
117 * messages from client. Always less than @e total.
119 uint32_t client_received_element_count;
122 * How many elements actually are used for the scalar product.
123 * Size of the arrays in @e r and @e r_prime. Also sometimes
124 * used as an index into the arrays during construction.
126 uint32_t used_element_count;
129 * Counts the number of values received from Alice by us.
130 * Always less than @e used_element_count.
132 uint32_t cadet_received_element_count;
135 * State of this session. In
136 * #GNUNET_SCALARPRODUCT_STATUS_ACTIVE while operation is
137 * ongoing, afterwards in #GNUNET_SCALARPRODUCT_STATUS_SUCCESS or
138 * #GNUNET_SCALARPRODUCT_STATUS_FAILURE.
140 enum GNUNET_SCALARPRODUCT_ResponseStatus status;
143 * Are we already in #destroy_service_session()?
150 struct GNUNET_CADET_Channel *channel;
153 * Originator's peer identity. (Only for diagnostics.)
155 struct GNUNET_PeerIdentity peer;
158 * (hopefully) unique transaction ID
160 struct GNUNET_HashCode session_id;
163 * The message queue for this channel.
165 struct GNUNET_MQ_Handle *cadet_mq;
171 * GNUnet configuration handle
173 static const struct GNUNET_CONFIGURATION_Handle *cfg;
176 * Handle to the CADET service.
178 static struct GNUNET_CADET_Handle *my_cadet;
181 * Context for DLOG operations on a curve.
183 static struct GNUNET_CRYPTO_EccDlogContext *edc;
187 * Callback used to free the elements in the map.
190 * @param key key of the element
191 * @param value the value to free
194 free_element_cb (void *cls,
195 const struct GNUNET_HashCode *key,
198 struct GNUNET_SCALARPRODUCT_Element *element = value;
200 GNUNET_free (element);
206 * Destroy session state, we are done with it.
208 * @param session the session to free elements from
211 destroy_service_session (struct BobServiceSession *s)
215 if (GNUNET_YES == s->in_destroy)
217 s->in_destroy = GNUNET_YES;
218 if (NULL != s->client)
220 struct GNUNET_SERVICE_Client *c = s->client;
223 GNUNET_SERVICE_client_drop (c);
225 if (NULL != s->intersected_elements)
227 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
230 GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
231 s->intersected_elements = NULL;
233 if (NULL != s->intersection_op)
235 GNUNET_SET_operation_cancel (s->intersection_op);
236 s->intersection_op = NULL;
238 if (NULL != s->intersection_set)
240 GNUNET_SET_destroy (s->intersection_set);
241 s->intersection_set = NULL;
243 if (NULL != s->sorted_elements)
245 for (i=0;i<s->used_element_count;i++)
246 gcry_mpi_release (s->sorted_elements[i].value);
247 GNUNET_free (s->sorted_elements);
248 s->sorted_elements = NULL;
250 if (NULL != s->prod_g_i_b_i)
252 gcry_mpi_point_release (s->prod_g_i_b_i);
253 s->prod_g_i_b_i = NULL;
255 if (NULL != s->prod_h_i_b_i)
257 gcry_mpi_point_release (s->prod_h_i_b_i);
258 s->prod_h_i_b_i = NULL;
262 GNUNET_CADET_close_port (s->port);
265 if (NULL != s->channel)
267 GNUNET_CADET_channel_destroy (s->channel);
275 * Notify the client that the session has succeeded or failed. This
276 * message gets sent to Bob's client if the operation completed or
277 * Alice disconnected.
279 * @param session the associated client session to fail or succeed
282 prepare_client_end_notification (struct BobServiceSession *session)
284 struct ClientResponseMessage *msg;
285 struct GNUNET_MQ_Envelope *e;
287 if (NULL == session->client_mq)
288 return; /* no client left to be notified */
289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
290 "Sending session-end notification with status %d to client for session %s\n",
292 GNUNET_h2s (&session->session_id));
293 e = GNUNET_MQ_msg (msg,
294 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
296 msg->product_length = htonl (0);
297 msg->status = htonl (session->status);
298 GNUNET_MQ_send (session->client_mq,
304 * Function called whenever a channel is destroyed. Should clean up
305 * any associated state.
307 * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
309 * @param cls the `struct BobServiceSession`
310 * @param channel connection to the other end (henceforth invalid)
311 * @param channel_ctx place where local state associated
312 * with the channel is stored
315 cb_channel_destruction (void *cls,
316 const struct GNUNET_CADET_Channel *channel)
318 struct BobServiceSession *s = cls;
320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
321 "Peer disconnected, terminating session %s with peer %s\n",
322 GNUNET_h2s (&s->session_id),
323 GNUNET_i2s (&s->peer));
325 if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
327 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
328 prepare_client_end_notification (s);
330 destroy_service_session (s);
335 * MQ finished giving our last message to CADET, now notify
336 * the client that we are finished.
339 bob_cadet_done_cb (void *cls)
341 struct BobServiceSession *session = cls;
343 session->status = GNUNET_SCALARPRODUCT_STATUS_SUCCESS;
344 prepare_client_end_notification (session);
349 * Bob generates the response message to be sent to Alice.
351 * @param s the associated requesting session with Alice
354 transmit_bobs_cryptodata_message (struct BobServiceSession *s)
356 struct EccBobCryptodataMessage *msg;
357 struct GNUNET_MQ_Envelope *e;
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 "Sending response to Alice\n");
361 e = GNUNET_MQ_msg (msg,
362 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA);
363 msg->contained_element_count = htonl (2);
364 if (NULL != s->prod_g_i_b_i)
365 GNUNET_CRYPTO_ecc_point_to_bin (edc,
368 if (NULL != s->prod_h_i_b_i)
369 GNUNET_CRYPTO_ecc_point_to_bin (edc,
372 GNUNET_MQ_notify_sent (e,
375 GNUNET_MQ_send (s->cadet_mq,
381 * Iterator to copy over messages from the hash map
382 * into an array for sorting.
384 * @param cls the `struct BobServiceSession *`
385 * @param key the key (unused)
386 * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
387 * TODO: code duplication with Alice!
390 copy_element_cb (void *cls,
391 const struct GNUNET_HashCode *key,
394 struct BobServiceSession *s = cls;
395 struct GNUNET_SCALARPRODUCT_Element *e = value;
399 mval = gcry_mpi_new (0);
400 val = (int64_t) GNUNET_ntohll (e->value);
402 gcry_mpi_sub_ui (mval, mval, -val);
404 gcry_mpi_add_ui (mval, mval, val);
405 s->sorted_elements [s->used_element_count].value = mval;
406 s->sorted_elements [s->used_element_count].key = &e->key;
407 s->used_element_count++;
413 * Compare two `struct MpiValue`s by key for sorting.
415 * @param a pointer to first `struct MpiValue *`
416 * @param b pointer to first `struct MpiValue *`
417 * @return -1 for a < b, 0 for a=b, 1 for a > b.
418 * TODO: code duplication with Alice!
421 element_cmp (const void *a,
424 const struct MpiElement *ma = a;
425 const struct MpiElement *mb = b;
427 return GNUNET_CRYPTO_hash_cmp (ma->key,
433 * Check a multipart-chunk of a request from another service to
434 * calculate a scalarproduct with us.
436 * @param cls closure (set from #GNUNET_CADET_connect)
437 * @param msg the actual message
438 * @return #GNUNET_OK to keep the connection open,
439 * #GNUNET_SYSERR to close it (signal serious error)
442 check_alices_cryptodata_message (void *cls,
443 const struct EccAliceCryptodataMessage *msg)
445 struct BobServiceSession *s = cls;
446 uint32_t contained_elements;
451 msize = ntohs (msg->header.size);
452 if (msize <= sizeof (struct EccAliceCryptodataMessage))
455 return GNUNET_SYSERR;
457 contained_elements = ntohl (msg->contained_element_count);
458 /* Our intersection may still be ongoing, but this is nevertheless
459 an upper bound on the required array size */
460 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
461 msg_length = sizeof (struct EccAliceCryptodataMessage)
462 + contained_elements * sizeof (struct GNUNET_CRYPTO_EccPoint) * 2;
463 if ( (msize != msg_length) ||
464 (0 == contained_elements) ||
465 (contained_elements > UINT16_MAX) ||
466 (max < contained_elements + s->cadet_received_element_count) )
469 return GNUNET_SYSERR;
476 * Handle a multipart-chunk of a request from another service to
477 * calculate a scalarproduct with us.
479 * @param cls closure (set from #GNUNET_CADET_connect)
480 * @param msg the actual message
483 handle_alices_cryptodata_message (void *cls,
484 const struct EccAliceCryptodataMessage *msg)
486 struct BobServiceSession *s = cls;
487 const struct GNUNET_CRYPTO_EccPoint *payload;
488 uint32_t contained_elements;
491 const struct MpiElement *b_i;
492 gcry_mpi_point_t tmp;
493 gcry_mpi_point_t g_i;
494 gcry_mpi_point_t h_i;
495 gcry_mpi_point_t g_i_b_i;
496 gcry_mpi_point_t h_i_b_i;
498 contained_elements = ntohl (msg->contained_element_count);
499 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
500 /* sort our vector for the computation */
501 if (NULL == s->sorted_elements)
504 = GNUNET_new_array (GNUNET_CONTAINER_multihashmap_size (s->intersected_elements),
506 s->used_element_count = 0;
507 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
510 qsort (s->sorted_elements,
511 s->used_element_count,
512 sizeof (struct MpiElement),
516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
517 "Received %u crypto values from Alice\n",
518 (unsigned int) contained_elements);
519 payload = (const struct GNUNET_CRYPTO_EccPoint *) &msg[1];
521 for (i=0;i<contained_elements;i++)
523 b_i = &s->sorted_elements[i + s->cadet_received_element_count];
524 g_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
526 g_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
529 gcry_mpi_point_release (g_i);
530 h_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
531 &payload[i * 2 + 1]);
532 h_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
535 gcry_mpi_point_release (h_i);
536 if (0 == i + s->cadet_received_element_count)
538 /* first iteration, nothing to add */
539 s->prod_g_i_b_i = g_i_b_i;
540 s->prod_h_i_b_i = h_i_b_i;
544 /* further iterations, cummulate resulting value */
545 tmp = GNUNET_CRYPTO_ecc_add (edc,
548 gcry_mpi_point_release (s->prod_g_i_b_i);
549 gcry_mpi_point_release (g_i_b_i);
550 s->prod_g_i_b_i = tmp;
551 tmp = GNUNET_CRYPTO_ecc_add (edc,
554 gcry_mpi_point_release (s->prod_h_i_b_i);
555 gcry_mpi_point_release (h_i_b_i);
556 s->prod_h_i_b_i = tmp;
559 s->cadet_received_element_count += contained_elements;
560 if ( (s->cadet_received_element_count == max) &&
561 (NULL == s->intersection_op) )
563 /* intersection has finished also on our side, and
564 we got the full set, so we can proceed with the
566 transmit_bobs_cryptodata_message (s);
568 GNUNET_CADET_receive_done (s->channel);
573 * Callback for set operation results. Called for each element
574 * that needs to be removed from the result set.
576 * @param cls closure with the `struct BobServiceSession`
577 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
578 * @param current_size current set size
579 * @param status what has happened with the set intersection?
582 cb_intersection_element_removed (void *cls,
583 const struct GNUNET_SET_Element *element,
584 uint64_t current_size,
585 enum GNUNET_SET_Status status)
587 struct BobServiceSession *s = cls;
588 struct GNUNET_SCALARPRODUCT_Element *se;
592 case GNUNET_SET_STATUS_OK:
593 /* this element has been removed from the set */
594 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
596 GNUNET_assert (NULL != se);
597 LOG (GNUNET_ERROR_TYPE_DEBUG,
598 "Removed element with key %s and value %lld\n",
599 GNUNET_h2s (&se->key),
600 (long long) GNUNET_ntohll (se->value));
601 GNUNET_assert (GNUNET_YES ==
602 GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
607 case GNUNET_SET_STATUS_DONE:
608 s->intersection_op = NULL;
609 GNUNET_break (NULL == s->intersection_set);
610 GNUNET_CADET_receive_done (s->channel);
611 LOG (GNUNET_ERROR_TYPE_DEBUG,
612 "Finished intersection, %d items remain\n",
613 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements));
614 if (s->client_received_element_count ==
615 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements))
617 /* CADET transmission from Alice is also already done,
618 start with our own reply */
619 transmit_bobs_cryptodata_message (s);
622 case GNUNET_SET_STATUS_HALF_DONE:
623 /* unexpected for intersection */
626 case GNUNET_SET_STATUS_FAILURE:
627 /* unhandled status code */
628 LOG (GNUNET_ERROR_TYPE_DEBUG,
629 "Set intersection failed!\n");
630 s->intersection_op = NULL;
631 if (NULL != s->intersection_set)
633 GNUNET_SET_destroy (s->intersection_set);
634 s->intersection_set = NULL;
636 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
637 prepare_client_end_notification (s);
647 * We've paired up a client session with an incoming CADET request.
648 * Initiate set intersection work.
650 * @param s client session to start intersection for
653 start_intersection (struct BobServiceSession *s)
655 struct GNUNET_HashCode set_sid;
657 GNUNET_CRYPTO_hash (&s->session_id,
658 sizeof (struct GNUNET_HashCode),
660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661 "Got session with key %s and %u elements, starting intersection.\n",
662 GNUNET_h2s (&s->session_id),
663 (unsigned int) s->total);
666 = GNUNET_SET_prepare (&s->peer,
669 GNUNET_SET_RESULT_REMOVED,
670 (struct GNUNET_SET_Option[]) {{ 0 }},
671 &cb_intersection_element_removed,
674 GNUNET_SET_commit (s->intersection_op,
675 s->intersection_set))
678 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
679 prepare_client_end_notification (s);
682 GNUNET_SET_destroy (s->intersection_set);
683 s->intersection_set = NULL;
688 * Handle a request from Alice to calculate a scalarproduct with us (Bob).
690 * @param cls closure (set from #GNUNET_CADET_connect)
691 * @param msg the actual message
694 handle_alices_computation_request (void *cls,
695 const struct EccServiceRequestMessage *msg)
697 struct BobServiceSession *s = cls;
699 s->session_id = msg->session_id; // ??
700 if (s->client_received_element_count < s->total)
702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
703 "Alice ready, still waiting for Bob client data!\n");
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 "Both ready, launching intersection!\n");
708 start_intersection (s);
713 * Function called for inbound channels on Bob's end. Does some
714 * preliminary initialization, more happens after we get Alice's first
717 * @param cls our `struct BobServiceSession`
718 * @param channel new handle to the channel
719 * @param initiator peer that started the channel
720 * @return session associated with the channel
723 cb_channel_incoming (void *cls,
724 struct GNUNET_CADET_Channel *channel,
725 const struct GNUNET_PeerIdentity *initiator)
727 struct BobServiceSession *s = cls;
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "New incoming channel from peer %s.\n",
731 GNUNET_i2s (initiator));
732 GNUNET_CADET_close_port (s->port);
734 s->peer = *initiator;
735 s->channel = channel;
736 s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
742 * We're receiving additional set data. Check it is well-formed.
744 * @param cls identification of the client
745 * @param msg the actual message
746 * @return #GNUNET_OK if @a msg is well-formed
749 check_bob_client_message_multipart (void *cls,
750 const struct ComputationBobCryptodataMultipartMessage *msg)
752 struct BobServiceSession *s = cls;
753 uint32_t contained_count;
756 msize = ntohs (msg->header.size);
757 contained_count = ntohl (msg->element_count_contained);
758 if ( (msize != (sizeof (struct ComputationBobCryptodataMultipartMessage) +
759 contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
760 (0 == contained_count) ||
761 (UINT16_MAX < contained_count) ||
762 (s->total == s->client_received_element_count) ||
763 (s->total < s->client_received_element_count + contained_count) )
766 return GNUNET_SYSERR;
773 * We're receiving additional set data. Add it to our
774 * set and if we are done, initiate the transaction.
776 * @param cls identification of the client
777 * @param msg the actual message
780 handle_bob_client_message_multipart (void *cls,
781 const struct ComputationBobCryptodataMultipartMessage *msg)
783 struct BobServiceSession *s = cls;
784 uint32_t contained_count;
785 const struct GNUNET_SCALARPRODUCT_Element *elements;
786 struct GNUNET_SET_Element set_elem;
787 struct GNUNET_SCALARPRODUCT_Element *elem;
789 contained_count = ntohl (msg->element_count_contained);
790 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
791 for (uint32_t i = 0; i < contained_count; i++)
793 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
796 sizeof (struct GNUNET_SCALARPRODUCT_Element));
798 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
801 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
807 set_elem.data = &elem->key;
808 set_elem.size = sizeof (elem->key);
809 set_elem.element_type = 0;
810 GNUNET_SET_add_element (s->intersection_set,
814 s->client_received_element_count += contained_count;
815 GNUNET_SERVICE_client_continue (s->client);
816 if (s->total != s->client_received_element_count)
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
820 "Request still partial, waiting for more client data!\n");
823 if (NULL == s->channel)
825 /* no Alice waiting for this request, wait for Alice */
826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
827 "Client ready, still waiting for Alice!\n");
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "Both ready, launching intersection!\n");
832 start_intersection (s);
837 * Handler for Bob's a client request message. Check @a msg is
840 * @param cls identification of the client
841 * @param msg the actual message
842 * @return #GNUNET_OK if @a msg is well-formed
845 check_bob_client_message (void *cls,
846 const struct BobComputationMessage *msg)
848 struct BobServiceSession *s = cls;
849 uint32_t contained_count;
850 uint32_t total_count;
853 if (GNUNET_SCALARPRODUCT_STATUS_INIT != s->status)
856 return GNUNET_SYSERR;
858 msize = ntohs (msg->header.size);
859 total_count = ntohl (msg->element_count_total);
860 contained_count = ntohl (msg->element_count_contained);
861 if ( (0 == total_count) ||
862 (0 == contained_count) ||
863 (UINT16_MAX < contained_count) ||
864 (msize != (sizeof (struct BobComputationMessage) +
865 contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) )
868 return GNUNET_SYSERR;
875 * Handler for Bob's a client request message. Bob is in the response
876 * role, keep the values + session and waiting for a matching session
877 * or process a waiting request from Alice.
879 * @param cls identification of the client
880 * @param msg the actual message
883 handle_bob_client_message (void *cls,
884 const struct BobComputationMessage *msg)
886 struct BobServiceSession *s = cls;
887 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
888 GNUNET_MQ_hd_fixed_size (alices_computation_request,
889 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_SESSION_INITIALIZATION,
890 struct EccServiceRequestMessage,
892 GNUNET_MQ_hd_var_size (alices_cryptodata_message,
893 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_ALICE_CRYPTODATA,
894 struct EccAliceCryptodataMessage,
896 GNUNET_MQ_handler_end ()
898 uint32_t contained_count;
899 uint32_t total_count;
900 const struct GNUNET_SCALARPRODUCT_Element *elements;
901 struct GNUNET_SET_Element set_elem;
902 struct GNUNET_SCALARPRODUCT_Element *elem;
904 total_count = ntohl (msg->element_count_total);
905 contained_count = ntohl (msg->element_count_contained);
907 s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE;
908 s->total = total_count;
909 s->client_received_element_count = contained_count;
910 s->session_id = msg->session_key;
911 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
912 s->intersected_elements
913 = GNUNET_CONTAINER_multihashmap_create (s->total,
916 = GNUNET_SET_create (cfg,
917 GNUNET_SET_OPERATION_INTERSECTION);
918 for (uint32_t i = 0; i < contained_count; i++)
920 if (0 == GNUNET_ntohll (elements[i].value))
922 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
925 sizeof (struct GNUNET_SCALARPRODUCT_Element));
927 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
930 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
936 set_elem.data = &elem->key;
937 set_elem.size = sizeof (elem->key);
938 set_elem.element_type = 0;
939 GNUNET_SET_add_element (s->intersection_set,
942 s->used_element_count++;
944 GNUNET_SERVICE_client_continue (s->client);
945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
946 "Received client request, opening port %s!\n",
947 GNUNET_h2s (&msg->session_key));
948 s->port = GNUNET_CADET_open_port (my_cadet,
950 &cb_channel_incoming,
953 &cb_channel_destruction,
958 GNUNET_SERVICE_client_drop (s->client);
965 * Task run during shutdown.
970 shutdown_task (void *cls)
972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
973 "Shutting down, initiating cleanup.\n");
974 // FIXME: we have to cut our connections to CADET first!
975 if (NULL != my_cadet)
977 GNUNET_CADET_disconnect (my_cadet);
982 GNUNET_CRYPTO_ecc_dlog_release (edc);
989 * A client connected.
991 * Setup the associated data structure.
993 * @param cls closure, NULL
994 * @param client identification of the client
995 * @param mq message queue to communicate with @a client
996 * @return our `struct BobServiceSession`
999 client_connect_cb (void *cls,
1000 struct GNUNET_SERVICE_Client *client,
1001 struct GNUNET_MQ_Handle *mq)
1003 struct BobServiceSession *s;
1005 s = GNUNET_new (struct BobServiceSession);
1013 * A client disconnected.
1015 * Remove the associated session(s), release data structures
1016 * and cancel pending outgoing transmissions to the client.
1018 * @param cls closure, NULL
1019 * @param client identification of the client
1020 * @param app_cls our `struct BobServiceSession`
1023 client_disconnect_cb (void *cls,
1024 struct GNUNET_SERVICE_Client *client,
1027 struct BobServiceSession *s = app_cls;
1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1030 "Client disconnected from us.\n");
1032 destroy_service_session (s);
1037 * Initialization of the program and message handlers
1039 * @param cls closure
1040 * @param c configuration to use
1041 * @param service the initialized service
1045 const struct GNUNET_CONFIGURATION_Handle *c,
1046 struct GNUNET_SERVICE_Handle *service)
1049 /* We don't really do DLOG, so we can setup with very minimal resources */
1050 edc = GNUNET_CRYPTO_ecc_dlog_prepare (4 /* max value */,
1052 my_cadet = GNUNET_CADET_connect (cfg);
1053 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1055 if (NULL == my_cadet)
1057 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1058 _("Connect to CADET failed\n"));
1059 GNUNET_SCHEDULER_shutdown ();
1066 * Define "main" method using service macro.
1069 ("scalarproduct-bob",
1070 GNUNET_SERVICE_OPTION_NONE,
1073 &client_disconnect_cb,
1075 GNUNET_MQ_hd_var_size (bob_client_message,
1076 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
1077 struct BobComputationMessage,
1079 GNUNET_MQ_hd_var_size (bob_client_message_multipart,
1080 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB,
1081 struct ComputationBobCryptodataMultipartMessage,
1083 GNUNET_MQ_handler_end ());
1086 /* end of gnunet-service-scalarproduct-ecc_bob.c */