aboutsummaryrefslogtreecommitdiff
path: root/src/set
diff options
context:
space:
mode:
authorChristian Fuchs <christian.fuchs@cfuchs.net>2013-11-18 16:58:09 +0000
committerChristian Fuchs <christian.fuchs@cfuchs.net>2013-11-18 16:58:09 +0000
commit2f458da11619c091b26e4f6d0f5c2cd05564dc9f (patch)
treeb1b58381427a85b2167c2716abfebfac5922bdc6 /src/set
parented1b854483dc796993c3866bc855f326f93abe2d (diff)
downloadgnunet-2f458da11619c091b26e4f6d0f5c2cd05564dc9f.tar.gz
gnunet-2f458da11619c091b26e4f6d0f5c2cd05564dc9f.zip
more work on intersection
Diffstat (limited to 'src/set')
-rw-r--r--src/set/gnunet-service-set_intersection.c223
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 */
137static int 138static int
138iterator_initialization_alice (void *cls, 139iterator_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 */
246static int 245static int
247iterator_element_removal (void *cls, 246iterator_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 */
278static int
279iterator_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 */
341static void
342finalize_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 */
513static void
514send_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 */
545static void
546send_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)
572static void 512static void
573send_bloomfilter (struct Operation *op) 513send_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,