aboutsummaryrefslogtreecommitdiff
path: root/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c')
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c1062
1 files changed, 0 insertions, 1062 deletions
diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
deleted file mode 100644
index 02a62c164..000000000
--- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
+++ /dev/null
@@ -1,1062 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013-2017, 2021 GNUnet e.V.
4
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.
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 Affero General Public License for more details.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file scalarproduct/gnunet-service-scalarproduct-ecc_bob.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_seti_service.h"
36#include "scalarproduct.h"
37#include "gnunet-service-scalarproduct-ecc.h"
38
39#define LOG(kind, ...) GNUNET_log_from (kind, "scalarproduct-bob", __VA_ARGS__)
40
41
42/**
43 * An encrypted element key-value pair.
44 */
45struct MpiElement
46{
47 /**
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.
51 */
52 const struct GNUNET_HashCode *key;
53
54 /**
55 * Value represented (a).
56 */
57 int64_t value;
58};
59
60
61/**
62 * A scalarproduct session which tracks an offer for a
63 * multiplication service by a local client.
64 */
65struct BobServiceSession
66{
67 /**
68 * The client this request is related to.
69 */
70 struct GNUNET_SERVICE_Client *client;
71
72 /**
73 * Client message queue.
74 */
75 struct GNUNET_MQ_Handle *client_mq;
76
77 /**
78 * All non-0-value'd elements transmitted to us.
79 */
80 struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
81
82 /**
83 * Set of elements for which we will be conducting an intersection.
84 * The resulting elements are then used for computing the scalar product.
85 */
86 struct GNUNET_SETI_Handle *intersection_set;
87
88 /**
89 * Set of elements for which will conduction an intersection.
90 * the resulting elements are then used for computing the scalar product.
91 */
92 struct GNUNET_SETI_OperationHandle *intersection_op;
93
94 /**
95 * Our open port.
96 */
97 struct GNUNET_CADET_Port *port;
98
99 /**
100 * b(Bob)
101 */
102 struct MpiElement *sorted_elements;
103
104 /**
105 * Product of the g_i^{b_i}
106 */
107 struct GNUNET_CRYPTO_EccPoint prod_g_i_b_i;
108
109 /**
110 * Product of the h_i^{b_i}
111 */
112 struct GNUNET_CRYPTO_EccPoint prod_h_i_b_i;
113
114 /**
115 * How many elements will be supplied in total from the client.
116 */
117 uint32_t total;
118
119 /**
120 * Already transferred elements (received) for multipart
121 * messages from client. Always less than @e total.
122 */
123 uint32_t client_received_element_count;
124
125 /**
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.
129 */
130 uint32_t used_element_count;
131
132 /**
133 * Counts the number of values received from Alice by us.
134 * Always less than @e used_element_count.
135 */
136 uint32_t cadet_received_element_count;
137
138 /**
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.
143 */
144 enum GNUNET_SCALARPRODUCT_ResponseStatus status;
145
146 /**
147 * Are we already in #destroy_service_session()?
148 */
149 int in_destroy;
150
151 /**
152 * The CADET channel.
153 */
154 struct GNUNET_CADET_Channel *channel;
155
156 /**
157 * Originator's peer identity. (Only for diagnostics.)
158 */
159 struct GNUNET_PeerIdentity peer;
160
161 /**
162 * (hopefully) unique transaction ID
163 */
164 struct GNUNET_HashCode session_id;
165
166 /**
167 * The message queue for this channel.
168 */
169 struct GNUNET_MQ_Handle *cadet_mq;
170};
171
172
173/**
174 * GNUnet configuration handle
175 */
176static const struct GNUNET_CONFIGURATION_Handle *cfg;
177
178/**
179 * Handle to the CADET service.
180 */
181static struct GNUNET_CADET_Handle *my_cadet;
182
183/**
184 * Context for DLOG operations on a curve.
185 */
186static struct GNUNET_CRYPTO_EccDlogContext *edc;
187
188
189/**
190 * Callback used to free the elements in the map.
191 *
192 * @param cls NULL
193 * @param key key of the element
194 * @param value the value to free
195 */
196static int
197free_element_cb (void *cls,
198 const struct GNUNET_HashCode *key,
199 void *value)
200{
201 struct GNUNET_SCALARPRODUCT_Element *element = value;
202
203 GNUNET_free (element);
204 return GNUNET_OK;
205}
206
207
208/**
209 * Destroy session state, we are done with it.
210 *
211 * @param session the session to free elements from
212 */
213static void
214destroy_service_session (struct BobServiceSession *s)
215{
216 if (GNUNET_YES == s->in_destroy)
217 return;
218 s->in_destroy = GNUNET_YES;
219 if (NULL != s->client)
220 {
221 struct GNUNET_SERVICE_Client *c = s->client;
222
223 s->client = NULL;
224 GNUNET_SERVICE_client_drop (c);
225 }
226 if (NULL != s->intersected_elements)
227 {
228 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
229 &free_element_cb,
230 NULL);
231 GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
232 s->intersected_elements = NULL;
233 }
234 if (NULL != s->intersection_op)
235 {
236 GNUNET_SETI_operation_cancel (s->intersection_op);
237 s->intersection_op = NULL;
238 }
239 if (NULL != s->intersection_set)
240 {
241 GNUNET_SETI_destroy (s->intersection_set);
242 s->intersection_set = NULL;
243 }
244 if (NULL != s->sorted_elements)
245 {
246 GNUNET_free (s->sorted_elements);
247 s->sorted_elements = NULL;
248 }
249 if (NULL != s->port)
250 {
251 GNUNET_CADET_close_port (s->port);
252 s->port = NULL;
253 }
254 if (NULL != s->channel)
255 {
256 GNUNET_CADET_channel_destroy (s->channel);
257 s->channel = NULL;
258 }
259 GNUNET_free (s);
260}
261
262
263/**
264 * Notify the client that the session has succeeded or failed. This
265 * message gets sent to Bob's client if the operation completed or
266 * Alice disconnected.
267 *
268 * @param session the associated client session to fail or succeed
269 */
270static void
271prepare_client_end_notification (struct BobServiceSession *session)
272{
273 struct ClientResponseMessage *msg;
274 struct GNUNET_MQ_Envelope *e;
275
276 if (NULL == session->client_mq)
277 return; /* no client left to be notified */
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
279 "Sending session-end notification with status %d to client for session %s\n",
280 session->status,
281 GNUNET_h2s (&session->session_id));
282 e = GNUNET_MQ_msg (msg,
283 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
284 msg->range = 0;
285 msg->product_length = htonl (0);
286 msg->status = htonl (session->status);
287 GNUNET_MQ_send (session->client_mq,
288 e);
289}
290
291
292/**
293 * Function called whenever a channel is destroyed. Should clean up
294 * any associated state.
295 *
296 * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
297 *
298 * @param cls the `struct BobServiceSession`
299 * @param channel connection to the other end (henceforth invalid)
300 * @param channel_ctx place where local state associated
301 * with the channel is stored
302 */
303static void
304cb_channel_destruction (void *cls,
305 const struct GNUNET_CADET_Channel *channel)
306{
307 struct BobServiceSession *s = cls;
308
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
310 "Peer disconnected, terminating session %s with peer %s\n",
311 GNUNET_h2s (&s->session_id),
312 GNUNET_i2s (&s->peer));
313 s->channel = NULL;
314 if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
315 {
316 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
317 prepare_client_end_notification (s);
318 }
319 destroy_service_session (s);
320}
321
322
323/**
324 * MQ finished giving our last message to CADET, now notify
325 * the client that we are finished.
326 */
327static void
328bob_cadet_done_cb (void *cls)
329{
330 struct BobServiceSession *session = cls;
331
332 session->status = GNUNET_SCALARPRODUCT_STATUS_SUCCESS;
333 prepare_client_end_notification (session);
334}
335
336
337/**
338 * Bob generates the response message to be sent to Alice.
339 *
340 * @param s the associated requesting session with Alice
341 */
342static void
343transmit_bobs_cryptodata_message (struct BobServiceSession *s)
344{
345 struct EccBobCryptodataMessage *msg;
346 struct GNUNET_MQ_Envelope *e;
347
348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
349 "Sending response to Alice\n");
350 e = GNUNET_MQ_msg (msg,
351 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA);
352 msg->contained_element_count = htonl (2);
353 msg->prod_g_i_b_i = s->prod_g_i_b_i;
354 msg->prod_h_i_b_i = s->prod_h_i_b_i;
355 GNUNET_MQ_notify_sent (e,
356 &bob_cadet_done_cb,
357 s);
358 GNUNET_MQ_send (s->cadet_mq,
359 e);
360}
361
362
363/**
364 * Iterator to copy over messages from the hash map
365 * into an array for sorting.
366 *
367 * @param cls the `struct AliceServiceSession *`
368 * @param key the key (unused)
369 * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
370 */
371static int
372copy_element_cb (void *cls,
373 const struct GNUNET_HashCode *key,
374 void *value)
375{
376 struct BobServiceSession *s = cls;
377 struct GNUNET_SCALARPRODUCT_Element *e = value;
378
379 s->sorted_elements[s->used_element_count].value = (int64_t) GNUNET_ntohll (
380 e->value);
381 s->sorted_elements[s->used_element_count].key = &e->key;
382 s->used_element_count++;
383 return GNUNET_OK;
384}
385
386
387/**
388 * Compare two `struct MpiValue`s by key for sorting.
389 *
390 * @param a pointer to first `struct MpiValue *`
391 * @param b pointer to first `struct MpiValue *`
392 * @return -1 for a < b, 0 for a=b, 1 for a > b.
393 * TODO: code duplication with Alice!
394 */
395static int
396element_cmp (const void *a,
397 const void *b)
398{
399 const struct MpiElement *ma = a;
400 const struct MpiElement *mb = b;
401
402 return GNUNET_CRYPTO_hash_cmp (ma->key,
403 mb->key);
404}
405
406
407/**
408 * Check a multipart-chunk of a request from another service to
409 * calculate a scalarproduct with us.
410 *
411 * @param cls closure (set from #GNUNET_CADET_connect)
412 * @param msg the actual message
413 * @return #GNUNET_OK to keep the connection open,
414 * #GNUNET_SYSERR to close it (signal serious error)
415 */
416static int
417check_alices_cryptodata_message (void *cls,
418 const struct EccAliceCryptodataMessage *msg)
419{
420 struct BobServiceSession *s = cls;
421 uint32_t contained_elements;
422 size_t msg_length;
423 uint16_t msize;
424 unsigned int max;
425
426 msize = ntohs (msg->header.size);
427 if (msize <= sizeof(struct EccAliceCryptodataMessage))
428 {
429 GNUNET_break_op (0);
430 return GNUNET_SYSERR;
431 }
432 contained_elements = ntohl (msg->contained_element_count);
433 /* Our intersection may still be ongoing, but this is nevertheless
434 an upper bound on the required array size */
435 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
436 msg_length = sizeof(struct EccAliceCryptodataMessage)
437 + contained_elements * sizeof(struct GNUNET_CRYPTO_EccPoint) * 2;
438 if ((msize != msg_length) ||
439 (0 == contained_elements) ||
440 (contained_elements > UINT16_MAX) ||
441 (max < contained_elements + s->cadet_received_element_count))
442 {
443 GNUNET_break_op (0);
444 return GNUNET_SYSERR;
445 }
446 return GNUNET_OK;
447}
448
449
450/**
451 * Handle a multipart-chunk of a request from another service to
452 * calculate a scalarproduct with us.
453 *
454 * @param cls closure (set from #GNUNET_CADET_connect)
455 * @param msg the actual message
456 */
457static void
458handle_alices_cryptodata_message (void *cls,
459 const struct EccAliceCryptodataMessage *msg)
460{
461 struct BobServiceSession *s = cls;
462 const struct GNUNET_CRYPTO_EccPoint *payload;
463 uint32_t contained_elements;
464 unsigned int max;
465 const struct GNUNET_CRYPTO_EccPoint *g_i;
466 const struct GNUNET_CRYPTO_EccPoint *h_i;
467 struct GNUNET_CRYPTO_EccPoint g_i_b_i;
468 struct GNUNET_CRYPTO_EccPoint h_i_b_i;
469
470 contained_elements = ntohl (msg->contained_element_count);
471 max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
472 /* sort our vector for the computation */
473 if (NULL == s->sorted_elements)
474 {
475 s->sorted_elements
476 = GNUNET_new_array (GNUNET_CONTAINER_multihashmap_size (
477 s->intersected_elements),
478 struct MpiElement);
479 s->used_element_count = 0;
480 GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
481 &copy_element_cb,
482 s);
483 qsort (s->sorted_elements,
484 s->used_element_count,
485 sizeof(struct MpiElement),
486 &element_cmp);
487 }
488
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Received %u crypto values from Alice\n",
491 (unsigned int) contained_elements);
492 payload = (const struct GNUNET_CRYPTO_EccPoint *) &msg[1];
493
494 for (unsigned int i = 0; i < contained_elements; i++)
495 {
496 int64_t val = s->sorted_elements[i + s->cadet_received_element_count].value;
497 struct GNUNET_CRYPTO_EccScalar vali;
498
499 GNUNET_assert (INT64_MIN != val);
500 GNUNET_CRYPTO_ecc_scalar_from_int (val > 0 ? val : -val,
501 &vali);
502 if (val < 0)
503 crypto_core_ed25519_scalar_negate (vali.v,
504 vali.v);
505 g_i = &payload[i * 2];
506 /* g_i_b_i = g_i^vali */
507 GNUNET_assert (GNUNET_OK ==
508 GNUNET_CRYPTO_ecc_pmul_mpi (g_i,
509 &vali,
510 &g_i_b_i));
511 h_i = &payload[i * 2 + 1];
512 /* h_i_b_i = h_i^vali */
513 GNUNET_assert (GNUNET_OK ==
514 GNUNET_CRYPTO_ecc_pmul_mpi (h_i,
515 &vali,
516 &h_i_b_i));
517 if (0 == i + s->cadet_received_element_count)
518 {
519 /* first iteration, nothing to add */
520 s->prod_g_i_b_i = g_i_b_i;
521 s->prod_h_i_b_i = h_i_b_i;
522 }
523 else
524 {
525 /* further iterations, cummulate resulting value */
526 GNUNET_assert (GNUNET_OK ==
527 GNUNET_CRYPTO_ecc_add (&s->prod_g_i_b_i,
528 &g_i_b_i,
529 &s->prod_g_i_b_i));
530 GNUNET_assert (GNUNET_OK ==
531 GNUNET_CRYPTO_ecc_add (&s->prod_h_i_b_i,
532 &h_i_b_i,
533 &s->prod_h_i_b_i));
534 }
535 }
536 s->cadet_received_element_count += contained_elements;
537 if ((s->cadet_received_element_count == max) &&
538 (NULL == s->intersection_op))
539 {
540 /* intersection has finished also on our side, and
541 we got the full set, so we can proceed with the
542 CADET response(s) */
543 transmit_bobs_cryptodata_message (s);
544 }
545 GNUNET_CADET_receive_done (s->channel);
546}
547
548
549/**
550 * Callback for set operation results. Called for each element
551 * that needs to be removed from the result set.
552 *
553 * @param cls closure with the `struct BobServiceSession`
554 * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
555 * @param current_size current set size
556 * @param status what has happened with the set intersection?
557 */
558static void
559cb_intersection_element_removed (void *cls,
560 const struct GNUNET_SETI_Element *element,
561 uint64_t current_size,
562 enum GNUNET_SETI_Status status)
563{
564 struct BobServiceSession *s = cls;
565 struct GNUNET_SCALARPRODUCT_Element *se;
566
567 switch (status)
568 {
569 case GNUNET_SETI_STATUS_DEL_LOCAL:
570 /* this element has been removed from the set */
571 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
572 element->data);
573 GNUNET_assert (NULL != se);
574 LOG (GNUNET_ERROR_TYPE_DEBUG,
575 "Removed element with key %s and value %lld\n",
576 GNUNET_h2s (&se->key),
577 (long long) GNUNET_ntohll (se->value));
578 GNUNET_assert (GNUNET_YES ==
579 GNUNET_CONTAINER_multihashmap_remove (
580 s->intersected_elements,
581 element->data,
582 se));
583 GNUNET_free (se);
584 return;
585 case GNUNET_SETI_STATUS_DONE:
586 s->intersection_op = NULL;
587 GNUNET_break (NULL == s->intersection_set);
588 GNUNET_CADET_receive_done (s->channel);
589 LOG (GNUNET_ERROR_TYPE_DEBUG,
590 "Finished intersection, %d items remain\n",
591 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements));
592 if (s->client_received_element_count ==
593 GNUNET_CONTAINER_multihashmap_size (s->intersected_elements))
594 {
595 /* CADET transmission from Alice is also already done,
596 start with our own reply */
597 transmit_bobs_cryptodata_message (s);
598 }
599 return;
600 case GNUNET_SETI_STATUS_FAILURE:
601 /* unhandled status code */
602 LOG (GNUNET_ERROR_TYPE_DEBUG,
603 "Set intersection failed!\n");
604 s->intersection_op = NULL;
605 if (NULL != s->intersection_set)
606 {
607 GNUNET_SETI_destroy (s->intersection_set);
608 s->intersection_set = NULL;
609 }
610 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
611 prepare_client_end_notification (s);
612 return;
613
614 default:
615 GNUNET_break (0);
616 return;
617 }
618}
619
620
621/**
622 * We've paired up a client session with an incoming CADET request.
623 * Initiate set intersection work.
624 *
625 * @param s client session to start intersection for
626 */
627static void
628start_intersection (struct BobServiceSession *s)
629{
630 struct GNUNET_HashCode set_sid;
631
632 GNUNET_CRYPTO_hash (&s->session_id,
633 sizeof(struct GNUNET_HashCode),
634 &set_sid);
635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
636 "Got session with key %s and %u elements, starting intersection.\n",
637 GNUNET_h2s (&s->session_id),
638 (unsigned int) s->total);
639
640 s->intersection_op
641 = GNUNET_SETI_prepare (&s->peer,
642 &set_sid,
643 NULL,
644 (struct GNUNET_SETI_Option[]) { { 0 } },
645 &cb_intersection_element_removed,
646 s);
647 if (GNUNET_OK !=
648 GNUNET_SETI_commit (s->intersection_op,
649 s->intersection_set))
650 {
651 GNUNET_break (0);
652 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
653 prepare_client_end_notification (s);
654 return;
655 }
656 GNUNET_SETI_destroy (s->intersection_set);
657 s->intersection_set = NULL;
658}
659
660
661/**
662 * Handle a request from Alice to calculate a scalarproduct with us (Bob).
663 *
664 * @param cls closure (set from #GNUNET_CADET_connect)
665 * @param msg the actual message
666 */
667static void
668handle_alices_computation_request (void *cls,
669 const struct EccServiceRequestMessage *msg)
670{
671 struct BobServiceSession *s = cls;
672
673 s->session_id = msg->session_id; // ??
674 if (s->client_received_element_count < s->total)
675 {
676 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
677 "Alice ready, still waiting for Bob client data!\n");
678 return;
679 }
680 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
681 "Both ready, launching intersection!\n");
682 start_intersection (s);
683}
684
685
686/**
687 * Function called for inbound channels on Bob's end. Does some
688 * preliminary initialization, more happens after we get Alice's first
689 * message.
690 *
691 * @param cls our `struct BobServiceSession`
692 * @param channel new handle to the channel
693 * @param initiator peer that started the channel
694 * @return session associated with the channel
695 */
696static void *
697cb_channel_incoming (void *cls,
698 struct GNUNET_CADET_Channel *channel,
699 const struct GNUNET_PeerIdentity *initiator)
700{
701 struct BobServiceSession *s = cls;
702
703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
704 "New incoming channel from peer %s.\n",
705 GNUNET_i2s (initiator));
706 GNUNET_CADET_close_port (s->port);
707 s->port = NULL;
708 s->peer = *initiator;
709 s->channel = channel;
710 s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
711 return s;
712}
713
714
715/**
716 * We're receiving additional set data. Check it is well-formed.
717 *
718 * @param cls identification of the client
719 * @param msg the actual message
720 * @return #GNUNET_OK if @a msg is well-formed
721 */
722static int
723check_bob_client_message_multipart (
724 void *cls,
725 const struct ComputationBobCryptodataMultipartMessage *msg)
726{
727 struct BobServiceSession *s = cls;
728 uint32_t contained_count;
729 uint16_t msize;
730
731 msize = ntohs (msg->header.size);
732 contained_count = ntohl (msg->element_count_contained);
733 if ((msize != (sizeof(struct ComputationBobCryptodataMultipartMessage)
734 + contained_count * sizeof(struct
735 GNUNET_SCALARPRODUCT_Element))) ||
736 (0 == contained_count) ||
737 (UINT16_MAX < contained_count) ||
738 (s->total == s->client_received_element_count) ||
739 (s->total < s->client_received_element_count + contained_count))
740 {
741 GNUNET_break (0);
742 return GNUNET_SYSERR;
743 }
744 return GNUNET_OK;
745}
746
747
748/**
749 * We're receiving additional set data. Add it to our
750 * set and if we are done, initiate the transaction.
751 *
752 * @param cls identification of the client
753 * @param msg the actual message
754 */
755static void
756handle_bob_client_message_multipart (
757 void *cls,
758 const struct ComputationBobCryptodataMultipartMessage *msg)
759{
760 struct BobServiceSession *s = cls;
761 uint32_t contained_count;
762 const struct GNUNET_SCALARPRODUCT_Element *elements;
763 struct GNUNET_SETI_Element set_elem;
764 struct GNUNET_SCALARPRODUCT_Element *elem;
765
766 contained_count = ntohl (msg->element_count_contained);
767 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
768 for (uint32_t i = 0; i < contained_count; i++)
769 {
770 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
771 GNUNET_memcpy (elem,
772 &elements[i],
773 sizeof(struct GNUNET_SCALARPRODUCT_Element));
774 if (GNUNET_SYSERR ==
775 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
776 &elem->key,
777 elem,
778 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
779 {
780 GNUNET_break (0);
781 GNUNET_free (elem);
782 continue;
783 }
784 set_elem.data = &elem->key;
785 set_elem.size = sizeof(elem->key);
786 set_elem.element_type = 0;
787 GNUNET_SETI_add_element (s->intersection_set,
788 &set_elem,
789 NULL, NULL);
790 }
791 s->client_received_element_count += contained_count;
792 GNUNET_SERVICE_client_continue (s->client);
793 if (s->total != s->client_received_element_count)
794 {
795 /* more to come */
796 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
797 "Request still partial, waiting for more client data!\n");
798 return;
799 }
800 if (NULL == s->channel)
801 {
802 /* no Alice waiting for this request, wait for Alice */
803 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
804 "Client ready, still waiting for Alice!\n");
805 return;
806 }
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
808 "Both ready, launching intersection!\n");
809 start_intersection (s);
810}
811
812
813/**
814 * Handler for Bob's a client request message. Check @a msg is
815 * well-formed.
816 *
817 * @param cls identification of the client
818 * @param msg the actual message
819 * @return #GNUNET_OK if @a msg is well-formed
820 */
821static int
822check_bob_client_message (void *cls,
823 const struct BobComputationMessage *msg)
824{
825 struct BobServiceSession *s = cls;
826 uint32_t contained_count;
827 uint32_t total_count;
828 uint16_t msize;
829
830 if (GNUNET_SCALARPRODUCT_STATUS_INIT != s->status)
831 {
832 GNUNET_break (0);
833 return GNUNET_SYSERR;
834 }
835 msize = ntohs (msg->header.size);
836 total_count = ntohl (msg->element_count_total);
837 contained_count = ntohl (msg->element_count_contained);
838 if ((0 == total_count) ||
839 (0 == contained_count) ||
840 (UINT16_MAX < contained_count) ||
841 (msize != (sizeof(struct BobComputationMessage)
842 + contained_count * sizeof(struct
843 GNUNET_SCALARPRODUCT_Element))))
844 {
845 GNUNET_break_op (0);
846 return GNUNET_SYSERR;
847 }
848 return GNUNET_OK;
849}
850
851
852/**
853 * Handler for Bob's a client request message. Bob is in the response
854 * role, keep the values + session and waiting for a matching session
855 * or process a waiting request from Alice.
856 *
857 * @param cls identification of the client
858 * @param msg the actual message
859 */
860static void
861handle_bob_client_message (void *cls,
862 const struct BobComputationMessage *msg)
863{
864 struct BobServiceSession *s = cls;
865 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
866 GNUNET_MQ_hd_fixed_size (alices_computation_request,
867 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_SESSION_INITIALIZATION,
868 struct EccServiceRequestMessage,
869 s),
870 GNUNET_MQ_hd_var_size (alices_cryptodata_message,
871 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_ALICE_CRYPTODATA,
872 struct EccAliceCryptodataMessage,
873 s),
874 GNUNET_MQ_handler_end ()
875 };
876 uint32_t contained_count;
877 uint32_t total_count;
878 const struct GNUNET_SCALARPRODUCT_Element *elements;
879 struct GNUNET_SETI_Element set_elem;
880 struct GNUNET_SCALARPRODUCT_Element *elem;
881
882 total_count = ntohl (msg->element_count_total);
883 contained_count = ntohl (msg->element_count_contained);
884
885 s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE;
886 s->total = total_count;
887 s->client_received_element_count = contained_count;
888 s->session_id = msg->session_key;
889 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
890 s->intersected_elements
891 = GNUNET_CONTAINER_multihashmap_create (s->total,
892 GNUNET_YES);
893 s->intersection_set = GNUNET_SETI_create (cfg);
894 for (uint32_t i = 0; i < contained_count; i++)
895 {
896 if (0 == GNUNET_ntohll (elements[i].value))
897 continue;
898 elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
899 GNUNET_memcpy (elem,
900 &elements[i],
901 sizeof(struct GNUNET_SCALARPRODUCT_Element));
902 if (GNUNET_SYSERR ==
903 GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
904 &elem->key,
905 elem,
906 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
907 {
908 GNUNET_break (0);
909 GNUNET_free (elem);
910 continue;
911 }
912 set_elem.data = &elem->key;
913 set_elem.size = sizeof(elem->key);
914 set_elem.element_type = 0;
915 GNUNET_SETI_add_element (s->intersection_set,
916 &set_elem,
917 NULL, NULL);
918 s->used_element_count++;
919 }
920 GNUNET_SERVICE_client_continue (s->client);
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922 "Received client request, opening port %s!\n",
923 GNUNET_h2s (&msg->session_key));
924 s->port = GNUNET_CADET_open_port (my_cadet,
925 &msg->session_key,
926 &cb_channel_incoming,
927 s,
928 NULL,
929 &cb_channel_destruction,
930 cadet_handlers);
931 if (NULL == s->port)
932 {
933 GNUNET_break (0);
934 GNUNET_SERVICE_client_drop (s->client);
935 return;
936 }
937}
938
939
940/**
941 * Task run during shutdown.
942 *
943 * @param cls unused
944 */
945static void
946shutdown_task (void *cls)
947{
948 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
949 "Shutting down, initiating cleanup.\n");
950 // FIXME: we have to cut our connections to CADET first!
951 if (NULL != my_cadet)
952 {
953 GNUNET_CADET_disconnect (my_cadet);
954 my_cadet = NULL;
955 }
956 if (NULL != edc)
957 {
958 GNUNET_CRYPTO_ecc_dlog_release (edc);
959 edc = NULL;
960 }
961}
962
963
964/**
965 * A client connected.
966 *
967 * Setup the associated data structure.
968 *
969 * @param cls closure, NULL
970 * @param client identification of the client
971 * @param mq message queue to communicate with @a client
972 * @return our `struct BobServiceSession`
973 */
974static void *
975client_connect_cb (void *cls,
976 struct GNUNET_SERVICE_Client *client,
977 struct GNUNET_MQ_Handle *mq)
978{
979 struct BobServiceSession *s;
980
981 s = GNUNET_new (struct BobServiceSession);
982 s->client = client;
983 s->client_mq = mq;
984 return s;
985}
986
987
988/**
989 * A client disconnected.
990 *
991 * Remove the associated session(s), release data structures
992 * and cancel pending outgoing transmissions to the client.
993 *
994 * @param cls closure, NULL
995 * @param client identification of the client
996 * @param app_cls our `struct BobServiceSession`
997 */
998static void
999client_disconnect_cb (void *cls,
1000 struct GNUNET_SERVICE_Client *client,
1001 void *app_cls)
1002{
1003 struct BobServiceSession *s = app_cls;
1004
1005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1006 "Client disconnected from us.\n");
1007 s->client = NULL;
1008 destroy_service_session (s);
1009}
1010
1011
1012/**
1013 * Initialization of the program and message handlers
1014 *
1015 * @param cls closure
1016 * @param c configuration to use
1017 * @param service the initialized service
1018 */
1019static void
1020run (void *cls,
1021 const struct GNUNET_CONFIGURATION_Handle *c,
1022 struct GNUNET_SERVICE_Handle *service)
1023{
1024 cfg = c;
1025 /* We don't really do DLOG, so we can setup with very minimal resources */
1026 edc = GNUNET_CRYPTO_ecc_dlog_prepare (4 /* max value */,
1027 2 /* RAM */);
1028 my_cadet = GNUNET_CADET_connect (cfg);
1029 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1030 NULL);
1031 if (NULL == my_cadet)
1032 {
1033 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1034 _ ("Connect to CADET failed\n"));
1035 GNUNET_SCHEDULER_shutdown ();
1036 return;
1037 }
1038}
1039
1040
1041/**
1042 * Define "main" method using service macro.
1043 */
1044GNUNET_SERVICE_MAIN
1045 ("scalarproduct-bob",
1046 GNUNET_SERVICE_OPTION_NONE,
1047 &run,
1048 &client_connect_cb,
1049 &client_disconnect_cb,
1050 NULL,
1051 GNUNET_MQ_hd_var_size (bob_client_message,
1052 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
1053 struct BobComputationMessage,
1054 NULL),
1055 GNUNET_MQ_hd_var_size (bob_client_message_multipart,
1056 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB,
1057 struct ComputationBobCryptodataMultipartMessage,
1058 NULL),
1059 GNUNET_MQ_handler_end ());
1060
1061
1062/* end of gnunet-service-scalarproduct-ecc_bob.c */