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.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
22 * @brief scalarproduct service implementation
23 * @author Christian M. Fuchs
24 * @author Christian Grothoff
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-ecc.h"
39 #define LOG(kind, ...) GNUNET_log_from (kind, "scalarproduct-bob", __VA_ARGS__)
43 * An encrypted element key-value pair.
48 * Key used to identify matching pairs of values to multiply.
49 * Points into an existing data structure, to avoid copying
50 * and doubling memory use.
52 const struct GNUNET_HashCode *key;
55 * Value represented (a).
62 * A scalarproduct session which tracks an offer for a
63 * multiplication service by a local client.
65 struct BobServiceSession
68 * The client this request is related to.
70 struct GNUNET_SERVICE_Client *client;
73 * Client message queue.
75 struct GNUNET_MQ_Handle *client_mq;
78 * All non-0-value'd elements transmitted to us.
80 struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
83 * Set of elements for which we will be conducting an intersection.
84 * The resulting elements are then used for computing the scalar product.
86 struct GNUNET_SET_Handle *intersection_set;
89 * Set of elements for which will conduction an intersection.
90 * the resulting elements are then used for computing the scalar product.
92 struct GNUNET_SET_OperationHandle *intersection_op;
97 struct GNUNET_CADET_Port *port;
102 struct MpiElement *sorted_elements;
105 * Product of the g_i^{b_i}
107 gcry_mpi_point_t prod_g_i_b_i;
110 * Product of the h_i^{b_i}
112 gcry_mpi_point_t prod_h_i_b_i;
115 * How many elements will be supplied in total from the client.
120 * Already transferred elements (received) for multipart
121 * messages from client. Always less than @e total.
123 uint32_t client_received_element_count;
126 * How many elements actually are used for the scalar product.
127 * Size of the arrays in @e r and @e r_prime. Also sometimes
128 * used as an index into the arrays during construction.
130 uint32_t used_element_count;
133 * Counts the number of values received from Alice by us.
134 * Always less than @e used_element_count.
136 uint32_t cadet_received_element_count;
139 * State of this session. In
140 * #GNUNET_SCALARPRODUCT_STATUS_ACTIVE while operation is
141 * ongoing, afterwards in #GNUNET_SCALARPRODUCT_STATUS_SUCCESS or
142 * #GNUNET_SCALARPRODUCT_STATUS_FAILURE.
144 enum GNUNET_SCALARPRODUCT_ResponseStatus status;
147 * Are we already in #destroy_service_session()?
154 struct GNUNET_CADET_Channel *channel;
157 * Originator's peer identity. (Only for diagnostics.)
159 struct GNUNET_PeerIdentity peer;
162 * (hopefully) unique transaction ID
164 struct GNUNET_HashCode session_id;
167 * The message queue for this channel.
169 struct GNUNET_MQ_Handle *cadet_mq;
174 * GNUnet configuration handle
176 static const struct GNUNET_CONFIGURATION_Handle *cfg;
179 * Handle to the CADET service.
181 static struct GNUNET_CADET_Handle *my_cadet;
184 * Context for DLOG operations on a curve.
186 static struct GNUNET_CRYPTO_EccDlogContext *edc;
190 * Callback used to free the elements in the map.
193 * @param key key of the element
194 * @param value the value to free
197 free_element_cb (void *cls,
198 const struct GNUNET_HashCode *key,
201 struct GNUNET_SCALARPRODUCT_Element *element = value;
203 GNUNET_free (element);
209 * Destroy session state, we are done with it.
211 * @param session the session to free elements from
214 destroy_service_session (struct BobServiceSession *s)
218 if (GNUNET_YES == s->in_destroy)
220 s->in_destroy = GNUNET_YES;
221 if (NULL != s->client)
223 struct GNUNET_SERVICE_Client *c = s->client;
226 GNUNET_SERVICE_client_drop (c);
228 if (NULL != s->intersected_elements)
230 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
233 GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
234 s->intersected_elements = NULL;
236 if (NULL != s->intersection_op)
238 GNUNET_SET_operation_cancel (s->intersection_op);
239 s->intersection_op = NULL;
241 if (NULL != s->intersection_set)
243 GNUNET_SET_destroy (s->intersection_set);
244 s->intersection_set = NULL;
246 if (NULL != s->sorted_elements)
248 for (i = 0; i < s->used_element_count; i++)
249 gcry_mpi_release (s->sorted_elements[i].value);
250 GNUNET_free (s->sorted_elements);
251 s->sorted_elements = NULL;
253 if (NULL != s->prod_g_i_b_i)
255 gcry_mpi_point_release (s->prod_g_i_b_i);
256 s->prod_g_i_b_i = NULL;
258 if (NULL != s->prod_h_i_b_i)
260 gcry_mpi_point_release (s->prod_h_i_b_i);
261 s->prod_h_i_b_i = NULL;
265 GNUNET_CADET_close_port (s->port);
268 if (NULL != s->channel)
270 GNUNET_CADET_channel_destroy (s->channel);
278 * Notify the client that the session has succeeded or failed. This
279 * message gets sent to Bob's client if the operation completed or
280 * Alice disconnected.
282 * @param session the associated client session to fail or succeed
285 prepare_client_end_notification (struct BobServiceSession *session)
287 struct ClientResponseMessage *msg;
288 struct GNUNET_MQ_Envelope *e;
290 if (NULL == session->client_mq)
291 return; /* no client left to be notified */
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
293 "Sending session-end notification with status %d to client for session %s\n",
295 GNUNET_h2s (&session->session_id));
296 e = GNUNET_MQ_msg (msg,
297 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
299 msg->product_length = htonl (0);
300 msg->status = htonl (session->status);
301 GNUNET_MQ_send (session->client_mq,
307 * Function called whenever a channel is destroyed. Should clean up
308 * any associated state.
310 * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
312 * @param cls the `struct BobServiceSession`
313 * @param channel connection to the other end (henceforth invalid)
314 * @param channel_ctx place where local state associated
315 * with the channel is stored
318 cb_channel_destruction (void *cls,
319 const struct GNUNET_CADET_Channel *channel)
321 struct BobServiceSession *s = cls;
323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
324 "Peer disconnected, terminating session %s with peer %s\n",
325 GNUNET_h2s (&s->session_id),
326 GNUNET_i2s (&s->peer));
328 if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
330 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
331 prepare_client_end_notification (s);
333 destroy_service_session (s);
338 * MQ finished giving our last message to CADET, now notify
339 * the client that we are finished.
342 bob_cadet_done_cb (void *cls)
344 struct BobServiceSession *session = cls;
346 session->status = GNUNET_SCALARPRODUCT_STATUS_SUCCESS;
347 prepare_client_end_notification (session);
352 * Bob generates the response message to be sent to Alice.
354 * @param s the associated requesting session with Alice
357 transmit_bobs_cryptodata_message (struct BobServiceSession *s)
359 struct EccBobCryptodataMessage *msg;
360 struct GNUNET_MQ_Envelope *e;
362 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
363 "Sending response to Alice\n");
364 e = GNUNET_MQ_msg (msg,
365 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA);
366 msg->contained_element_count = htonl (2);
367 if (NULL != s->prod_g_i_b_i)
368 GNUNET_CRYPTO_ecc_point_to_bin (edc,
371 if (NULL != s->prod_h_i_b_i)
372 GNUNET_CRYPTO_ecc_point_to_bin (edc,
375 GNUNET_MQ_notify_sent (e,
378 GNUNET_MQ_send (s->cadet_mq,
384 * Iterator to copy over messages from the hash map
385 * into an array for sorting.
387 * @param cls the `struct BobServiceSession *`
388 * @param key the key (unused)
389 * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
390 * TODO: code duplication with Alice!
393 copy_element_cb (void *cls,
394 const struct GNUNET_HashCode *key,
397 struct BobServiceSession *s = cls;
398 struct GNUNET_SCALARPRODUCT_Element *e = value;
402 mval = gcry_mpi_new (0);
403 val = (int64_t) GNUNET_ntohll (e->value);
405 gcry_mpi_sub_ui (mval, mval, -val);
407 gcry_mpi_add_ui (mval, mval, val);
408 s->sorted_elements [s->used_element_count].value = mval;
409 s->sorted_elements [s->used_element_count].key = &e->key;
410 s->used_element_count++;
416 * Compare two `struct MpiValue`s by key for sorting.
418 * @param a pointer to first `struct MpiValue *`
419 * @param b pointer to first `struct MpiValue *`
420 * @return -1 for a < b, 0 for a=b, 1 for a > b.
421 * TODO: code duplication with Alice!
424 element_cmp (const void *a,
427 const struct MpiElement *ma = a;
428 const struct MpiElement *mb = b;
430 return GNUNET_CRYPTO_hash_cmp (ma->key,
436 * Check a multipart-chunk of a request from another service to
437 * calculate a scalarproduct with us.
439 * @param cls closure (set from #GNUNET_CADET_connect)
440 * @param msg the actual message
441 * @return #GNUNET_OK to keep the connection open,
442 * #GNUNET_SYSERR to close it (signal serious error)
445 check_alices_cryptodata_message (void *cls,
446 const struct EccAliceCryptodataMessage *msg)
448 struct BobServiceSession *s = cls;
449 uint32_t contained_elements;
454 msize = ntohs (msg->header.size);
455 if (msize <= sizeof(struct EccAliceCryptodataMessage))
458 return GNUNET_SYSERR;
460 contained_elements = ntohl (msg->contained_element_count);
461 /* Our intersection may still be ongoing, but this is nevertheless
462 an upper bound on the required array size */
463 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
464 msg_length = sizeof(struct EccAliceCryptodataMessage)
465 + contained_elements * sizeof(struct GNUNET_CRYPTO_EccPoint) * 2;
466 if ((msize != msg_length) ||
467 (0 == contained_elements) ||
468 (contained_elements > UINT16_MAX) ||
469 (max < contained_elements + s->cadet_received_element_count))
472 return GNUNET_SYSERR;
479 * Handle a multipart-chunk of a request from another service to
480 * calculate a scalarproduct with us.
482 * @param cls closure (set from #GNUNET_CADET_connect)
483 * @param msg the actual message
486 handle_alices_cryptodata_message (void *cls,
487 const struct EccAliceCryptodataMessage *msg)
489 struct BobServiceSession *s = cls;
490 const struct GNUNET_CRYPTO_EccPoint *payload;
491 uint32_t contained_elements;
494 const struct MpiElement *b_i;
495 gcry_mpi_point_t tmp;
496 gcry_mpi_point_t g_i;
497 gcry_mpi_point_t h_i;
498 gcry_mpi_point_t g_i_b_i;
499 gcry_mpi_point_t h_i_b_i;
501 contained_elements = ntohl (msg->contained_element_count);
502 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
503 /* sort our vector for the computation */
504 if (NULL == s->sorted_elements)
507 = GNUNET_new_array (GNUNET_CONTAINER_multihashmap_size (
508 s->intersected_elements),
510 s->used_element_count = 0;
511 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
514 qsort (s->sorted_elements,
515 s->used_element_count,
516 sizeof(struct MpiElement),
520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
521 "Received %u crypto values from Alice\n",
522 (unsigned int) contained_elements);
523 payload = (const struct GNUNET_CRYPTO_EccPoint *) &msg[1];
525 for (i = 0; i < contained_elements; i++)
527 b_i = &s->sorted_elements[i + s->cadet_received_element_count];
528 g_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
530 g_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
533 gcry_mpi_point_release (g_i);
534 h_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
535 &payload[i * 2 + 1]);
536 h_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
539 gcry_mpi_point_release (h_i);
540 if (0 == i + s->cadet_received_element_count)
542 /* first iteration, nothing to add */
543 s->prod_g_i_b_i = g_i_b_i;
544 s->prod_h_i_b_i = h_i_b_i;
548 /* further iterations, cummulate resulting value */
549 tmp = GNUNET_CRYPTO_ecc_add (edc,
552 gcry_mpi_point_release (s->prod_g_i_b_i);
553 gcry_mpi_point_release (g_i_b_i);
554 s->prod_g_i_b_i = tmp;
555 tmp = GNUNET_CRYPTO_ecc_add (edc,
558 gcry_mpi_point_release (s->prod_h_i_b_i);
559 gcry_mpi_point_release (h_i_b_i);
560 s->prod_h_i_b_i = tmp;
563 s->cadet_received_element_count += contained_elements;
564 if ((s->cadet_received_element_count == max) &&
565 (NULL == s->intersection_op))
567 /* intersection has finished also on our side, and
568 we got the full set, so we can proceed with the
570 transmit_bobs_cryptodata_message (s);
572 GNUNET_CADET_receive_done (s->channel);
577 * Callback for set operation results. Called for each element
578 * that needs to be removed from the result set.
580 * @param cls closure with the `struct BobServiceSession`
581 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
582 * @param current_size current set size
583 * @param status what has happened with the set intersection?
586 cb_intersection_element_removed (void *cls,
587 const struct GNUNET_SET_Element *element,
588 uint64_t current_size,
589 enum GNUNET_SET_Status status)
591 struct BobServiceSession *s = cls;
592 struct GNUNET_SCALARPRODUCT_Element *se;
596 case GNUNET_SET_STATUS_OK:
597 /* this element has been removed from the set */
598 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
600 GNUNET_assert (NULL != se);
601 LOG (GNUNET_ERROR_TYPE_DEBUG,
602 "Removed element with key %s and value %lld\n",
603 GNUNET_h2s (&se->key),
604 (long long) GNUNET_ntohll (se->value));
605 GNUNET_assert (GNUNET_YES ==
606 GNUNET_CONTAINER_multihashmap_remove (
607 s->intersected_elements,
613 case GNUNET_SET_STATUS_DONE:
614 s->intersection_op = NULL;
615 GNUNET_break (NULL == s->intersection_set);
616 GNUNET_CADET_receive_done (s->channel);
617 LOG (GNUNET_ERROR_TYPE_DEBUG,
618 "Finished intersection, %d items remain\n",
619 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements));
620 if (s->client_received_element_count ==
621 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements))
623 /* CADET transmission from Alice is also already done,
624 start with our own reply */
625 transmit_bobs_cryptodata_message (s);
629 case GNUNET_SET_STATUS_HALF_DONE:
630 /* unexpected for intersection */
634 case GNUNET_SET_STATUS_FAILURE:
635 /* unhandled status code */
636 LOG (GNUNET_ERROR_TYPE_DEBUG,
637 "Set intersection failed!\n");
638 s->intersection_op = NULL;
639 if (NULL != s->intersection_set)
641 GNUNET_SET_destroy (s->intersection_set);
642 s->intersection_set = NULL;
644 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
645 prepare_client_end_notification (s);
656 * We've paired up a client session with an incoming CADET request.
657 * Initiate set intersection work.
659 * @param s client session to start intersection for
662 start_intersection (struct BobServiceSession *s)
664 struct GNUNET_HashCode set_sid;
666 GNUNET_CRYPTO_hash (&s->session_id,
667 sizeof(struct GNUNET_HashCode),
669 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
670 "Got session with key %s and %u elements, starting intersection.\n",
671 GNUNET_h2s (&s->session_id),
672 (unsigned int) s->total);
675 = GNUNET_SET_prepare (&s->peer,
678 GNUNET_SET_RESULT_REMOVED,
679 (struct GNUNET_SET_Option[]) { { 0 } },
680 &cb_intersection_element_removed,
683 GNUNET_SET_commit (s->intersection_op,
684 s->intersection_set))
687 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
688 prepare_client_end_notification (s);
691 GNUNET_SET_destroy (s->intersection_set);
692 s->intersection_set = NULL;
697 * Handle a request from Alice to calculate a scalarproduct with us (Bob).
699 * @param cls closure (set from #GNUNET_CADET_connect)
700 * @param msg the actual message
703 handle_alices_computation_request (void *cls,
704 const struct EccServiceRequestMessage *msg)
706 struct BobServiceSession *s = cls;
708 s->session_id = msg->session_id; // ??
709 if (s->client_received_element_count < s->total)
711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
712 "Alice ready, still waiting for Bob client data!\n");
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
716 "Both ready, launching intersection!\n");
717 start_intersection (s);
722 * Function called for inbound channels on Bob's end. Does some
723 * preliminary initialization, more happens after we get Alice's first
726 * @param cls our `struct BobServiceSession`
727 * @param channel new handle to the channel
728 * @param initiator peer that started the channel
729 * @return session associated with the channel
732 cb_channel_incoming (void *cls,
733 struct GNUNET_CADET_Channel *channel,
734 const struct GNUNET_PeerIdentity *initiator)
736 struct BobServiceSession *s = cls;
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
739 "New incoming channel from peer %s.\n",
740 GNUNET_i2s (initiator));
741 GNUNET_CADET_close_port (s->port);
743 s->peer = *initiator;
744 s->channel = channel;
745 s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
751 * We're receiving additional set data. Check it is well-formed.
753 * @param cls identification of the client
754 * @param msg the actual message
755 * @return #GNUNET_OK if @a msg is well-formed
758 check_bob_client_message_multipart (void *cls,
760 ComputationBobCryptodataMultipartMessage *
763 struct BobServiceSession *s = cls;
764 uint32_t contained_count;
767 msize = ntohs (msg->header.size);
768 contained_count = ntohl (msg->element_count_contained);
769 if ((msize != (sizeof(struct ComputationBobCryptodataMultipartMessage)
770 + contained_count * sizeof(struct
771 GNUNET_SCALARPRODUCT_Element))) ||
772 (0 == contained_count) ||
773 (UINT16_MAX < contained_count) ||
774 (s->total == s->client_received_element_count) ||
775 (s->total < s->client_received_element_count + contained_count))
778 return GNUNET_SYSERR;
785 * We're receiving additional set data. Add it to our
786 * set and if we are done, initiate the transaction.
788 * @param cls identification of the client
789 * @param msg the actual message
792 handle_bob_client_message_multipart (void *cls,
794 ComputationBobCryptodataMultipartMessage *
797 struct BobServiceSession *s = cls;
798 uint32_t contained_count;
799 const struct GNUNET_SCALARPRODUCT_Element *elements;
800 struct GNUNET_SET_Element set_elem;
801 struct GNUNET_SCALARPRODUCT_Element *elem;
803 contained_count = ntohl (msg->element_count_contained);
804 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
805 for (uint32_t i = 0; i < contained_count; i++)
807 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
810 sizeof(struct GNUNET_SCALARPRODUCT_Element));
812 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
815 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
821 set_elem.data = &elem->key;
822 set_elem.size = sizeof(elem->key);
823 set_elem.element_type = 0;
824 GNUNET_SET_add_element (s->intersection_set,
828 s->client_received_element_count += contained_count;
829 GNUNET_SERVICE_client_continue (s->client);
830 if (s->total != s->client_received_element_count)
833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
834 "Request still partial, waiting for more client data!\n");
837 if (NULL == s->channel)
839 /* no Alice waiting for this request, wait for Alice */
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
841 "Client ready, still waiting for Alice!\n");
844 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
845 "Both ready, launching intersection!\n");
846 start_intersection (s);
851 * Handler for Bob's a client request message. Check @a msg is
854 * @param cls identification of the client
855 * @param msg the actual message
856 * @return #GNUNET_OK if @a msg is well-formed
859 check_bob_client_message (void *cls,
860 const struct BobComputationMessage *msg)
862 struct BobServiceSession *s = cls;
863 uint32_t contained_count;
864 uint32_t total_count;
867 if (GNUNET_SCALARPRODUCT_STATUS_INIT != s->status)
870 return GNUNET_SYSERR;
872 msize = ntohs (msg->header.size);
873 total_count = ntohl (msg->element_count_total);
874 contained_count = ntohl (msg->element_count_contained);
875 if ((0 == total_count) ||
876 (0 == contained_count) ||
877 (UINT16_MAX < contained_count) ||
878 (msize != (sizeof(struct BobComputationMessage)
879 + contained_count * sizeof(struct
880 GNUNET_SCALARPRODUCT_Element))))
883 return GNUNET_SYSERR;
890 * Handler for Bob's a client request message. Bob is in the response
891 * role, keep the values + session and waiting for a matching session
892 * or process a waiting request from Alice.
894 * @param cls identification of the client
895 * @param msg the actual message
898 handle_bob_client_message (void *cls,
899 const struct BobComputationMessage *msg)
901 struct BobServiceSession *s = cls;
902 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
903 GNUNET_MQ_hd_fixed_size (alices_computation_request,
904 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_SESSION_INITIALIZATION,
905 struct EccServiceRequestMessage,
907 GNUNET_MQ_hd_var_size (alices_cryptodata_message,
908 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_ALICE_CRYPTODATA,
909 struct EccAliceCryptodataMessage,
911 GNUNET_MQ_handler_end ()
913 uint32_t contained_count;
914 uint32_t total_count;
915 const struct GNUNET_SCALARPRODUCT_Element *elements;
916 struct GNUNET_SET_Element set_elem;
917 struct GNUNET_SCALARPRODUCT_Element *elem;
919 total_count = ntohl (msg->element_count_total);
920 contained_count = ntohl (msg->element_count_contained);
922 s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE;
923 s->total = total_count;
924 s->client_received_element_count = contained_count;
925 s->session_id = msg->session_key;
926 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
927 s->intersected_elements
928 = GNUNET_CONTAINER_multihashmap_create (s->total,
931 = GNUNET_SET_create (cfg,
932 GNUNET_SET_OPERATION_INTERSECTION);
933 for (uint32_t i = 0; i < contained_count; i++)
935 if (0 == GNUNET_ntohll (elements[i].value))
937 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
940 sizeof(struct GNUNET_SCALARPRODUCT_Element));
942 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
945 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
951 set_elem.data = &elem->key;
952 set_elem.size = sizeof(elem->key);
953 set_elem.element_type = 0;
954 GNUNET_SET_add_element (s->intersection_set,
957 s->used_element_count++;
959 GNUNET_SERVICE_client_continue (s->client);
960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
961 "Received client request, opening port %s!\n",
962 GNUNET_h2s (&msg->session_key));
963 s->port = GNUNET_CADET_open_port (my_cadet,
965 &cb_channel_incoming,
968 &cb_channel_destruction,
973 GNUNET_SERVICE_client_drop (s->client);
980 * Task run during shutdown.
985 shutdown_task (void *cls)
987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
988 "Shutting down, initiating cleanup.\n");
989 // FIXME: we have to cut our connections to CADET first!
990 if (NULL != my_cadet)
992 GNUNET_CADET_disconnect (my_cadet);
997 GNUNET_CRYPTO_ecc_dlog_release (edc);
1004 * A client connected.
1006 * Setup the associated data structure.
1008 * @param cls closure, NULL
1009 * @param client identification of the client
1010 * @param mq message queue to communicate with @a client
1011 * @return our `struct BobServiceSession`
1014 client_connect_cb (void *cls,
1015 struct GNUNET_SERVICE_Client *client,
1016 struct GNUNET_MQ_Handle *mq)
1018 struct BobServiceSession *s;
1020 s = GNUNET_new (struct BobServiceSession);
1028 * A client disconnected.
1030 * Remove the associated session(s), release data structures
1031 * and cancel pending outgoing transmissions to the client.
1033 * @param cls closure, NULL
1034 * @param client identification of the client
1035 * @param app_cls our `struct BobServiceSession`
1038 client_disconnect_cb (void *cls,
1039 struct GNUNET_SERVICE_Client *client,
1042 struct BobServiceSession *s = app_cls;
1044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1045 "Client disconnected from us.\n");
1047 destroy_service_session (s);
1052 * Initialization of the program and message handlers
1054 * @param cls closure
1055 * @param c configuration to use
1056 * @param service the initialized service
1060 const struct GNUNET_CONFIGURATION_Handle *c,
1061 struct GNUNET_SERVICE_Handle *service)
1064 /* We don't really do DLOG, so we can setup with very minimal resources */
1065 edc = GNUNET_CRYPTO_ecc_dlog_prepare (4 /* max value */,
1067 my_cadet = GNUNET_CADET_connect (cfg);
1068 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1070 if (NULL == my_cadet)
1072 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1073 _ ("Connect to CADET failed\n"));
1074 GNUNET_SCHEDULER_shutdown ();
1081 * Define "main" method using service macro.
1084 ("scalarproduct-bob",
1085 GNUNET_SERVICE_OPTION_NONE,
1088 &client_disconnect_cb,
1090 GNUNET_MQ_hd_var_size (bob_client_message,
1091 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
1092 struct BobComputationMessage,
1094 GNUNET_MQ_hd_var_size (bob_client_message_multipart,
1095 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB,
1096 struct ComputationBobCryptodataMultipartMessage,
1098 GNUNET_MQ_handler_end ());
1101 /* end of gnunet-service-scalarproduct-ecc_bob.c */