diff options
Diffstat (limited to 'src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c')
-rw-r--r-- | src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c | 1149 |
1 files changed, 0 insertions, 1149 deletions
diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c deleted file mode 100644 index dc43b5a54..000000000 --- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c +++ /dev/null | |||
@@ -1,1149 +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_alice.c | ||
22 | * @brief scalarproduct service implementation | ||
23 | * @author Christian M. Fuchs | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include <limits.h> | ||
28 | #include <gcrypt.h> | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_core_service.h" | ||
31 | #include "gnunet_cadet_service.h" | ||
32 | #include "gnunet_applications.h" | ||
33 | #include "gnunet_protocols.h" | ||
34 | #include "gnunet_scalarproduct_service.h" | ||
35 | #include "gnunet_seti_service.h" | ||
36 | #include "scalarproduct.h" | ||
37 | #include "gnunet-service-scalarproduct-ecc.h" | ||
38 | |||
39 | #define LOG(kind, ...) \ | ||
40 | GNUNET_log_from (kind, "scalarproduct-alice", __VA_ARGS__) | ||
41 | |||
42 | /** | ||
43 | * Maximum allowed result value for the scalarproduct computation. | ||
44 | * DLOG will fail if the result is bigger. At 1 million, the | ||
45 | * precomputation takes about 2s on a fast machine. | ||
46 | */ | ||
47 | #define MAX_RESULT (1024 * 1024) | ||
48 | |||
49 | /** | ||
50 | * How many values should DLOG store in memory (determines baseline | ||
51 | * RAM consumption, roughly 100 bytes times the value given here). | ||
52 | * Should be about SQRT (MAX_RESULT), larger values will make the | ||
53 | * online computation faster. | ||
54 | */ | ||
55 | #define MAX_RAM (1024) | ||
56 | |||
57 | /** | ||
58 | * An encrypted element key-value pair. | ||
59 | */ | ||
60 | struct MpiElement | ||
61 | { | ||
62 | /** | ||
63 | * Key used to identify matching pairs of values to multiply. | ||
64 | * Points into an existing data structure, to avoid copying | ||
65 | * and doubling memory use. | ||
66 | */ | ||
67 | const struct GNUNET_HashCode *key; | ||
68 | |||
69 | /** | ||
70 | * a_i value, not disclosed to Bob. | ||
71 | */ | ||
72 | int64_t value; | ||
73 | }; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * A scalarproduct session which tracks | ||
78 | * a request form the client to our final response. | ||
79 | */ | ||
80 | struct AliceServiceSession | ||
81 | { | ||
82 | /** | ||
83 | * (hopefully) unique transaction ID | ||
84 | */ | ||
85 | struct GNUNET_HashCode session_id; | ||
86 | |||
87 | /** | ||
88 | * Alice or Bob's peerID | ||
89 | */ | ||
90 | struct GNUNET_PeerIdentity peer; | ||
91 | |||
92 | /** | ||
93 | * The client this request is related to. | ||
94 | */ | ||
95 | struct GNUNET_SERVICE_Client *client; | ||
96 | |||
97 | /** | ||
98 | * The message queue for the client. | ||
99 | */ | ||
100 | struct GNUNET_MQ_Handle *client_mq; | ||
101 | |||
102 | /** | ||
103 | * The message queue for CADET. | ||
104 | */ | ||
105 | struct GNUNET_MQ_Handle *cadet_mq; | ||
106 | |||
107 | /** | ||
108 | * all non-0-value'd elements transmitted to us. | ||
109 | * Values are of type `struct GNUNET_SCALARPRODUCT_Element *` | ||
110 | */ | ||
111 | struct GNUNET_CONTAINER_MultiHashMap *intersected_elements; | ||
112 | |||
113 | /** | ||
114 | * Set of elements for which will conduction an intersection. | ||
115 | * the resulting elements are then used for computing the scalar product. | ||
116 | */ | ||
117 | struct GNUNET_SETI_Handle *intersection_set; | ||
118 | |||
119 | /** | ||
120 | * Set of elements for which will conduction an intersection. | ||
121 | * the resulting elements are then used for computing the scalar product. | ||
122 | */ | ||
123 | struct GNUNET_SETI_OperationHandle *intersection_op; | ||
124 | |||
125 | /** | ||
126 | * Handle to Alice's Intersection operation listening for Bob | ||
127 | */ | ||
128 | struct GNUNET_SETI_ListenHandle *intersection_listen; | ||
129 | |||
130 | /** | ||
131 | * channel-handle associated with our cadet handle | ||
132 | */ | ||
133 | struct GNUNET_CADET_Channel *channel; | ||
134 | |||
135 | /** | ||
136 | * a(Alice), sorted array by key of length @e used_element_count. | ||
137 | */ | ||
138 | struct MpiElement *sorted_elements; | ||
139 | |||
140 | /** | ||
141 | * The computed scalar product. INT_MAX if the computation failed. | ||
142 | */ | ||
143 | int product; | ||
144 | |||
145 | /** | ||
146 | * How many elements we were supplied with from the client (total | ||
147 | * count before intersection). | ||
148 | */ | ||
149 | uint32_t total; | ||
150 | |||
151 | /** | ||
152 | * How many elements actually are used for the scalar product. | ||
153 | * Size of the arrays in @e r and @e r_prime. Sometimes also | ||
154 | * reset to 0 and used as a counter! | ||
155 | */ | ||
156 | uint32_t used_element_count; | ||
157 | |||
158 | /** | ||
159 | * Already transferred elements from client to us. | ||
160 | * Less or equal than @e total. | ||
161 | */ | ||
162 | uint32_t client_received_element_count; | ||
163 | |||
164 | /** | ||
165 | * State of this session. In | ||
166 | * #GNUNET_SCALARPRODUCT_STATUS_ACTIVE while operation is | ||
167 | * ongoing, afterwards in #GNUNET_SCALARPRODUCT_STATUS_SUCCESS or | ||
168 | * #GNUNET_SCALARPRODUCT_STATUS_FAILURE. | ||
169 | */ | ||
170 | enum GNUNET_SCALARPRODUCT_ResponseStatus status; | ||
171 | |||
172 | /** | ||
173 | * Flag to prevent recursive calls to #destroy_service_session() from | ||
174 | * doing harm. | ||
175 | */ | ||
176 | int in_destroy; | ||
177 | }; | ||
178 | |||
179 | |||
180 | /** | ||
181 | * GNUnet configuration handle | ||
182 | */ | ||
183 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
184 | |||
185 | /** | ||
186 | * Context for DLOG operations on a curve. | ||
187 | */ | ||
188 | static struct GNUNET_CRYPTO_EccDlogContext *edc; | ||
189 | |||
190 | /** | ||
191 | * Alice's private key ('a'). | ||
192 | */ | ||
193 | static struct GNUNET_CRYPTO_EccScalar my_privkey; | ||
194 | |||
195 | /** | ||
196 | * Inverse of Alice's private key ('a_inv'). | ||
197 | */ | ||
198 | static struct GNUNET_CRYPTO_EccScalar my_privkey_inv; | ||
199 | |||
200 | /** | ||
201 | * Handle to the CADET service. | ||
202 | */ | ||
203 | static struct GNUNET_CADET_Handle *my_cadet; | ||
204 | |||
205 | |||
206 | /** | ||
207 | * Iterator called to free elements. | ||
208 | * | ||
209 | * @param cls the `struct AliceServiceSession *` (unused) | ||
210 | * @param key the key (unused) | ||
211 | * @param value value to free | ||
212 | * @return #GNUNET_OK (continue to iterate) | ||
213 | */ | ||
214 | static int | ||
215 | free_element_cb (void *cls, | ||
216 | const struct GNUNET_HashCode *key, | ||
217 | void *value) | ||
218 | { | ||
219 | struct GNUNET_SCALARPRODUCT_Element *e = value; | ||
220 | |||
221 | GNUNET_free (e); | ||
222 | return GNUNET_OK; | ||
223 | } | ||
224 | |||
225 | |||
226 | /** | ||
227 | * Destroy session state, we are done with it. | ||
228 | * | ||
229 | * @param s the session to free elements from | ||
230 | */ | ||
231 | static void | ||
232 | destroy_service_session (struct AliceServiceSession *s) | ||
233 | { | ||
234 | if (GNUNET_YES == s->in_destroy) | ||
235 | return; | ||
236 | s->in_destroy = GNUNET_YES; | ||
237 | if (NULL != s->client) | ||
238 | { | ||
239 | struct GNUNET_SERVICE_Client *c = s->client; | ||
240 | |||
241 | s->client = NULL; | ||
242 | GNUNET_SERVICE_client_drop (c); | ||
243 | } | ||
244 | if (NULL != s->channel) | ||
245 | { | ||
246 | GNUNET_CADET_channel_destroy (s->channel); | ||
247 | s->channel = NULL; | ||
248 | } | ||
249 | if (NULL != s->intersected_elements) | ||
250 | { | ||
251 | GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements, | ||
252 | &free_element_cb, | ||
253 | s); | ||
254 | GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements); | ||
255 | s->intersected_elements = NULL; | ||
256 | } | ||
257 | if (NULL != s->intersection_listen) | ||
258 | { | ||
259 | GNUNET_SETI_listen_cancel (s->intersection_listen); | ||
260 | s->intersection_listen = NULL; | ||
261 | } | ||
262 | if (NULL != s->intersection_op) | ||
263 | { | ||
264 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
265 | "Set intersection, op still ongoing!\n"); | ||
266 | GNUNET_SETI_operation_cancel (s->intersection_op); | ||
267 | s->intersection_op = NULL; | ||
268 | } | ||
269 | if (NULL != s->intersection_set) | ||
270 | { | ||
271 | GNUNET_SETI_destroy (s->intersection_set); | ||
272 | s->intersection_set = NULL; | ||
273 | } | ||
274 | if (NULL != s->sorted_elements) | ||
275 | { | ||
276 | GNUNET_free (s->sorted_elements); | ||
277 | s->sorted_elements = NULL; | ||
278 | } | ||
279 | GNUNET_free (s); | ||
280 | } | ||
281 | |||
282 | |||
283 | /** | ||
284 | * Notify the client that the session has failed. A message gets sent | ||
285 | * to Alice's client if we encountered any error. | ||
286 | * | ||
287 | * @param session the associated client session to fail or succeed | ||
288 | */ | ||
289 | static void | ||
290 | prepare_client_end_notification (struct AliceServiceSession *session) | ||
291 | { | ||
292 | struct ClientResponseMessage *msg; | ||
293 | struct GNUNET_MQ_Envelope *e; | ||
294 | |||
295 | if (NULL == session->client_mq) | ||
296 | return; /* no client left to be notified */ | ||
297 | GNUNET_log ( | ||
298 | GNUNET_ERROR_TYPE_DEBUG, | ||
299 | "Sending session-end notification with status %d to client for session %s\n", | ||
300 | session->status, | ||
301 | GNUNET_h2s (&session->session_id)); | ||
302 | e = GNUNET_MQ_msg (msg, | ||
303 | GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT); | ||
304 | msg->product_length = htonl (0); | ||
305 | msg->status = htonl (session->status); | ||
306 | GNUNET_MQ_send (session->client_mq, | ||
307 | e); | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * Prepare the final (positive) response we will send to Alice's | ||
313 | * client. | ||
314 | * | ||
315 | * @param s the session associated with our client. | ||
316 | */ | ||
317 | static void | ||
318 | transmit_client_response (struct AliceServiceSession *s) | ||
319 | { | ||
320 | struct ClientResponseMessage *msg; | ||
321 | struct GNUNET_MQ_Envelope *e; | ||
322 | unsigned char *product_exported = NULL; | ||
323 | size_t product_length = 0; | ||
324 | int32_t range; | ||
325 | gcry_error_t rc; | ||
326 | gcry_mpi_t value; | ||
327 | |||
328 | if (INT_MAX == s->product) | ||
329 | { | ||
330 | GNUNET_break (0); | ||
331 | prepare_client_end_notification (s); | ||
332 | return; | ||
333 | } | ||
334 | value = gcry_mpi_new (32); | ||
335 | if (0 > s->product) | ||
336 | { | ||
337 | range = -1; | ||
338 | gcry_mpi_set_ui (value, | ||
339 | -s->product); | ||
340 | } | ||
341 | else if (0 < s->product) | ||
342 | { | ||
343 | range = 1; | ||
344 | gcry_mpi_set_ui (value, | ||
345 | s->product); | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | /* result is exactly zero */ | ||
350 | range = 0; | ||
351 | } | ||
352 | if ( (0 != range) && | ||
353 | (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD, | ||
354 | &product_exported, | ||
355 | &product_length, | ||
356 | value)))) | ||
357 | { | ||
358 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, | ||
359 | "gcry_mpi_scan", | ||
360 | rc); | ||
361 | prepare_client_end_notification (s); | ||
362 | return; | ||
363 | } | ||
364 | gcry_mpi_release (value); | ||
365 | e = GNUNET_MQ_msg_extra (msg, | ||
366 | product_length, | ||
367 | GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT); | ||
368 | msg->status = htonl (GNUNET_SCALARPRODUCT_STATUS_SUCCESS); | ||
369 | msg->range = htonl (range); | ||
370 | msg->product_length = htonl (product_length); | ||
371 | if (NULL != product_exported) | ||
372 | { | ||
373 | GNUNET_memcpy (&msg[1], | ||
374 | product_exported, | ||
375 | product_length); | ||
376 | GNUNET_free (product_exported); | ||
377 | } | ||
378 | GNUNET_MQ_send (s->client_mq, | ||
379 | e); | ||
380 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
381 | "Sent result to client, session %s has ended!\n", | ||
382 | GNUNET_h2s (&s->session_id)); | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Function called whenever a channel is destroyed. Should clean up | ||
388 | * any associated state. | ||
389 | * | ||
390 | * It must NOT call #GNUNET_CADET_channel_destroy() on the channel. | ||
391 | * | ||
392 | * @param cls the `struct AliceServiceSession` | ||
393 | * @param channel connection to the other end (henceforth invalid) | ||
394 | */ | ||
395 | static void | ||
396 | cb_channel_destruction (void *cls, | ||
397 | const struct GNUNET_CADET_Channel *channel) | ||
398 | { | ||
399 | struct AliceServiceSession *s = cls; | ||
400 | |||
401 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
402 | "Peer disconnected, terminating session %s with peer %s\n", | ||
403 | GNUNET_h2s (&s->session_id), | ||
404 | GNUNET_i2s (&s->peer)); | ||
405 | s->channel = NULL; | ||
406 | if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status) | ||
407 | { | ||
408 | /* We didn't get an answer yet, fail with error */ | ||
409 | s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; | ||
410 | prepare_client_end_notification (s); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | |||
415 | /** | ||
416 | * Handle a response we got from another service we wanted to | ||
417 | * calculate a scalarproduct with. | ||
418 | * | ||
419 | * @param cls the `struct AliceServiceSession *` | ||
420 | * @param msg the actual message | ||
421 | */ | ||
422 | static void | ||
423 | handle_bobs_cryptodata_message (void *cls, | ||
424 | const struct EccBobCryptodataMessage *msg) | ||
425 | { | ||
426 | struct AliceServiceSession *s = cls; | ||
427 | uint32_t contained; | ||
428 | |||
429 | contained = ntohl (msg->contained_element_count); | ||
430 | if (2 != contained) | ||
431 | { | ||
432 | GNUNET_break_op (0); | ||
433 | destroy_service_session (s); | ||
434 | return; | ||
435 | } | ||
436 | if (NULL == s->sorted_elements) | ||
437 | { | ||
438 | /* we're not ready yet, how can Bob be? */ | ||
439 | GNUNET_break_op (0); | ||
440 | destroy_service_session (s); | ||
441 | return; | ||
442 | } | ||
443 | if (s->total != s->client_received_element_count) | ||
444 | { | ||
445 | /* we're not ready yet, how can Bob be? */ | ||
446 | GNUNET_break_op (0); | ||
447 | destroy_service_session (s); | ||
448 | return; | ||
449 | } | ||
450 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
451 | "Received %u crypto values from Bob\n", | ||
452 | (unsigned int) contained); | ||
453 | GNUNET_CADET_receive_done (s->channel); | ||
454 | { | ||
455 | struct GNUNET_CRYPTO_EccPoint g_i_b_i_a_inv; | ||
456 | struct GNUNET_CRYPTO_EccPoint g_ai_bi; | ||
457 | |||
458 | GNUNET_assert ( | ||
459 | GNUNET_OK == | ||
460 | GNUNET_CRYPTO_ecc_pmul_mpi (&msg->prod_g_i_b_i, | ||
461 | &my_privkey_inv, | ||
462 | &g_i_b_i_a_inv)); | ||
463 | GNUNET_assert ( | ||
464 | GNUNET_OK == | ||
465 | GNUNET_CRYPTO_ecc_add (&g_i_b_i_a_inv, | ||
466 | &msg->prod_h_i_b_i, | ||
467 | &g_ai_bi)); | ||
468 | s->product = GNUNET_CRYPTO_ecc_dlog (edc, | ||
469 | &g_ai_bi); | ||
470 | if (INT_MAX == s->product) | ||
471 | { | ||
472 | /* result too big */ | ||
473 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
474 | "Scalar product result out of range\n"); | ||
475 | } | ||
476 | } | ||
477 | transmit_client_response (s); | ||
478 | } | ||
479 | |||
480 | |||
481 | /** | ||
482 | * Iterator to copy over messages from the hash map | ||
483 | * into an array for sorting. | ||
484 | * | ||
485 | * @param cls the `struct AliceServiceSession *` | ||
486 | * @param key the key (unused) | ||
487 | * @param value the `struct GNUNET_SCALARPRODUCT_Element *` | ||
488 | */ | ||
489 | static int | ||
490 | copy_element_cb (void *cls, | ||
491 | const struct GNUNET_HashCode *key, | ||
492 | void *value) | ||
493 | { | ||
494 | struct AliceServiceSession *s = cls; | ||
495 | struct GNUNET_SCALARPRODUCT_Element *e = value; | ||
496 | |||
497 | s->sorted_elements[s->used_element_count].value = (int64_t) GNUNET_ntohll ( | ||
498 | e->value); | ||
499 | s->sorted_elements[s->used_element_count].key = &e->key; | ||
500 | s->used_element_count++; | ||
501 | return GNUNET_OK; | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Compare two `struct MpiValue`s by key for sorting. | ||
507 | * | ||
508 | * @param a pointer to first `struct MpiValue *` | ||
509 | * @param b pointer to first `struct MpiValue *` | ||
510 | * @return -1 for a < b, 0 for a=b, 1 for a > b. | ||
511 | */ | ||
512 | static int | ||
513 | element_cmp (const void *a, | ||
514 | const void *b) | ||
515 | { | ||
516 | const struct MpiElement *ma = a; | ||
517 | const struct MpiElement *mb = b; | ||
518 | |||
519 | return GNUNET_CRYPTO_hash_cmp (ma->key, | ||
520 | mb->key); | ||
521 | } | ||
522 | |||
523 | |||
524 | /** | ||
525 | * Maximum number of elements we can put into a single cryptodata | ||
526 | * message | ||
527 | */ | ||
528 | #define ELEMENT_CAPACITY \ | ||
529 | ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 \ | ||
530 | - sizeof(struct EccAliceCryptodataMessage)) \ | ||
531 | / sizeof(struct GNUNET_CRYPTO_EccPoint)) | ||
532 | |||
533 | |||
534 | /** | ||
535 | * Send the cryptographic data from Alice to Bob. | ||
536 | * Does nothing if we already transferred all elements. | ||
537 | * | ||
538 | * @param s the associated service session | ||
539 | */ | ||
540 | static void | ||
541 | send_alices_cryptodata_message (struct AliceServiceSession *s) | ||
542 | { | ||
543 | struct EccAliceCryptodataMessage *msg; | ||
544 | struct GNUNET_MQ_Envelope *e; | ||
545 | struct GNUNET_CRYPTO_EccPoint *payload; | ||
546 | struct GNUNET_CRYPTO_EccScalar r_ia; | ||
547 | struct GNUNET_CRYPTO_EccScalar r_ia_ai; | ||
548 | unsigned int off; | ||
549 | unsigned int todo_count; | ||
550 | |||
551 | s->sorted_elements = GNUNET_new_array (GNUNET_CONTAINER_multihashmap_size ( | ||
552 | s->intersected_elements), | ||
553 | struct MpiElement); | ||
554 | s->used_element_count = 0; | ||
555 | GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements, | ||
556 | ©_element_cb, | ||
557 | s); | ||
558 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
559 | "Finished intersection, %d items remain\n", | ||
560 | s->used_element_count); | ||
561 | qsort (s->sorted_elements, | ||
562 | s->used_element_count, | ||
563 | sizeof(struct MpiElement), | ||
564 | &element_cmp); | ||
565 | off = 0; | ||
566 | while (off < s->used_element_count) | ||
567 | { | ||
568 | todo_count = s->used_element_count - off; | ||
569 | if (todo_count > ELEMENT_CAPACITY) | ||
570 | todo_count = ELEMENT_CAPACITY; | ||
571 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
572 | "Sending %u/%u crypto values to Bob\n", | ||
573 | (unsigned int) todo_count, | ||
574 | (unsigned int) s->used_element_count); | ||
575 | |||
576 | e = | ||
577 | GNUNET_MQ_msg_extra (msg, | ||
578 | todo_count * 2 | ||
579 | * sizeof(struct GNUNET_CRYPTO_EccPoint), | ||
580 | GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_ALICE_CRYPTODATA); | ||
581 | msg->contained_element_count = htonl (todo_count); | ||
582 | payload = (struct GNUNET_CRYPTO_EccPoint *) &msg[1]; | ||
583 | for (unsigned int i = off; i < off + todo_count; i++) | ||
584 | { | ||
585 | struct GNUNET_CRYPTO_EccScalar r_i; | ||
586 | struct GNUNET_CRYPTO_EccPoint g_i; | ||
587 | struct GNUNET_CRYPTO_EccPoint h_i; | ||
588 | |||
589 | /* r_i = random() mod n */ | ||
590 | GNUNET_CRYPTO_ecc_random_mod_n (&r_i); | ||
591 | /* g_i = g^{r_i} */ | ||
592 | GNUNET_assert (GNUNET_OK == | ||
593 | GNUNET_CRYPTO_ecc_dexp_mpi (&r_i, | ||
594 | &g_i)); | ||
595 | /* r_ia = r_i * a */ | ||
596 | crypto_core_ed25519_scalar_mul (r_ia.v, | ||
597 | r_i.v, | ||
598 | my_privkey.v); | ||
599 | /* r_ia_ai = r_ia + a_i */ | ||
600 | { | ||
601 | int64_t val = s->sorted_elements[i].value; | ||
602 | struct GNUNET_CRYPTO_EccScalar vali; | ||
603 | |||
604 | GNUNET_assert (INT64_MIN != val); | ||
605 | GNUNET_CRYPTO_ecc_scalar_from_int (val > 0 ? val : -val, | ||
606 | &vali); | ||
607 | if (val > 0) | ||
608 | crypto_core_ed25519_scalar_add (r_ia_ai.v, | ||
609 | r_ia.v, | ||
610 | vali.v); | ||
611 | else | ||
612 | crypto_core_ed25519_scalar_sub (r_ia_ai.v, | ||
613 | r_ia.v, | ||
614 | vali.v); | ||
615 | } | ||
616 | /* h_i = g^{r_ia_ai} */ | ||
617 | GNUNET_assert (GNUNET_OK == | ||
618 | GNUNET_CRYPTO_ecc_dexp_mpi (&r_ia_ai, | ||
619 | &h_i)); | ||
620 | memcpy (&payload[(i - off) * 2], | ||
621 | &g_i, | ||
622 | sizeof (g_i)); | ||
623 | memcpy (&payload[(i - off) * 2 + 1], | ||
624 | &h_i, | ||
625 | sizeof (h_i)); | ||
626 | } | ||
627 | off += todo_count; | ||
628 | GNUNET_MQ_send (s->cadet_mq, | ||
629 | e); | ||
630 | } | ||
631 | } | ||
632 | |||
633 | |||
634 | /** | ||
635 | * Callback for set operation results. Called for each element | ||
636 | * that should be removed from the result set, and then once | ||
637 | * to indicate that the set intersection operation is done. | ||
638 | * | ||
639 | * @param cls closure with the `struct AliceServiceSession` | ||
640 | * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK | ||
641 | * @param current_size current set size | ||
642 | * @param status what has happened with the set intersection? | ||
643 | */ | ||
644 | static void | ||
645 | cb_intersection_element_removed (void *cls, | ||
646 | const struct GNUNET_SETI_Element *element, | ||
647 | uint64_t current_size, | ||
648 | enum GNUNET_SETI_Status status) | ||
649 | { | ||
650 | struct AliceServiceSession *s = cls; | ||
651 | struct GNUNET_SCALARPRODUCT_Element *se; | ||
652 | |||
653 | switch (status) | ||
654 | { | ||
655 | case GNUNET_SETI_STATUS_DEL_LOCAL: | ||
656 | /* this element has been removed from the set */ | ||
657 | se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements, | ||
658 | element->data); | ||
659 | GNUNET_assert (NULL != se); | ||
660 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
661 | "Intersection removed element with key %s and value %lld\n", | ||
662 | GNUNET_h2s (&se->key), | ||
663 | (long long) GNUNET_ntohll (se->value)); | ||
664 | GNUNET_assert ( | ||
665 | GNUNET_YES == | ||
666 | GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements, | ||
667 | element->data, | ||
668 | se)); | ||
669 | GNUNET_free (se); | ||
670 | return; | ||
671 | case GNUNET_SETI_STATUS_DONE: | ||
672 | s->intersection_op = NULL; | ||
673 | if (NULL != s->intersection_set) | ||
674 | { | ||
675 | GNUNET_SETI_destroy (s->intersection_set); | ||
676 | s->intersection_set = NULL; | ||
677 | } | ||
678 | send_alices_cryptodata_message (s); | ||
679 | return; | ||
680 | case GNUNET_SETI_STATUS_FAILURE: | ||
681 | /* unhandled status code */ | ||
682 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n"); | ||
683 | if (NULL != s->intersection_listen) | ||
684 | { | ||
685 | GNUNET_SETI_listen_cancel (s->intersection_listen); | ||
686 | s->intersection_listen = NULL; | ||
687 | } | ||
688 | s->intersection_op = NULL; | ||
689 | if (NULL != s->intersection_set) | ||
690 | { | ||
691 | GNUNET_SETI_destroy (s->intersection_set); | ||
692 | s->intersection_set = NULL; | ||
693 | } | ||
694 | s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; | ||
695 | prepare_client_end_notification (s); | ||
696 | return; | ||
697 | |||
698 | default: | ||
699 | GNUNET_break (0); | ||
700 | return; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | |||
705 | /** | ||
706 | * Called when another peer wants to do a set operation with the | ||
707 | * local peer. If a listen error occurs, the @a request is NULL. | ||
708 | * | ||
709 | * @param cls closure with the `struct AliceServiceSession *` | ||
710 | * @param other_peer the other peer | ||
711 | * @param context_msg message with application specific information from | ||
712 | * the other peer | ||
713 | * @param request request from the other peer (never NULL), use GNUNET_SETI_accept() | ||
714 | * to accept it, otherwise the request will be refused | ||
715 | * Note that we can't just return value from the listen callback, | ||
716 | * as it is also necessary to specify the set we want to do the | ||
717 | * operation with, which sometimes can be derived from the context | ||
718 | * message. It's necessary to specify the timeout. | ||
719 | */ | ||
720 | static void | ||
721 | cb_intersection_request_alice (void *cls, | ||
722 | const struct GNUNET_PeerIdentity *other_peer, | ||
723 | const struct GNUNET_MessageHeader *context_msg, | ||
724 | struct GNUNET_SETI_Request *request) | ||
725 | { | ||
726 | struct AliceServiceSession *s = cls; | ||
727 | |||
728 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
729 | "Received intersection request from %s!\n", | ||
730 | GNUNET_i2s (other_peer)); | ||
731 | if (0 != GNUNET_memcmp (other_peer, | ||
732 | &s->peer)) | ||
733 | { | ||
734 | GNUNET_break_op (0); | ||
735 | return; | ||
736 | } | ||
737 | s->intersection_op | ||
738 | = GNUNET_SETI_accept (request, | ||
739 | (struct GNUNET_SETI_Option[]){ { 0 } }, | ||
740 | &cb_intersection_element_removed, | ||
741 | s); | ||
742 | if (NULL == s->intersection_op) | ||
743 | { | ||
744 | GNUNET_break (0); | ||
745 | s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; | ||
746 | prepare_client_end_notification (s); | ||
747 | return; | ||
748 | } | ||
749 | if (GNUNET_OK != | ||
750 | GNUNET_SETI_commit (s->intersection_op, | ||
751 | s->intersection_set)) | ||
752 | { | ||
753 | GNUNET_break (0); | ||
754 | s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; | ||
755 | prepare_client_end_notification (s); | ||
756 | return; | ||
757 | } | ||
758 | } | ||
759 | |||
760 | |||
761 | /** | ||
762 | * Our client has finished sending us its multipart message. | ||
763 | * | ||
764 | * @param session the service session context | ||
765 | */ | ||
766 | static void | ||
767 | client_request_complete_alice (struct AliceServiceSession *s) | ||
768 | { | ||
769 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = { | ||
770 | GNUNET_MQ_hd_fixed_size (bobs_cryptodata_message, | ||
771 | GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA, | ||
772 | struct EccBobCryptodataMessage, | ||
773 | s), | ||
774 | GNUNET_MQ_handler_end () | ||
775 | }; | ||
776 | struct EccServiceRequestMessage *msg; | ||
777 | struct GNUNET_MQ_Envelope *e; | ||
778 | struct GNUNET_HashCode set_sid; | ||
779 | |||
780 | GNUNET_CRYPTO_hash (&s->session_id, | ||
781 | sizeof(struct GNUNET_HashCode), | ||
782 | &set_sid); | ||
783 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
784 | "Creating new channel for session with key %s.\n", | ||
785 | GNUNET_h2s (&s->session_id)); | ||
786 | s->channel = GNUNET_CADET_channel_create (my_cadet, | ||
787 | s, | ||
788 | &s->peer, | ||
789 | &s->session_id, | ||
790 | NULL, | ||
791 | &cb_channel_destruction, | ||
792 | cadet_handlers); | ||
793 | if (NULL == s->channel) | ||
794 | { | ||
795 | s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; | ||
796 | prepare_client_end_notification (s); | ||
797 | return; | ||
798 | } | ||
799 | s->cadet_mq = GNUNET_CADET_get_mq (s->channel); | ||
800 | s->intersection_listen = GNUNET_SETI_listen (cfg, | ||
801 | &set_sid, | ||
802 | &cb_intersection_request_alice, | ||
803 | s); | ||
804 | if (NULL == s->intersection_listen) | ||
805 | { | ||
806 | s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; | ||
807 | GNUNET_CADET_channel_destroy (s->channel); | ||
808 | s->channel = NULL; | ||
809 | prepare_client_end_notification (s); | ||
810 | return; | ||
811 | } | ||
812 | |||
813 | e = | ||
814 | GNUNET_MQ_msg (msg, | ||
815 | GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_SESSION_INITIALIZATION); | ||
816 | GNUNET_MQ_env_set_options (e, GNUNET_MQ_PRIO_CRITICAL_CONTROL); | ||
817 | msg->session_id = s->session_id; | ||
818 | GNUNET_MQ_send (s->cadet_mq, e); | ||
819 | } | ||
820 | |||
821 | |||
822 | /** | ||
823 | * We're receiving additional set data. Check if | ||
824 | * @a msg is well-formed. | ||
825 | * | ||
826 | * @param cls client identification of the client | ||
827 | * @param msg the actual message | ||
828 | * @return #GNUNET_OK if @a msg is well-formed | ||
829 | */ | ||
830 | static int | ||
831 | check_alice_client_message_multipart ( | ||
832 | void *cls, | ||
833 | const struct ComputationBobCryptodataMultipartMessage *msg) | ||
834 | { | ||
835 | struct AliceServiceSession *s = cls; | ||
836 | uint32_t contained_count; | ||
837 | uint16_t msize; | ||
838 | |||
839 | msize = ntohs (msg->header.size); | ||
840 | contained_count = ntohl (msg->element_count_contained); | ||
841 | if ((msize != | ||
842 | (sizeof(struct ComputationBobCryptodataMultipartMessage) | ||
843 | + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))) || | ||
844 | (0 == contained_count) || | ||
845 | (s->total == s->client_received_element_count) || | ||
846 | (s->total < s->client_received_element_count + contained_count)) | ||
847 | { | ||
848 | GNUNET_break_op (0); | ||
849 | return GNUNET_SYSERR; | ||
850 | } | ||
851 | return GNUNET_OK; | ||
852 | } | ||
853 | |||
854 | |||
855 | /** | ||
856 | * We're receiving additional set data. Add it to our | ||
857 | * set and if we are done, initiate the transaction. | ||
858 | * | ||
859 | * @param cls client identification of the client | ||
860 | * @param msg the actual message | ||
861 | */ | ||
862 | static void | ||
863 | handle_alice_client_message_multipart ( | ||
864 | void *cls, | ||
865 | const struct ComputationBobCryptodataMultipartMessage *msg) | ||
866 | { | ||
867 | struct AliceServiceSession *s = cls; | ||
868 | uint32_t contained_count; | ||
869 | const struct GNUNET_SCALARPRODUCT_Element *elements; | ||
870 | struct GNUNET_SETI_Element set_elem; | ||
871 | struct GNUNET_SCALARPRODUCT_Element *elem; | ||
872 | |||
873 | contained_count = ntohl (msg->element_count_contained); | ||
874 | s->client_received_element_count += contained_count; | ||
875 | elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1]; | ||
876 | for (uint32_t i = 0; i < contained_count; i++) | ||
877 | { | ||
878 | elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element); | ||
879 | GNUNET_memcpy (elem, | ||
880 | &elements[i], | ||
881 | sizeof(struct GNUNET_SCALARPRODUCT_Element)); | ||
882 | if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put ( | ||
883 | s->intersected_elements, | ||
884 | &elem->key, | ||
885 | elem, | ||
886 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
887 | { | ||
888 | GNUNET_break (0); | ||
889 | GNUNET_free (elem); | ||
890 | continue; | ||
891 | } | ||
892 | set_elem.data = &elem->key; | ||
893 | set_elem.size = sizeof(elem->key); | ||
894 | set_elem.element_type = 0; | ||
895 | GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL); | ||
896 | s->used_element_count++; | ||
897 | } | ||
898 | GNUNET_SERVICE_client_continue (s->client); | ||
899 | if (s->total != s->client_received_element_count) | ||
900 | { | ||
901 | /* more to come */ | ||
902 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
903 | "Received client multipart data, waiting for more!\n"); | ||
904 | return; | ||
905 | } | ||
906 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Launching computation\n"); | ||
907 | client_request_complete_alice (s); | ||
908 | } | ||
909 | |||
910 | |||
911 | /** | ||
912 | * Handler for Alice's client request message. | ||
913 | * Check that @a msg is well-formed. | ||
914 | * | ||
915 | * @param cls identification of the client | ||
916 | * @param msg the actual message | ||
917 | * @return #GNUNET_OK if @a msg is well-formed | ||
918 | */ | ||
919 | static int | ||
920 | check_alice_client_message (void *cls, | ||
921 | const struct AliceComputationMessage *msg) | ||
922 | { | ||
923 | struct AliceServiceSession *s = cls; | ||
924 | uint16_t msize; | ||
925 | uint32_t total_count; | ||
926 | uint32_t contained_count; | ||
927 | |||
928 | if (NULL != s->intersected_elements) | ||
929 | { | ||
930 | /* only one concurrent session per client connection allowed, | ||
931 | simplifies logic a lot... */ | ||
932 | GNUNET_break (0); | ||
933 | return GNUNET_SYSERR; | ||
934 | } | ||
935 | msize = ntohs (msg->header.size); | ||
936 | total_count = ntohl (msg->element_count_total); | ||
937 | contained_count = ntohl (msg->element_count_contained); | ||
938 | if ((0 == total_count) || (0 == contained_count) || | ||
939 | (msize != | ||
940 | (sizeof(struct AliceComputationMessage) | ||
941 | + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element)))) | ||
942 | { | ||
943 | GNUNET_break_op (0); | ||
944 | return GNUNET_SYSERR; | ||
945 | } | ||
946 | return GNUNET_OK; | ||
947 | } | ||
948 | |||
949 | |||
950 | /** | ||
951 | * Handler for Alice's client request message. | ||
952 | * We are doing request-initiation to compute a scalar product with a peer. | ||
953 | * | ||
954 | * @param cls identification of the client | ||
955 | * @param msg the actual message | ||
956 | */ | ||
957 | static void | ||
958 | handle_alice_client_message (void *cls, | ||
959 | const struct AliceComputationMessage *msg) | ||
960 | { | ||
961 | struct AliceServiceSession *s = cls; | ||
962 | uint32_t contained_count; | ||
963 | uint32_t total_count; | ||
964 | const struct GNUNET_SCALARPRODUCT_Element *elements; | ||
965 | struct GNUNET_SETI_Element set_elem; | ||
966 | struct GNUNET_SCALARPRODUCT_Element *elem; | ||
967 | |||
968 | total_count = ntohl (msg->element_count_total); | ||
969 | contained_count = ntohl (msg->element_count_contained); | ||
970 | s->peer = msg->peer; | ||
971 | s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE; | ||
972 | s->total = total_count; | ||
973 | s->client_received_element_count = contained_count; | ||
974 | s->session_id = msg->session_key; | ||
975 | elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1]; | ||
976 | s->intersected_elements = | ||
977 | GNUNET_CONTAINER_multihashmap_create (s->total, | ||
978 | GNUNET_YES); | ||
979 | s->intersection_set = GNUNET_SETI_create (cfg); | ||
980 | for (uint32_t i = 0; i < contained_count; i++) | ||
981 | { | ||
982 | if (0 == GNUNET_ntohll (elements[i].value)) | ||
983 | continue; | ||
984 | elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element); | ||
985 | *elem = elements[i]; | ||
986 | if (GNUNET_SYSERR == | ||
987 | GNUNET_CONTAINER_multihashmap_put ( | ||
988 | s->intersected_elements, | ||
989 | &elem->key, | ||
990 | elem, | ||
991 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
992 | { | ||
993 | /* element with same key encountered twice! */ | ||
994 | GNUNET_break (0); | ||
995 | GNUNET_free (elem); | ||
996 | continue; | ||
997 | } | ||
998 | set_elem.data = &elem->key; | ||
999 | set_elem.size = sizeof(elem->key); | ||
1000 | set_elem.element_type = 0; | ||
1001 | GNUNET_SETI_add_element (s->intersection_set, | ||
1002 | &set_elem, | ||
1003 | NULL, | ||
1004 | NULL); | ||
1005 | s->used_element_count++; | ||
1006 | } | ||
1007 | GNUNET_SERVICE_client_continue (s->client); | ||
1008 | if (s->total != s->client_received_element_count) | ||
1009 | { | ||
1010 | /* wait for multipart msg */ | ||
1011 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1012 | "Received partial client request, waiting for more!\n"); | ||
1013 | return; | ||
1014 | } | ||
1015 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1016 | "Launching computation\n"); | ||
1017 | client_request_complete_alice (s); | ||
1018 | } | ||
1019 | |||
1020 | |||
1021 | /** | ||
1022 | * Task run during shutdown. | ||
1023 | * | ||
1024 | * @param cls unused | ||
1025 | * @param tc unused | ||
1026 | */ | ||
1027 | static void | ||
1028 | shutdown_task (void *cls) | ||
1029 | { | ||
1030 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1031 | "Shutting down, initiating cleanup.\n"); | ||
1032 | // FIXME: we have to cut our connections to CADET first! | ||
1033 | if (NULL != my_cadet) | ||
1034 | { | ||
1035 | GNUNET_CADET_disconnect (my_cadet); | ||
1036 | my_cadet = NULL; | ||
1037 | } | ||
1038 | if (NULL != edc) | ||
1039 | { | ||
1040 | GNUNET_CRYPTO_ecc_dlog_release (edc); | ||
1041 | edc = NULL; | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | |||
1046 | /** | ||
1047 | * A client connected. | ||
1048 | * | ||
1049 | * Setup the associated data structure. | ||
1050 | * | ||
1051 | * @param cls closure, NULL | ||
1052 | * @param client identification of the client | ||
1053 | * @param mq message queue to communicate with @a client | ||
1054 | * @return our `struct AliceServiceSession` | ||
1055 | */ | ||
1056 | static void * | ||
1057 | client_connect_cb (void *cls, | ||
1058 | struct GNUNET_SERVICE_Client *client, | ||
1059 | struct GNUNET_MQ_Handle *mq) | ||
1060 | { | ||
1061 | struct AliceServiceSession *s; | ||
1062 | |||
1063 | s = GNUNET_new (struct AliceServiceSession); | ||
1064 | s->client = client; | ||
1065 | s->client_mq = mq; | ||
1066 | return s; | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | /** | ||
1071 | * A client disconnected. | ||
1072 | * | ||
1073 | * Remove the associated session(s), release data structures | ||
1074 | * and cancel pending outgoing transmissions to the client. | ||
1075 | * | ||
1076 | * @param cls closure, NULL | ||
1077 | * @param client identification of the client | ||
1078 | * @param app_cls our `struct AliceServiceSession` | ||
1079 | */ | ||
1080 | static void | ||
1081 | client_disconnect_cb (void *cls, | ||
1082 | struct GNUNET_SERVICE_Client *client, | ||
1083 | void *app_cls) | ||
1084 | { | ||
1085 | struct AliceServiceSession *s = app_cls; | ||
1086 | |||
1087 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1088 | "Client %p disconnected from us.\n", | ||
1089 | client); | ||
1090 | s->client = NULL; | ||
1091 | s->client_mq = NULL; | ||
1092 | destroy_service_session (s); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | /** | ||
1097 | * Initialization of the program and message handlers | ||
1098 | * | ||
1099 | * @param cls closure | ||
1100 | * @param c configuration to use | ||
1101 | * @param service the initialized service | ||
1102 | */ | ||
1103 | static void | ||
1104 | run (void *cls, | ||
1105 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1106 | struct GNUNET_SERVICE_Handle *service) | ||
1107 | { | ||
1108 | cfg = c; | ||
1109 | edc = GNUNET_CRYPTO_ecc_dlog_prepare (MAX_RESULT, | ||
1110 | MAX_RAM); | ||
1111 | /* Select a random 'a' value for Alice */ | ||
1112 | GNUNET_CRYPTO_ecc_rnd_mpi (&my_privkey, | ||
1113 | &my_privkey_inv); | ||
1114 | my_cadet = GNUNET_CADET_connect (cfg); | ||
1115 | if (NULL == my_cadet) | ||
1116 | { | ||
1117 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1118 | _ ("Connect to CADET failed\n")); | ||
1119 | GNUNET_SCHEDULER_shutdown (); | ||
1120 | return; | ||
1121 | } | ||
1122 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
1123 | NULL); | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | /** | ||
1128 | * Define "main" method using service macro. | ||
1129 | */ | ||
1130 | GNUNET_SERVICE_MAIN ( | ||
1131 | "scalarproduct-alice", | ||
1132 | GNUNET_SERVICE_OPTION_NONE, | ||
1133 | &run, | ||
1134 | &client_connect_cb, | ||
1135 | &client_disconnect_cb, | ||
1136 | NULL, | ||
1137 | GNUNET_MQ_hd_var_size (alice_client_message, | ||
1138 | GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE, | ||
1139 | struct AliceComputationMessage, | ||
1140 | NULL), | ||
1141 | GNUNET_MQ_hd_var_size ( | ||
1142 | alice_client_message_multipart, | ||
1143 | GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_ALICE, | ||
1144 | struct ComputationBobCryptodataMultipartMessage, | ||
1145 | NULL), | ||
1146 | GNUNET_MQ_handler_end ()); | ||
1147 | |||
1148 | |||
1149 | /* end of gnunet-service-scalarproduct-ecc_alice.c */ | ||