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
69 * The client this request is related to.
71 struct GNUNET_SERVICE_Client *client;
74 * Client message queue.
76 struct GNUNET_MQ_Handle *client_mq;
79 * All non-0-value'd elements transmitted to us.
81 struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
84 * Set of elements for which we will be conducting an intersection.
85 * The resulting elements are then used for computing the scalar product.
87 struct GNUNET_SET_Handle *intersection_set;
90 * Set of elements for which will conduction an intersection.
91 * the resulting elements are then used for computing the scalar product.
93 struct GNUNET_SET_OperationHandle *intersection_op;
98 struct GNUNET_CADET_Port *port;
103 struct MpiElement *sorted_elements;
106 * Product of the g_i^{b_i}
108 gcry_mpi_point_t prod_g_i_b_i;
111 * Product of the h_i^{b_i}
113 gcry_mpi_point_t prod_h_i_b_i;
116 * How many elements will be supplied in total from the client.
121 * Already transferred elements (received) for multipart
122 * messages from client. Always less than @e total.
124 uint32_t client_received_element_count;
127 * How many elements actually are used for the scalar product.
128 * Size of the arrays in @e r and @e r_prime. Also sometimes
129 * used as an index into the arrays during construction.
131 uint32_t used_element_count;
134 * Counts the number of values received from Alice by us.
135 * Always less than @e used_element_count.
137 uint32_t cadet_received_element_count;
140 * State of this session. In
141 * #GNUNET_SCALARPRODUCT_STATUS_ACTIVE while operation is
142 * ongoing, afterwards in #GNUNET_SCALARPRODUCT_STATUS_SUCCESS or
143 * #GNUNET_SCALARPRODUCT_STATUS_FAILURE.
145 enum GNUNET_SCALARPRODUCT_ResponseStatus status;
148 * Are we already in #destroy_service_session()?
155 struct GNUNET_CADET_Channel *channel;
158 * Originator's peer identity. (Only for diagnostics.)
160 struct GNUNET_PeerIdentity peer;
163 * (hopefully) unique transaction ID
165 struct GNUNET_HashCode session_id;
168 * The message queue for this channel.
170 struct GNUNET_MQ_Handle *cadet_mq;
176 * GNUnet configuration handle
178 static const struct GNUNET_CONFIGURATION_Handle *cfg;
181 * Handle to the CADET service.
183 static struct GNUNET_CADET_Handle *my_cadet;
186 * Context for DLOG operations on a curve.
188 static struct GNUNET_CRYPTO_EccDlogContext *edc;
192 * Callback used to free the elements in the map.
195 * @param key key of the element
196 * @param value the value to free
199 free_element_cb (void *cls,
200 const struct GNUNET_HashCode *key,
203 struct GNUNET_SCALARPRODUCT_Element *element = value;
205 GNUNET_free (element);
211 * Destroy session state, we are done with it.
213 * @param session the session to free elements from
216 destroy_service_session (struct BobServiceSession *s)
220 if (GNUNET_YES == s->in_destroy)
222 s->in_destroy = GNUNET_YES;
223 if (NULL != s->client)
225 struct GNUNET_SERVICE_Client *c = s->client;
228 GNUNET_SERVICE_client_drop (c);
230 if (NULL != s->intersected_elements)
232 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
235 GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
236 s->intersected_elements = NULL;
238 if (NULL != s->intersection_op)
240 GNUNET_SET_operation_cancel (s->intersection_op);
241 s->intersection_op = NULL;
243 if (NULL != s->intersection_set)
245 GNUNET_SET_destroy (s->intersection_set);
246 s->intersection_set = NULL;
248 if (NULL != s->sorted_elements)
250 for (i=0;i<s->used_element_count;i++)
251 gcry_mpi_release (s->sorted_elements[i].value);
252 GNUNET_free (s->sorted_elements);
253 s->sorted_elements = NULL;
255 if (NULL != s->prod_g_i_b_i)
257 gcry_mpi_point_release (s->prod_g_i_b_i);
258 s->prod_g_i_b_i = NULL;
260 if (NULL != s->prod_h_i_b_i)
262 gcry_mpi_point_release (s->prod_h_i_b_i);
263 s->prod_h_i_b_i = NULL;
267 GNUNET_CADET_close_port (s->port);
270 if (NULL != s->channel)
272 GNUNET_CADET_channel_destroy (s->channel);
280 * Notify the client that the session has succeeded or failed. This
281 * message gets sent to Bob's client if the operation completed or
282 * Alice disconnected.
284 * @param session the associated client session to fail or succeed
287 prepare_client_end_notification (struct BobServiceSession *session)
289 struct ClientResponseMessage *msg;
290 struct GNUNET_MQ_Envelope *e;
292 if (NULL == session->client_mq)
293 return; /* no client left to be notified */
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
295 "Sending session-end notification with status %d to client for session %s\n",
297 GNUNET_h2s (&session->session_id));
298 e = GNUNET_MQ_msg (msg,
299 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
301 msg->product_length = htonl (0);
302 msg->status = htonl (session->status);
303 GNUNET_MQ_send (session->client_mq,
309 * Function called whenever a channel is destroyed. Should clean up
310 * any associated state.
312 * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
314 * @param cls the `struct BobServiceSession`
315 * @param channel connection to the other end (henceforth invalid)
316 * @param channel_ctx place where local state associated
317 * with the channel is stored
320 cb_channel_destruction (void *cls,
321 const struct GNUNET_CADET_Channel *channel)
323 struct BobServiceSession *s = cls;
325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
326 "Peer disconnected, terminating session %s with peer %s\n",
327 GNUNET_h2s (&s->session_id),
328 GNUNET_i2s (&s->peer));
330 if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
332 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
333 prepare_client_end_notification (s);
335 destroy_service_session (s);
340 * MQ finished giving our last message to CADET, now notify
341 * the client that we are finished.
344 bob_cadet_done_cb (void *cls)
346 struct BobServiceSession *session = cls;
348 session->status = GNUNET_SCALARPRODUCT_STATUS_SUCCESS;
349 prepare_client_end_notification (session);
354 * Bob generates the response message to be sent to Alice.
356 * @param s the associated requesting session with Alice
359 transmit_bobs_cryptodata_message (struct BobServiceSession *s)
361 struct EccBobCryptodataMessage *msg;
362 struct GNUNET_MQ_Envelope *e;
364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
365 "Sending response to Alice\n");
366 e = GNUNET_MQ_msg (msg,
367 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA);
368 msg->contained_element_count = htonl (2);
369 if (NULL != s->prod_g_i_b_i)
370 GNUNET_CRYPTO_ecc_point_to_bin (edc,
373 if (NULL != s->prod_h_i_b_i)
374 GNUNET_CRYPTO_ecc_point_to_bin (edc,
377 GNUNET_MQ_notify_sent (e,
380 GNUNET_MQ_send (s->cadet_mq,
386 * Iterator to copy over messages from the hash map
387 * into an array for sorting.
389 * @param cls the `struct BobServiceSession *`
390 * @param key the key (unused)
391 * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
392 * TODO: code duplication with Alice!
395 copy_element_cb (void *cls,
396 const struct GNUNET_HashCode *key,
399 struct BobServiceSession *s = cls;
400 struct GNUNET_SCALARPRODUCT_Element *e = value;
404 mval = gcry_mpi_new (0);
405 val = (int64_t) GNUNET_ntohll (e->value);
407 gcry_mpi_sub_ui (mval, mval, -val);
409 gcry_mpi_add_ui (mval, mval, val);
410 s->sorted_elements [s->used_element_count].value = mval;
411 s->sorted_elements [s->used_element_count].key = &e->key;
412 s->used_element_count++;
418 * Compare two `struct MpiValue`s by key for sorting.
420 * @param a pointer to first `struct MpiValue *`
421 * @param b pointer to first `struct MpiValue *`
422 * @return -1 for a < b, 0 for a=b, 1 for a > b.
423 * TODO: code duplication with Alice!
426 element_cmp (const void *a,
429 const struct MpiElement *ma = a;
430 const struct MpiElement *mb = b;
432 return GNUNET_CRYPTO_hash_cmp (ma->key,
438 * Check a multipart-chunk of a request from another service to
439 * calculate a scalarproduct with us.
441 * @param cls closure (set from #GNUNET_CADET_connect)
442 * @param msg the actual message
443 * @return #GNUNET_OK to keep the connection open,
444 * #GNUNET_SYSERR to close it (signal serious error)
447 check_alices_cryptodata_message (void *cls,
448 const struct EccAliceCryptodataMessage *msg)
450 struct BobServiceSession *s = cls;
451 uint32_t contained_elements;
456 msize = ntohs (msg->header.size);
457 if (msize <= sizeof (struct EccAliceCryptodataMessage))
460 return GNUNET_SYSERR;
462 contained_elements = ntohl (msg->contained_element_count);
463 /* Our intersection may still be ongoing, but this is nevertheless
464 an upper bound on the required array size */
465 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
466 msg_length = sizeof (struct EccAliceCryptodataMessage)
467 + contained_elements * sizeof (struct GNUNET_CRYPTO_EccPoint) * 2;
468 if ( (msize != msg_length) ||
469 (0 == contained_elements) ||
470 (contained_elements > UINT16_MAX) ||
471 (max < contained_elements + s->cadet_received_element_count) )
474 return GNUNET_SYSERR;
481 * Handle a multipart-chunk of a request from another service to
482 * calculate a scalarproduct with us.
484 * @param cls closure (set from #GNUNET_CADET_connect)
485 * @param msg the actual message
488 handle_alices_cryptodata_message (void *cls,
489 const struct EccAliceCryptodataMessage *msg)
491 struct BobServiceSession *s = cls;
492 const struct GNUNET_CRYPTO_EccPoint *payload;
493 uint32_t contained_elements;
496 const struct MpiElement *b_i;
497 gcry_mpi_point_t tmp;
498 gcry_mpi_point_t g_i;
499 gcry_mpi_point_t h_i;
500 gcry_mpi_point_t g_i_b_i;
501 gcry_mpi_point_t h_i_b_i;
503 contained_elements = ntohl (msg->contained_element_count);
504 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
505 /* sort our vector for the computation */
506 if (NULL == s->sorted_elements)
509 = GNUNET_new_array (GNUNET_CONTAINER_multihashmap_size (s->intersected_elements),
511 s->used_element_count = 0;
512 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
515 qsort (s->sorted_elements,
516 s->used_element_count,
517 sizeof (struct MpiElement),
521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
522 "Received %u crypto values from Alice\n",
523 (unsigned int) contained_elements);
524 payload = (const struct GNUNET_CRYPTO_EccPoint *) &msg[1];
526 for (i=0;i<contained_elements;i++)
528 b_i = &s->sorted_elements[i + s->cadet_received_element_count];
529 g_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
531 g_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
534 gcry_mpi_point_release (g_i);
535 h_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
536 &payload[i * 2 + 1]);
537 h_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
540 gcry_mpi_point_release (h_i);
541 if (0 == i + s->cadet_received_element_count)
543 /* first iteration, nothing to add */
544 s->prod_g_i_b_i = g_i_b_i;
545 s->prod_h_i_b_i = h_i_b_i;
549 /* further iterations, cummulate resulting value */
550 tmp = GNUNET_CRYPTO_ecc_add (edc,
553 gcry_mpi_point_release (s->prod_g_i_b_i);
554 gcry_mpi_point_release (g_i_b_i);
555 s->prod_g_i_b_i = tmp;
556 tmp = GNUNET_CRYPTO_ecc_add (edc,
559 gcry_mpi_point_release (s->prod_h_i_b_i);
560 gcry_mpi_point_release (h_i_b_i);
561 s->prod_h_i_b_i = tmp;
564 s->cadet_received_element_count += contained_elements;
565 if ( (s->cadet_received_element_count == max) &&
566 (NULL == s->intersection_op) )
568 /* intersection has finished also on our side, and
569 we got the full set, so we can proceed with the
571 transmit_bobs_cryptodata_message (s);
573 GNUNET_CADET_receive_done (s->channel);
578 * Callback for set operation results. Called for each element
579 * that needs to be removed from the result set.
581 * @param cls closure with the `struct BobServiceSession`
582 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
583 * @param current_size current set size
584 * @param status what has happened with the set intersection?
587 cb_intersection_element_removed (void *cls,
588 const struct GNUNET_SET_Element *element,
589 uint64_t current_size,
590 enum GNUNET_SET_Status status)
592 struct BobServiceSession *s = cls;
593 struct GNUNET_SCALARPRODUCT_Element *se;
597 case GNUNET_SET_STATUS_OK:
598 /* this element has been removed from the set */
599 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
601 GNUNET_assert (NULL != se);
602 LOG (GNUNET_ERROR_TYPE_DEBUG,
603 "Removed element with key %s and value %lld\n",
604 GNUNET_h2s (&se->key),
605 (long long) GNUNET_ntohll (se->value));
606 GNUNET_assert (GNUNET_YES ==
607 GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
612 case GNUNET_SET_STATUS_DONE:
613 s->intersection_op = NULL;
614 GNUNET_break (NULL == s->intersection_set);
615 GNUNET_CADET_receive_done (s->channel);
616 LOG (GNUNET_ERROR_TYPE_DEBUG,
617 "Finished intersection, %d items remain\n",
618 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements));
619 if (s->client_received_element_count ==
620 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements))
622 /* CADET transmission from Alice is also already done,
623 start with our own reply */
624 transmit_bobs_cryptodata_message (s);
627 case GNUNET_SET_STATUS_HALF_DONE:
628 /* unexpected for intersection */
631 case GNUNET_SET_STATUS_FAILURE:
632 /* unhandled status code */
633 LOG (GNUNET_ERROR_TYPE_DEBUG,
634 "Set intersection failed!\n");
635 s->intersection_op = NULL;
636 if (NULL != s->intersection_set)
638 GNUNET_SET_destroy (s->intersection_set);
639 s->intersection_set = NULL;
641 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
642 prepare_client_end_notification (s);
652 * We've paired up a client session with an incoming CADET request.
653 * Initiate set intersection work.
655 * @param s client session to start intersection for
658 start_intersection (struct BobServiceSession *s)
660 struct GNUNET_HashCode set_sid;
662 GNUNET_CRYPTO_hash (&s->session_id,
663 sizeof (struct GNUNET_HashCode),
665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
666 "Got session with key %s and %u elements, starting intersection.\n",
667 GNUNET_h2s (&s->session_id),
668 (unsigned int) s->total);
671 = GNUNET_SET_prepare (&s->peer,
674 GNUNET_SET_RESULT_REMOVED,
675 (struct GNUNET_SET_Option[]) {{ 0 }},
676 &cb_intersection_element_removed,
679 GNUNET_SET_commit (s->intersection_op,
680 s->intersection_set))
683 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
684 prepare_client_end_notification (s);
687 GNUNET_SET_destroy (s->intersection_set);
688 s->intersection_set = NULL;
693 * Handle a request from Alice to calculate a scalarproduct with us (Bob).
695 * @param cls closure (set from #GNUNET_CADET_connect)
696 * @param msg the actual message
699 handle_alices_computation_request (void *cls,
700 const struct EccServiceRequestMessage *msg)
702 struct BobServiceSession *s = cls;
704 s->session_id = msg->session_id; // ??
705 if (s->client_received_element_count < s->total)
707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
708 "Alice ready, still waiting for Bob client data!\n");
711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
712 "Both ready, launching intersection!\n");
713 start_intersection (s);
718 * Function called for inbound channels on Bob's end. Does some
719 * preliminary initialization, more happens after we get Alice's first
722 * @param cls our `struct BobServiceSession`
723 * @param channel new handle to the channel
724 * @param initiator peer that started the channel
725 * @return session associated with the channel
728 cb_channel_incoming (void *cls,
729 struct GNUNET_CADET_Channel *channel,
730 const struct GNUNET_PeerIdentity *initiator)
732 struct BobServiceSession *s = cls;
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735 "New incoming channel from peer %s.\n",
736 GNUNET_i2s (initiator));
737 GNUNET_CADET_close_port (s->port);
739 s->peer = *initiator;
740 s->channel = channel;
741 s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
747 * We're receiving additional set data. Check it is well-formed.
749 * @param cls identification of the client
750 * @param msg the actual message
751 * @return #GNUNET_OK if @a msg is well-formed
754 check_bob_client_message_multipart (void *cls,
755 const struct ComputationBobCryptodataMultipartMessage *msg)
757 struct BobServiceSession *s = cls;
758 uint32_t contained_count;
761 msize = ntohs (msg->header.size);
762 contained_count = ntohl (msg->element_count_contained);
763 if ( (msize != (sizeof (struct ComputationBobCryptodataMultipartMessage) +
764 contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
765 (0 == contained_count) ||
766 (UINT16_MAX < contained_count) ||
767 (s->total == s->client_received_element_count) ||
768 (s->total < s->client_received_element_count + contained_count) )
771 return GNUNET_SYSERR;
778 * We're receiving additional set data. Add it to our
779 * set and if we are done, initiate the transaction.
781 * @param cls identification of the client
782 * @param msg the actual message
785 handle_bob_client_message_multipart (void *cls,
786 const struct ComputationBobCryptodataMultipartMessage *msg)
788 struct BobServiceSession *s = cls;
789 uint32_t contained_count;
790 const struct GNUNET_SCALARPRODUCT_Element *elements;
791 struct GNUNET_SET_Element set_elem;
792 struct GNUNET_SCALARPRODUCT_Element *elem;
794 contained_count = ntohl (msg->element_count_contained);
795 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
796 for (uint32_t i = 0; i < contained_count; i++)
798 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
801 sizeof (struct GNUNET_SCALARPRODUCT_Element));
803 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
806 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
812 set_elem.data = &elem->key;
813 set_elem.size = sizeof (elem->key);
814 set_elem.element_type = 0;
815 GNUNET_SET_add_element (s->intersection_set,
819 s->client_received_element_count += contained_count;
820 GNUNET_SERVICE_client_continue (s->client);
821 if (s->total != s->client_received_element_count)
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825 "Request still partial, waiting for more client data!\n");
828 if (NULL == s->channel)
830 /* no Alice waiting for this request, wait for Alice */
831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
832 "Client ready, still waiting for Alice!\n");
835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
836 "Both ready, launching intersection!\n");
837 start_intersection (s);
842 * Handler for Bob's a client request message. Check @a msg is
845 * @param cls identification of the client
846 * @param msg the actual message
847 * @return #GNUNET_OK if @a msg is well-formed
850 check_bob_client_message (void *cls,
851 const struct BobComputationMessage *msg)
853 struct BobServiceSession *s = cls;
854 uint32_t contained_count;
855 uint32_t total_count;
858 if (GNUNET_SCALARPRODUCT_STATUS_INIT != s->status)
861 return GNUNET_SYSERR;
863 msize = ntohs (msg->header.size);
864 total_count = ntohl (msg->element_count_total);
865 contained_count = ntohl (msg->element_count_contained);
866 if ( (0 == total_count) ||
867 (0 == contained_count) ||
868 (UINT16_MAX < contained_count) ||
869 (msize != (sizeof (struct BobComputationMessage) +
870 contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) )
873 return GNUNET_SYSERR;
880 * Handler for Bob's a client request message. Bob is in the response
881 * role, keep the values + session and waiting for a matching session
882 * or process a waiting request from Alice.
884 * @param cls identification of the client
885 * @param msg the actual message
888 handle_bob_client_message (void *cls,
889 const struct BobComputationMessage *msg)
891 struct BobServiceSession *s = cls;
892 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
893 GNUNET_MQ_hd_fixed_size (alices_computation_request,
894 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_SESSION_INITIALIZATION,
895 struct EccServiceRequestMessage,
897 GNUNET_MQ_hd_var_size (alices_cryptodata_message,
898 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_ALICE_CRYPTODATA,
899 struct EccAliceCryptodataMessage,
901 GNUNET_MQ_handler_end ()
903 uint32_t contained_count;
904 uint32_t total_count;
905 const struct GNUNET_SCALARPRODUCT_Element *elements;
906 struct GNUNET_SET_Element set_elem;
907 struct GNUNET_SCALARPRODUCT_Element *elem;
909 total_count = ntohl (msg->element_count_total);
910 contained_count = ntohl (msg->element_count_contained);
912 s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE;
913 s->total = total_count;
914 s->client_received_element_count = contained_count;
915 s->session_id = msg->session_key;
916 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
917 s->intersected_elements
918 = GNUNET_CONTAINER_multihashmap_create (s->total,
921 = GNUNET_SET_create (cfg,
922 GNUNET_SET_OPERATION_INTERSECTION);
923 for (uint32_t i = 0; i < contained_count; i++)
925 if (0 == GNUNET_ntohll (elements[i].value))
927 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
930 sizeof (struct GNUNET_SCALARPRODUCT_Element));
932 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
935 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
941 set_elem.data = &elem->key;
942 set_elem.size = sizeof (elem->key);
943 set_elem.element_type = 0;
944 GNUNET_SET_add_element (s->intersection_set,
947 s->used_element_count++;
949 GNUNET_SERVICE_client_continue (s->client);
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
951 "Received client request, opening port %s!\n",
952 GNUNET_h2s (&msg->session_key));
953 s->port = GNUNET_CADET_open_port (my_cadet,
955 &cb_channel_incoming,
958 &cb_channel_destruction,
963 GNUNET_SERVICE_client_drop (s->client);
970 * Task run during shutdown.
975 shutdown_task (void *cls)
977 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
978 "Shutting down, initiating cleanup.\n");
979 // FIXME: we have to cut our connections to CADET first!
980 if (NULL != my_cadet)
982 GNUNET_CADET_disconnect (my_cadet);
987 GNUNET_CRYPTO_ecc_dlog_release (edc);
994 * A client connected.
996 * Setup the associated data structure.
998 * @param cls closure, NULL
999 * @param client identification of the client
1000 * @param mq message queue to communicate with @a client
1001 * @return our `struct BobServiceSession`
1004 client_connect_cb (void *cls,
1005 struct GNUNET_SERVICE_Client *client,
1006 struct GNUNET_MQ_Handle *mq)
1008 struct BobServiceSession *s;
1010 s = GNUNET_new (struct BobServiceSession);
1018 * A client disconnected.
1020 * Remove the associated session(s), release data structures
1021 * and cancel pending outgoing transmissions to the client.
1023 * @param cls closure, NULL
1024 * @param client identification of the client
1025 * @param app_cls our `struct BobServiceSession`
1028 client_disconnect_cb (void *cls,
1029 struct GNUNET_SERVICE_Client *client,
1032 struct BobServiceSession *s = app_cls;
1034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1035 "Client disconnected from us.\n");
1037 destroy_service_session (s);
1042 * Initialization of the program and message handlers
1044 * @param cls closure
1045 * @param c configuration to use
1046 * @param service the initialized service
1050 const struct GNUNET_CONFIGURATION_Handle *c,
1051 struct GNUNET_SERVICE_Handle *service)
1054 /* We don't really do DLOG, so we can setup with very minimal resources */
1055 edc = GNUNET_CRYPTO_ecc_dlog_prepare (4 /* max value */,
1057 my_cadet = GNUNET_CADET_connect (cfg);
1058 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1060 if (NULL == my_cadet)
1062 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1063 _("Connect to CADET failed\n"));
1064 GNUNET_SCHEDULER_shutdown ();
1071 * Define "main" method using service macro.
1074 ("scalarproduct-bob",
1075 GNUNET_SERVICE_OPTION_NONE,
1078 &client_disconnect_cb,
1080 GNUNET_MQ_hd_var_size (bob_client_message,
1081 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
1082 struct BobComputationMessage,
1084 GNUNET_MQ_hd_var_size (bob_client_message_multipart,
1085 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB,
1086 struct ComputationBobCryptodataMultipartMessage,
1088 GNUNET_MQ_handler_end ());
1091 /* end of gnunet-service-scalarproduct-ecc_bob.c */