diff options
author | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-11-18 16:58:09 +0000 |
---|---|---|
committer | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-11-18 16:58:09 +0000 |
commit | 2f458da11619c091b26e4f6d0f5c2cd05564dc9f (patch) | |
tree | b1b58381427a85b2167c2716abfebfac5922bdc6 /src/set | |
parent | ed1b854483dc796993c3866bc855f326f93abe2d (diff) | |
download | gnunet-2f458da11619c091b26e4f6d0f5c2cd05564dc9f.tar.gz gnunet-2f458da11619c091b26e4f6d0f5c2cd05564dc9f.zip |
more work on intersection
Diffstat (limited to 'src/set')
-rw-r--r-- | src/set/gnunet-service-set_intersection.c | 223 |
1 files changed, 82 insertions, 141 deletions
diff --git a/src/set/gnunet-service-set_intersection.c b/src/set/gnunet-service-set_intersection.c index 042d9fa33..1c79d3c73 100644 --- a/src/set/gnunet-service-set_intersection.c +++ b/src/set/gnunet-service-set_intersection.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "set_protocol.h" | 30 | #include "set_protocol.h" |
31 | #include <gcrypt.h> | 31 | #include <gcrypt.h> |
32 | 32 | ||
33 | #define BLOOMFILTER_SIZE GNUNET_CRYPTO_HASH_LENGTH | ||
33 | /** | 34 | /** |
34 | * Current phase we are in for a intersection operation. | 35 | * Current phase we are in for a intersection operation. |
35 | */ | 36 | */ |
@@ -135,7 +136,7 @@ struct OperationState | |||
135 | * #GNUNET_NO if not. | 136 | * #GNUNET_NO if not. |
136 | */ | 137 | */ |
137 | static int | 138 | static int |
138 | iterator_initialization_alice (void *cls, | 139 | iterator_initialization_by_alice (void *cls, |
139 | const struct GNUNET_HashCode *key, | 140 | const struct GNUNET_HashCode *key, |
140 | void *value){ | 141 | void *value){ |
141 | struct ElementEntry *ee = value; | 142 | struct ElementEntry *ee = value; |
@@ -167,8 +168,6 @@ iterator_initialization_alice (void *cls, | |||
167 | } | 168 | } |
168 | 169 | ||
169 | /** | 170 | /** |
170 | * Bob's version: | ||
171 | * | ||
172 | * fills the contained-elements hashmap with all relevant | 171 | * fills the contained-elements hashmap with all relevant |
173 | * elements and adds their mutated hashes to our local bloomfilter | 172 | * elements and adds their mutated hashes to our local bloomfilter |
174 | * | 173 | * |
@@ -234,7 +233,7 @@ iterator_element_count (void *cls, | |||
234 | 233 | ||
235 | /** | 234 | /** |
236 | * removes element from a hashmap if it is not contained within the | 235 | * removes element from a hashmap if it is not contained within the |
237 | * provided remote bloomfilter. | 236 | * provided remote bloomfilter. Then, fill our new bloomfilter. |
238 | * | 237 | * |
239 | * @param cls closure | 238 | * @param cls closure |
240 | * @param key current key code | 239 | * @param key current key code |
@@ -244,7 +243,7 @@ iterator_element_count (void *cls, | |||
244 | * #GNUNET_NO if not. | 243 | * #GNUNET_NO if not. |
245 | */ | 244 | */ |
246 | static int | 245 | static int |
247 | iterator_element_removal (void *cls, | 246 | iterator_bf_round (void *cls, |
248 | const struct GNUNET_HashCode *key, | 247 | const struct GNUNET_HashCode *key, |
249 | void *value){ | 248 | void *value){ |
250 | struct ElementEntry *ee = value; | 249 | struct ElementEntry *ee = value; |
@@ -259,31 +258,10 @@ iterator_element_removal (void *cls, | |||
259 | GNUNET_CONTAINER_multihashmap_remove (op->state->my_elements, | 258 | GNUNET_CONTAINER_multihashmap_remove (op->state->my_elements, |
260 | &ee->element_hash, | 259 | &ee->element_hash, |
261 | ee); | 260 | ee); |
261 | return GNUNET_YES; | ||
262 | } | 262 | } |
263 | 263 | ||
264 | return GNUNET_YES; | 264 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt+1, &mutated_hash); |
265 | } | ||
266 | |||
267 | /** | ||
268 | * removes element from a hashmap if it is not contained within the | ||
269 | * provided remote bloomfilter. | ||
270 | * | ||
271 | * @param cls closure | ||
272 | * @param key current key code | ||
273 | * @param value value in the hash map | ||
274 | * @return #GNUNET_YES if we should continue to | ||
275 | * iterate, | ||
276 | * #GNUNET_NO if not. | ||
277 | */ | ||
278 | static int | ||
279 | iterator_create_bf (void *cls, | ||
280 | const struct GNUNET_HashCode *key, | ||
281 | void *value){ | ||
282 | struct ElementEntry *ee = value; | ||
283 | struct Operation *op = cls; | ||
284 | struct GNUNET_HashCode mutated_hash; | ||
285 | |||
286 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
287 | 265 | ||
288 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, | 266 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, |
289 | &mutated_hash); | 267 | &mutated_hash); |
@@ -356,6 +334,25 @@ fail_intersection_operation (struct OperationState *eo) | |||
356 | 334 | ||
357 | 335 | ||
358 | /** | 336 | /** |
337 | * Inform the peer that this operation is complete. | ||
338 | * | ||
339 | * @param eo the intersection operation to fail | ||
340 | */ | ||
341 | static void | ||
342 | finalize_intersection_operation (struct Operation *op) | ||
343 | { | ||
344 | struct GNUNET_MQ_Envelope *ev; | ||
345 | |||
346 | op->state->phase = PHASE_FINISHED; | ||
347 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Intersection succeeded, sending DONE\n"); | ||
348 | GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); | ||
349 | op->state->local_bf = NULL; | ||
350 | |||
351 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_P2P_DONE); | ||
352 | GNUNET_MQ_send (op->mq, ev); | ||
353 | } | ||
354 | |||
355 | /** | ||
359 | * Send a request for the evaluate operation to a remote peer | 356 | * Send a request for the evaluate operation to a remote peer |
360 | * | 357 | * |
361 | * @param eo operation with the other peer | 358 | * @param eo operation with the other peer |
@@ -396,7 +393,6 @@ send_operation_request (struct Operation *op) | |||
396 | 393 | ||
397 | } | 394 | } |
398 | 395 | ||
399 | |||
400 | /** | 396 | /** |
401 | * Handle an BF message from a remote peer. | 397 | * Handle an BF message from a remote peer. |
402 | * | 398 | * |
@@ -408,50 +404,60 @@ handle_p2p_bf (void *cls, const struct GNUNET_MessageHeader *mh) | |||
408 | { | 404 | { |
409 | struct Operation *op = cls; | 405 | struct Operation *op = cls; |
410 | struct BFMessage *msg = (struct BFMessage *) mh; | 406 | struct BFMessage *msg = (struct BFMessage *) mh; |
407 | uint32_t old_count; | ||
411 | 408 | ||
412 | switch (op->state->phase){ | 409 | old_count = op->state->my_elements_count; |
410 | op->spec->salt = ntohl (msg->sender_mutator); | ||
411 | |||
412 | op->state->remote_bf = GNUNET_CONTAINER_bloomfilter_init (&msg[1], | ||
413 | BLOOMFILTER_SIZE, | ||
414 | ntohl (msg->bloomfilter_length)); | ||
415 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, | ||
416 | BLOOMFILTER_SIZE, | ||
417 | GNUNET_CONSTANTS_BLOOMFILTER_K); | ||
418 | switch (op->state->phase) | ||
419 | { | ||
413 | case PHASE_INITIAL: | 420 | case PHASE_INITIAL: |
414 | op->state->phase = PHASE_BF_EXCHANGE; | 421 | // If we are alice and got our first msg |
415 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | 422 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (op->state->my_elements_count, GNUNET_YES); |
416 | 423 | ||
417 | op->spec->salt = ntohl(msg->sender_mutator); | ||
418 | op->state->remote_bf = GNUNET_CONTAINER_bloomfilter_init (&msg[1], | ||
419 | GNUNET_CRYPTO_HASH_LENGTH, | ||
420 | ntohl(msg->bloomfilter_length)); | ||
421 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, | ||
422 | GNUNET_CRYPTO_HASH_LENGTH, | ||
423 | GNUNET_CONSTANTS_BLOOMFILTER_K); | ||
424 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | 424 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, |
425 | &iterator_initialization_alice, | 425 | &iterator_initialization_by_alice, |
426 | op); | 426 | op); |
427 | // iterator_initialization_alice created a new BF with salt+1 | 427 | break; |
428 | // bob needs this information for decoding the next BF | 428 | case PHASE_BF_EXCHANGE: |
429 | // this behavior can be modified at will later on. | 429 | case PHASE_MAYBE_FINISHED: |
430 | op->spec->salt++; | 430 | // if we are bob or alice and are continuing operation |
431 | 431 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | |
432 | GNUNET_CONTAINER_bloomfilter_free(op->state->remote_bf); | 432 | &iterator_bf_round, |
433 | op->state->remote_bf = NULL; | 433 | op); |
434 | 434 | break; | |
435 | if (op->state->my_elements_count == ntohl(msg->sender_element_count)) | ||
436 | op->state->phase = PHASE_MAYBE_FINISHED; | ||
437 | |||
438 | send_bloomfilter (op); | ||
439 | |||
440 | // if (the remote peer has less elements than us) | ||
441 | // run our elements through his bloomfilter | ||
442 | // if (we have the same elements) | ||
443 | // done; | ||
444 | // | ||
445 | // evict elements we can exclude through the bloomfilter | ||
446 | // | ||
447 | // create a new bloomfilter over our remaining elements | ||
448 | // | ||
449 | // send our new count and the bloomfilter back | ||
450 | case PHASE_BF_EXCHANGE: | ||
451 | break; | ||
452 | default: | 435 | default: |
453 | GNUNET_break_op(0); | 436 | GNUNET_break_op (0); |
437 | fail_intersection_operation(op); | ||
454 | } | 438 | } |
439 | // the iterators created a new BF with salt+1 | ||
440 | // the peer needs this information for decoding the next BF | ||
441 | // this behavior can be modified at will later on. | ||
442 | op->spec->salt++; | ||
443 | |||
444 | GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); | ||
445 | op->state->remote_bf = NULL; | ||
446 | |||
447 | if ((op->state->phase == PHASE_MAYBE_FINISHED) | ||
448 | && (old_count == op->state->my_elements_count)){ | ||
449 | // In the last round we though we were finished, we now know this is correct | ||
450 | finalize_intersection_operation(op); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | op->state->phase = PHASE_BF_EXCHANGE; | ||
455 | // maybe we are finished, but we do one more round to make certain | ||
456 | // we don't have false positives ... | ||
457 | if (op->state->my_elements_count == ntohl (msg->sender_element_count)) | ||
458 | op->state->phase = PHASE_MAYBE_FINISHED; | ||
459 | |||
460 | send_bloomfilter (op); | ||
455 | } | 461 | } |
456 | 462 | ||
457 | 463 | ||
@@ -469,8 +475,8 @@ handle_p2p_element_info (void *cls, const struct GNUNET_MessageHeader *mh) | |||
469 | uint32_t remote_element_count; | 475 | uint32_t remote_element_count; |
470 | 476 | ||
471 | remote_element_count = ntohl(msg->sender_element_count); | 477 | remote_element_count = ntohl(msg->sender_element_count); |
472 | if (op->state->phase == PHASE_INITIAL | 478 | if ((op->state->phase == PHASE_INITIAL) |
473 | || op->state->my_elements_count > remote_element_count){ | 479 | || (op->state->my_elements_count > remote_element_count)){ |
474 | GNUNET_break_op (0); | 480 | GNUNET_break_op (0); |
475 | fail_intersection_operation(op); | 481 | fail_intersection_operation(op); |
476 | } | 482 | } |
@@ -478,20 +484,12 @@ handle_p2p_element_info (void *cls, const struct GNUNET_MessageHeader *mh) | |||
478 | op->state->phase = PHASE_BF_EXCHANGE; | 484 | op->state->phase = PHASE_BF_EXCHANGE; |
479 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | 485 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); |
480 | 486 | ||
481 | op->spec->salt = ntohl (msg->sender_mutator); | ||
482 | op->state->remote_bf = GNUNET_CONTAINER_bloomfilter_init (&msg[1], | ||
483 | GNUNET_CRYPTO_HASH_LENGTH, | ||
484 | ntohl (msg->bloomfilter_length)); | ||
485 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, | 487 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, |
486 | GNUNET_CRYPTO_HASH_LENGTH, | 488 | BLOOMFILTER_SIZE, |
487 | GNUNET_CONSTANTS_BLOOMFILTER_K); | 489 | GNUNET_CONSTANTS_BLOOMFILTER_K); |
488 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | 490 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, |
489 | &iterator_initialization_alice, | 491 | &iterator_initialization, |
490 | op); | 492 | op); |
491 | // iterator_initialization_alice created a new BF with salt+1 | ||
492 | // bob needs this information for decoding the next BF | ||
493 | // this behavior can be modified at will later on. | ||
494 | op->spec->salt++; | ||
495 | 493 | ||
496 | GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); | 494 | GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); |
497 | op->state->remote_bf = NULL; | 495 | op->state->remote_bf = NULL; |
@@ -504,64 +502,6 @@ handle_p2p_element_info (void *cls, const struct GNUNET_MessageHeader *mh) | |||
504 | 502 | ||
505 | 503 | ||
506 | /** | 504 | /** |
507 | * Send a result message to the client indicating | ||
508 | * that there is a new element. | ||
509 | * | ||
510 | * @param eo intersection operation | ||
511 | * @param element element to send | ||
512 | */ | ||
513 | static void | ||
514 | send_client_element (struct OperationState *eo, | ||
515 | struct GNUNET_SET_Element *element) | ||
516 | { | ||
517 | struct GNUNET_MQ_Envelope *ev; | ||
518 | struct GNUNET_SET_ResultMessage *rm; | ||
519 | |||
520 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element (size %u) to client\n", element->size); | ||
521 | GNUNET_assert (0 != eo->spec->client_request_id); | ||
522 | ev = GNUNET_MQ_msg_extra (rm, element->size, GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
523 | if (NULL == ev) | ||
524 | { | ||
525 | GNUNET_MQ_discard (ev); | ||
526 | GNUNET_break (0); | ||
527 | return; | ||
528 | } | ||
529 | rm->result_status = htons (GNUNET_SET_STATUS_OK); | ||
530 | rm->request_id = htonl (eo->spec->client_request_id); | ||
531 | rm->element_type = element->type; | ||
532 | memcpy (&rm[1], element->data, element->size); | ||
533 | GNUNET_MQ_send (eo->spec->set->client_mq, ev); | ||
534 | } | ||
535 | |||
536 | |||
537 | /** | ||
538 | * Send a result message to the client indicating | ||
539 | * that the operation is over. | ||
540 | * After the result done message has been sent to the client, | ||
541 | * destroy the evaluate operation. | ||
542 | * | ||
543 | * @param eo intersection operation | ||
544 | */ | ||
545 | static void | ||
546 | send_client_done_and_destroy (struct OperationState *eo) | ||
547 | { | ||
548 | struct GNUNET_MQ_Envelope *ev; | ||
549 | struct GNUNET_SET_ResultMessage *rm; | ||
550 | |||
551 | GNUNET_assert (GNUNET_NO == eo->client_done_sent); | ||
552 | |||
553 | eo->client_done_sent = GNUNET_YES; | ||
554 | |||
555 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
556 | rm->request_id = htonl (eo->spec->client_request_id); | ||
557 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); | ||
558 | rm->element_type = htons (0); | ||
559 | GNUNET_MQ_send (eo->spec->set->client_mq, ev); | ||
560 | |||
561 | intersection_operation_destroy (eo); | ||
562 | } | ||
563 | |||
564 | /** | ||
565 | * Send a bloomfilter to our peer. | 505 | * Send a bloomfilter to our peer. |
566 | * that the operation is over. | 506 | * that the operation is over. |
567 | * After the result done message has been sent to the client, | 507 | * After the result done message has been sent to the client, |
@@ -572,7 +512,6 @@ send_client_done_and_destroy (struct OperationState *eo) | |||
572 | static void | 512 | static void |
573 | send_bloomfilter (struct Operation *op) | 513 | send_bloomfilter (struct Operation *op) |
574 | { | 514 | { |
575 | struct BloomFilter *bf; | ||
576 | struct GNUNET_MQ_Envelope *ev; | 515 | struct GNUNET_MQ_Envelope *ev; |
577 | struct BFMessage *msg; | 516 | struct BFMessage *msg; |
578 | uint32_t bf_size; | 517 | uint32_t bf_size; |
@@ -590,7 +529,9 @@ send_bloomfilter (struct Operation *op) | |||
590 | GNUNET_assert (GNUNET_SYSERR != | 529 | GNUNET_assert (GNUNET_SYSERR != |
591 | GNUNET_CONTAINER_bloomfilter_get_raw_data (op->state->local_bf, | 530 | GNUNET_CONTAINER_bloomfilter_get_raw_data (op->state->local_bf, |
592 | &msg->sender_bf_data, | 531 | &msg->sender_bf_data, |
593 | GNUNET_CRYPTO_HASH_LENGTH)); | 532 | BLOOMFILTER_SIZE)); |
533 | GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); | ||
534 | op->state->local_bf = NULL; | ||
594 | GNUNET_MQ_send (op->mq, ev); | 535 | GNUNET_MQ_send (op->mq, ev); |
595 | } | 536 | } |
596 | 537 | ||
@@ -692,7 +633,7 @@ intersection_accept (struct Operation *op) | |||
692 | &iterator_element_count, | 633 | &iterator_element_count, |
693 | op); | 634 | op); |
694 | 635 | ||
695 | // if we have more elements than our peer, he should start | 636 | // if Alice (the peer) has more elements than Bob (us), she should start |
696 | if (op->spec->element_count < op->state->my_elements_count){ | 637 | if (op->spec->element_count < op->state->my_elements_count){ |
697 | op->state->phase = PHASE_INITIAL; | 638 | op->state->phase = PHASE_INITIAL; |
698 | send_element_count(op); | 639 | send_element_count(op); |
@@ -702,7 +643,7 @@ intersection_accept (struct Operation *op) | |||
702 | // create a new bloomfilter in case we have fewer elements | 643 | // create a new bloomfilter in case we have fewer elements |
703 | op->state->phase = PHASE_BF_EXCHANGE; | 644 | op->state->phase = PHASE_BF_EXCHANGE; |
704 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, | 645 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, |
705 | GNUNET_CRYPTO_HASH_LENGTH, | 646 | BLOOMFILTER_SIZE, |
706 | GNUNET_CONSTANTS_BLOOMFILTER_K); | 647 | GNUNET_CONSTANTS_BLOOMFILTER_K); |
707 | 648 | ||
708 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | 649 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, |