diff options
author | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-11-14 16:48:49 +0000 |
---|---|---|
committer | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-11-14 16:48:49 +0000 |
commit | 0d6e1036ad64d341651d113e3427323a157353d3 (patch) | |
tree | ccd6286eddbdb4ce055209d9c1557bc3802fb45c /src/set | |
parent | d67a1f6613ec4feadc99026f027483aff03f8381 (diff) | |
download | gnunet-0d6e1036ad64d341651d113e3427323a157353d3.tar.gz gnunet-0d6e1036ad64d341651d113e3427323a157353d3.zip |
added new msg type
more work on intersection
Diffstat (limited to 'src/set')
-rw-r--r-- | src/set/gnunet-service-set.c | 2 | ||||
-rw-r--r-- | src/set/gnunet-service-set.h | 5 | ||||
-rw-r--r-- | src/set/gnunet-service-set_intersection.c | 541 | ||||
-rw-r--r-- | src/set/set_protocol.h | 17 |
4 files changed, 365 insertions, 200 deletions
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c index d4c347d48..490a3e5ce 100644 --- a/src/set/gnunet-service-set.c +++ b/src/set/gnunet-service-set.c | |||
@@ -567,6 +567,7 @@ handle_incoming_msg (struct Operation *op, | |||
567 | spec->app_id = msg->app_id; | 567 | spec->app_id = msg->app_id; |
568 | spec->salt = ntohl (msg->salt); | 568 | spec->salt = ntohl (msg->salt); |
569 | spec->peer = op->state->peer; | 569 | spec->peer = op->state->peer; |
570 | spec->element_count = ntohl (msg->element_count); | ||
570 | 571 | ||
571 | op->spec = spec; | 572 | op->spec = spec; |
572 | 573 | ||
@@ -1325,6 +1326,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
1325 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_DONE, 0}, | 1326 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_DONE, 0}, |
1326 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS, 0}, | 1327 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS, 0}, |
1327 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 0}, | 1328 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 0}, |
1329 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 0}, | ||
1328 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF, 0}, | 1330 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF, 0}, |
1329 | {NULL, 0, 0} | 1331 | {NULL, 0, 0} |
1330 | }; | 1332 | }; |
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h index 62e8cbc87..af3aa7287 100644 --- a/src/set/gnunet-service-set.h +++ b/src/set/gnunet-service-set.h | |||
@@ -89,6 +89,11 @@ struct OperationSpecification | |||
89 | * Salt to use for the operation. | 89 | * Salt to use for the operation. |
90 | */ | 90 | */ |
91 | uint32_t salt; | 91 | uint32_t salt; |
92 | |||
93 | /** | ||
94 | * Remote peers element count | ||
95 | */ | ||
96 | uint32_t element_count; | ||
92 | 97 | ||
93 | /** | 98 | /** |
94 | * ID used to identify an operation between service and client | 99 | * ID used to identify an operation between service and client |
diff --git a/src/set/gnunet-service-set_intersection.c b/src/set/gnunet-service-set_intersection.c index de5198b9c..042d9fa33 100644 --- a/src/set/gnunet-service-set_intersection.c +++ b/src/set/gnunet-service-set_intersection.c | |||
@@ -36,14 +36,23 @@ | |||
36 | enum IntersectionOperationPhase | 36 | enum IntersectionOperationPhase |
37 | { | 37 | { |
38 | /** | 38 | /** |
39 | * We get our tunnel but received no message as of now | 39 | * Alices has suggested an operation to bob, |
40 | * and is waiting for a bf or session end. | ||
40 | */ | 41 | */ |
41 | PHASE_EXPECT_INITIAL, | 42 | PHASE_INITIAL, |
42 | /** | 43 | /** |
43 | * We expect a BF + the number of the other peers elements | 44 | * Bob has accepted the operation, Bob and Alice are now exchanging bfs |
45 | * until one notices the their element count is equal | ||
44 | */ | 46 | */ |
45 | PHASE_BF_EXCHANGE, | 47 | PHASE_BF_EXCHANGE, |
46 | /** | 48 | /** |
49 | * if both peers have an equal peercount, they enter this state for | ||
50 | * one more turn, to see if they actually have agreed on a correct set. | ||
51 | * if a peer finds the same element count after the next iteration, | ||
52 | * it ends the the session | ||
53 | */ | ||
54 | PHASE_MAYBE_FINISHED, | ||
55 | /** | ||
47 | * The protocol is over. | 56 | * The protocol is over. |
48 | * Results may still have to be sent to the client. | 57 | * Results may still have to be sent to the client. |
49 | */ | 58 | */ |
@@ -81,12 +90,12 @@ struct OperationState | |||
81 | /** | 90 | /** |
82 | * Maps element-id-hashes to 'elements in our set'. | 91 | * Maps element-id-hashes to 'elements in our set'. |
83 | */ | 92 | */ |
84 | struct GNUNET_CONTAINER_MultiHashMap *contained_elements; | 93 | struct GNUNET_CONTAINER_MultiHashMap *my_elements; |
85 | 94 | ||
86 | /** | 95 | /** |
87 | * Current element count contained within contained_elements | 96 | * Current element count contained within contained_elements |
88 | */ | 97 | */ |
89 | uint32_t contained_elements_count; | 98 | uint32_t my_elements_count; |
90 | 99 | ||
91 | /** | 100 | /** |
92 | * Iterator for sending elements on the key to element mapping to the client. | 101 | * Iterator for sending elements on the key to element mapping to the client. |
@@ -112,6 +121,175 @@ struct OperationState | |||
112 | }; | 121 | }; |
113 | 122 | ||
114 | 123 | ||
124 | /** | ||
125 | * Alice's version: | ||
126 | * | ||
127 | * fills the contained-elements hashmap with all relevant | ||
128 | * elements and adds their mutated hashes to our local bloomfilter with mutator+1 | ||
129 | * | ||
130 | * @param cls closure | ||
131 | * @param key current key code | ||
132 | * @param value value in the hash map | ||
133 | * @return #GNUNET_YES if we should continue to | ||
134 | * iterate, | ||
135 | * #GNUNET_NO if not. | ||
136 | */ | ||
137 | static int | ||
138 | iterator_initialization_alice (void *cls, | ||
139 | const struct GNUNET_HashCode *key, | ||
140 | void *value){ | ||
141 | struct ElementEntry *ee = value; | ||
142 | struct Operation *op = cls; | ||
143 | struct GNUNET_HashCode mutated_hash; | ||
144 | |||
145 | //only consider this element, if it is valid for us | ||
146 | if ((op->generation_created >= ee->generation_removed) | ||
147 | || (op->generation_created < ee->generation_added)) | ||
148 | return GNUNET_YES; | ||
149 | |||
150 | // not contained according to bob's bloomfilter | ||
151 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
152 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, | ||
153 | &mutated_hash)) | ||
154 | return GNUNET_YES; | ||
155 | |||
156 | op->state->my_elements_count++; | ||
157 | GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, | ||
158 | &ee->element_hash, ee, | ||
159 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
160 | |||
161 | // create our own bloomfilter with salt+1 | ||
162 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt+1, &mutated_hash); | ||
163 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, | ||
164 | &mutated_hash); | ||
165 | |||
166 | return GNUNET_YES; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Bob's version: | ||
171 | * | ||
172 | * fills the contained-elements hashmap with all relevant | ||
173 | * elements and adds their mutated hashes to our local bloomfilter | ||
174 | * | ||
175 | * @param cls closure | ||
176 | * @param key current key code | ||
177 | * @param value value in the hash map | ||
178 | * @return #GNUNET_YES if we should continue to | ||
179 | * iterate, | ||
180 | * #GNUNET_NO if not. | ||
181 | */ | ||
182 | static int | ||
183 | iterator_initialization (void *cls, | ||
184 | const struct GNUNET_HashCode *key, | ||
185 | void *value){ | ||
186 | struct ElementEntry *ee = value; | ||
187 | struct Operation *op = cls; | ||
188 | struct GNUNET_HashCode mutated_hash; | ||
189 | |||
190 | //only consider this element, if it is valid for us | ||
191 | if ((op->generation_created >= ee->generation_removed) | ||
192 | || (op->generation_created < ee->generation_added)) | ||
193 | return GNUNET_YES; | ||
194 | |||
195 | GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, | ||
196 | &ee->element_hash, ee, | ||
197 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
198 | |||
199 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
200 | |||
201 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, | ||
202 | &mutated_hash); | ||
203 | |||
204 | return GNUNET_YES; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Counts all valid elements in the hashmap | ||
209 | * (the ones that are valid in our generation) | ||
210 | * | ||
211 | * @param cls closure | ||
212 | * @param key current key code | ||
213 | * @param value value in the hash map | ||
214 | * @return #GNUNET_YES if we should continue to | ||
215 | * iterate, | ||
216 | * #GNUNET_NO if not. | ||
217 | */ | ||
218 | static int | ||
219 | iterator_element_count (void *cls, | ||
220 | const struct GNUNET_HashCode *key, | ||
221 | void *value){ | ||
222 | struct ElementEntry *ee = value; | ||
223 | struct Operation *op = cls; | ||
224 | |||
225 | //only consider this element, if it is valid for us | ||
226 | if ((op->generation_created >= ee->generation_removed) | ||
227 | || (op->generation_created < ee->generation_added)) | ||
228 | return GNUNET_YES; | ||
229 | |||
230 | op->state->my_elements_count++; | ||
231 | |||
232 | return GNUNET_YES; | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * removes element from a hashmap if it is not contained within the | ||
237 | * provided remote bloomfilter. | ||
238 | * | ||
239 | * @param cls closure | ||
240 | * @param key current key code | ||
241 | * @param value value in the hash map | ||
242 | * @return #GNUNET_YES if we should continue to | ||
243 | * iterate, | ||
244 | * #GNUNET_NO if not. | ||
245 | */ | ||
246 | static int | ||
247 | iterator_element_removal (void *cls, | ||
248 | const struct GNUNET_HashCode *key, | ||
249 | void *value){ | ||
250 | struct ElementEntry *ee = value; | ||
251 | struct Operation *op = cls; | ||
252 | struct GNUNET_HashCode mutated_hash; | ||
253 | |||
254 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
255 | |||
256 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, | ||
257 | &mutated_hash)){ | ||
258 | op->state->my_elements_count--; | ||
259 | GNUNET_CONTAINER_multihashmap_remove (op->state->my_elements, | ||
260 | &ee->element_hash, | ||
261 | ee); | ||
262 | } | ||
263 | |||
264 | return GNUNET_YES; | ||
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 | |||
288 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, | ||
289 | &mutated_hash); | ||
290 | |||
291 | return GNUNET_YES; | ||
292 | } | ||
115 | 293 | ||
116 | /** | 294 | /** |
117 | * Destroy a intersection operation, and free all resources | 295 | * Destroy a intersection operation, and free all resources |
@@ -201,6 +379,8 @@ send_operation_request (struct Operation *op) | |||
201 | msg->operation = htonl (GNUNET_SET_OPERATION_INTERSECTION); | 379 | msg->operation = htonl (GNUNET_SET_OPERATION_INTERSECTION); |
202 | msg->app_id = op->spec->app_id; | 380 | msg->app_id = op->spec->app_id; |
203 | msg->salt = htonl (op->spec->salt); | 381 | msg->salt = htonl (op->spec->salt); |
382 | msg->element_count = htonl(op->state->my_elements); | ||
383 | |||
204 | GNUNET_MQ_send (op->mq, ev); | 384 | GNUNET_MQ_send (op->mq, ev); |
205 | 385 | ||
206 | if (NULL != op->spec->context_msg) | 386 | if (NULL != op->spec->context_msg) |
@@ -226,19 +406,40 @@ send_operation_request (struct Operation *op) | |||
226 | static void | 406 | static void |
227 | handle_p2p_bf (void *cls, const struct GNUNET_MessageHeader *mh) | 407 | handle_p2p_bf (void *cls, const struct GNUNET_MessageHeader *mh) |
228 | { | 408 | { |
229 | struct OperationState *eo = cls; | 409 | struct Operation *op = cls; |
230 | struct BFMessage *msg = (struct BFMessage *) mh; | 410 | struct BFMessage *msg = (struct BFMessage *) mh; |
231 | unsigned int buckets_in_message; | ||
232 | 411 | ||
233 | if (eo->phase == PHASE_EXPECT_INITIAL ) | 412 | switch (op->state->phase){ |
234 | { | 413 | case PHASE_INITIAL: |
235 | eo->phase = PHASE_BF_EXCHANGE; | 414 | op->state->phase = PHASE_BF_EXCHANGE; |
415 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
416 | |||
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, | ||
425 | &iterator_initialization_alice, | ||
426 | op); | ||
427 | // iterator_initialization_alice created a new BF with salt+1 | ||
428 | // bob needs this information for decoding the next BF | ||
429 | // this behavior can be modified at will later on. | ||
430 | op->spec->salt++; | ||
431 | |||
432 | GNUNET_CONTAINER_bloomfilter_free(op->state->remote_bf); | ||
433 | op->state->remote_bf = NULL; | ||
434 | |||
435 | if (op->state->my_elements_count == ntohl(msg->sender_element_count)) | ||
436 | op->state->phase = PHASE_MAYBE_FINISHED; | ||
437 | |||
438 | send_bloomfilter (op); | ||
236 | 439 | ||
237 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "creating new bf of size %u\n", 1<<msg->order); | ||
238 | |||
239 | // if (the remote peer has less elements than us) | 440 | // if (the remote peer has less elements than us) |
240 | // run our elements through his bloomfilter | 441 | // run our elements through his bloomfilter |
241 | // else if (we have the same elements) | 442 | // if (we have the same elements) |
242 | // done; | 443 | // done; |
243 | // | 444 | // |
244 | // evict elements we can exclude through the bloomfilter | 445 | // evict elements we can exclude through the bloomfilter |
@@ -246,12 +447,59 @@ handle_p2p_bf (void *cls, const struct GNUNET_MessageHeader *mh) | |||
246 | // create a new bloomfilter over our remaining elements | 447 | // create a new bloomfilter over our remaining elements |
247 | // | 448 | // |
248 | // send our new count and the bloomfilter back | 449 | // send our new count and the bloomfilter back |
450 | case PHASE_BF_EXCHANGE: | ||
451 | break; | ||
452 | default: | ||
453 | GNUNET_break_op(0); | ||
249 | } | 454 | } |
250 | else if (eo->phase == PHASE_BF_EXCHANGE) | 455 | } |
251 | { | 456 | |
252 | 457 | ||
458 | /** | ||
459 | * Handle an BF message from a remote peer. | ||
460 | * | ||
461 | * @param cls the intersection operation | ||
462 | * @param mh the header of the message | ||
463 | */ | ||
464 | static void | ||
465 | handle_p2p_element_info (void *cls, const struct GNUNET_MessageHeader *mh) | ||
466 | { | ||
467 | struct Operation *op = cls; | ||
468 | struct BFMessage *msg = (struct BFMessage *) mh; | ||
469 | uint32_t remote_element_count; | ||
470 | |||
471 | remote_element_count = ntohl(msg->sender_element_count); | ||
472 | if (op->state->phase == PHASE_INITIAL | ||
473 | || op->state->my_elements_count > remote_element_count){ | ||
474 | GNUNET_break_op (0); | ||
475 | fail_intersection_operation(op); | ||
253 | } | 476 | } |
254 | 477 | ||
478 | op->state->phase = PHASE_BF_EXCHANGE; | ||
479 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
480 | |||
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, | ||
486 | GNUNET_CRYPTO_HASH_LENGTH, | ||
487 | GNUNET_CONSTANTS_BLOOMFILTER_K); | ||
488 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | ||
489 | &iterator_initialization_alice, | ||
490 | 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 | |||
496 | GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); | ||
497 | op->state->remote_bf = NULL; | ||
498 | |||
499 | if (op->state->my_elements_count == ntohl (msg->sender_element_count)) | ||
500 | op->state->phase = PHASE_MAYBE_FINISHED; | ||
501 | |||
502 | send_bloomfilter (op); | ||
255 | } | 503 | } |
256 | 504 | ||
257 | 505 | ||
@@ -313,7 +561,6 @@ send_client_done_and_destroy (struct OperationState *eo) | |||
313 | intersection_operation_destroy (eo); | 561 | intersection_operation_destroy (eo); |
314 | } | 562 | } |
315 | 563 | ||
316 | |||
317 | /** | 564 | /** |
318 | * Send a bloomfilter to our peer. | 565 | * Send a bloomfilter to our peer. |
319 | * that the operation is over. | 566 | * that the operation is over. |
@@ -328,24 +575,49 @@ send_bloomfilter (struct Operation *op) | |||
328 | struct BloomFilter *bf; | 575 | struct BloomFilter *bf; |
329 | struct GNUNET_MQ_Envelope *ev; | 576 | struct GNUNET_MQ_Envelope *ev; |
330 | struct BFMessage *msg; | 577 | struct BFMessage *msg; |
331 | 578 | uint32_t bf_size; | |
332 | 579 | ||
333 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending bf of size %u\n", ); | 580 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending bf of size %u\n",); |
334 | 581 | ||
335 | ev = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); | 582 | // send our bloomfilter |
583 | bf_size = GNUNET_CONTAINER_bloomfilter_get_size (op->state->local_bf); | ||
584 | |||
585 | ev = GNUNET_MQ_msg_extra (msg, bf_size, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); | ||
336 | msg->reserved = 0; | 586 | msg->reserved = 0; |
587 | msg->sender_element_count = htonl (op->state->my_elements_count); | ||
588 | msg->bloomfilter_length = htonl (bf_size); | ||
337 | msg->sender_mutator = htonl (op->spec->salt); | 589 | msg->sender_mutator = htonl (op->spec->salt); |
338 | msg->sender_element_count = htonl (op->state->contained_elements_count); | 590 | GNUNET_assert (GNUNET_SYSERR != |
339 | GNUNET_assert(GNUNET_SYSERR != GNUNET_CONTAINER_bloomfilter_get_raw_data( | 591 | GNUNET_CONTAINER_bloomfilter_get_raw_data (op->state->local_bf, |
340 | op->state->local_bf, | 592 | &msg->sender_bf_data, |
341 | &msg->bf_data, | 593 | GNUNET_CRYPTO_HASH_LENGTH)); |
342 | GNUNET_CRYPTO_HASH_LENGTH)); | ||
343 | |||
344 | GNUNET_MQ_send (op->mq, ev); | 594 | GNUNET_MQ_send (op->mq, ev); |
595 | } | ||
345 | 596 | ||
346 | op->state->phase = PHASE_BF_EXCHANGE; | 597 | /** |
598 | * Send our element to the peer, in case our element count is lower than his | ||
599 | * | ||
600 | * @param eo intersection operation | ||
601 | */ | ||
602 | static void | ||
603 | send_element_count (struct Operation *op) | ||
604 | { | ||
605 | struct GNUNET_MQ_Envelope *ev; | ||
606 | struct BFMessage *msg; | ||
607 | |||
608 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element count (bf_msg)\n"); | ||
609 | |||
610 | // just send our element count, as the other peer must start | ||
611 | ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO); | ||
612 | msg->reserved = 0; | ||
613 | msg->sender_element_count = htonl (op->state->my_elements_count); | ||
614 | msg->bloomfilter_length = htonl (0); | ||
615 | msg->sender_mutator = htonl (0); | ||
616 | |||
617 | GNUNET_MQ_send (op->mq, ev); | ||
347 | } | 618 | } |
348 | 619 | ||
620 | |||
349 | /** | 621 | /** |
350 | * Handle a done message from a remote peer | 622 | * Handle a done message from a remote peer |
351 | * | 623 | * |
@@ -391,157 +663,16 @@ intersection_evaluate (struct Operation *op) | |||
391 | { | 663 | { |
392 | op->state = GNUNET_new (struct OperationState); | 664 | op->state = GNUNET_new (struct OperationState); |
393 | /* we started the operation, thus we have to send the operation request */ | 665 | /* we started the operation, thus we have to send the operation request */ |
394 | op->state->phase = PHASE_BF_EXCHANGE; | 666 | op->state->phase = PHASE_INITIAL; |
667 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES); | ||
668 | GNUNET_CONTAINER_multihashmap_iterate(op->spec->set->elements, | ||
669 | &iterator_element_count, | ||
670 | op); | ||
671 | |||
395 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "evaluating intersection operation"); | 672 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "evaluating intersection operation"); |
396 | send_operation_request (op); | 673 | send_operation_request (op); |
397 | } | 674 | } |
398 | 675 | ||
399 | |||
400 | /** | ||
401 | * Alice's version: | ||
402 | * | ||
403 | * fills the contained-elements hashmap with all relevant | ||
404 | * elements and adds their mutated hashes to our local bloomfilter with mutator+1 | ||
405 | * | ||
406 | * @param cls closure | ||
407 | * @param key current key code | ||
408 | * @param value value in the hash map | ||
409 | * @return #GNUNET_YES if we should continue to | ||
410 | * iterate, | ||
411 | * #GNUNET_NO if not. | ||
412 | */ | ||
413 | static int | ||
414 | intersection_iterator_set_to_contained_alice (void *cls, | ||
415 | const struct GNUNET_HashCode *key, | ||
416 | void *value){ | ||
417 | struct ElementEntry *ee = value; | ||
418 | struct Operation *op = cls; | ||
419 | struct GNUNET_HashCode mutated_hash; | ||
420 | |||
421 | //only consider this element, if it is valid for us | ||
422 | if ((op->generation_created >= ee->generation_removed) | ||
423 | || (op->generation_created < ee->generation_added)) | ||
424 | return GNUNET_YES; | ||
425 | |||
426 | // not contained according to bob's bloomfilter | ||
427 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
428 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, | ||
429 | &mutated_hash)) | ||
430 | return GNUNET_YES; | ||
431 | |||
432 | op->state->contained_elements_count++; | ||
433 | GNUNET_CONTAINER_multihashmap_put (op->state->contained_elements, | ||
434 | &ee->element_hash, ee, | ||
435 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
436 | |||
437 | // create our own bloomfilter with salt+1 | ||
438 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt+1, &mutated_hash); | ||
439 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, | ||
440 | &mutated_hash); | ||
441 | |||
442 | return GNUNET_YES; | ||
443 | } | ||
444 | |||
445 | /** | ||
446 | * Bob's version: | ||
447 | * | ||
448 | * fills the contained-elements hashmap with all relevant | ||
449 | * elements and adds their mutated hashes to our local bloomfilter | ||
450 | * | ||
451 | * @param cls closure | ||
452 | * @param key current key code | ||
453 | * @param value value in the hash map | ||
454 | * @return #GNUNET_YES if we should continue to | ||
455 | * iterate, | ||
456 | * #GNUNET_NO if not. | ||
457 | */ | ||
458 | static int | ||
459 | intersection_iterator_set_to_contained_bob (void *cls, | ||
460 | const struct GNUNET_HashCode *key, | ||
461 | void *value){ | ||
462 | struct ElementEntry *ee = value; | ||
463 | struct Operation *op = cls; | ||
464 | struct GNUNET_HashCode mutated_hash; | ||
465 | |||
466 | //only consider this element, if it is valid for us | ||
467 | if ((op->generation_created >= ee->generation_removed) | ||
468 | || (op->generation_created < ee->generation_added)) | ||
469 | return GNUNET_YES; | ||
470 | |||
471 | GNUNET_CONTAINER_multihashmap_put (op->state->contained_elements, | ||
472 | &ee->element_hash, ee, | ||
473 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
474 | |||
475 | op->state->contained_elements_count++; | ||
476 | |||
477 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
478 | |||
479 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, | ||
480 | &mutated_hash); | ||
481 | |||
482 | return GNUNET_YES; | ||
483 | } | ||
484 | |||
485 | /** | ||
486 | * removes element from a hashmap if it is not contained within the | ||
487 | * provided remote bloomfilter. | ||
488 | * | ||
489 | * @param cls closure | ||
490 | * @param key current key code | ||
491 | * @param value value in the hash map | ||
492 | * @return #GNUNET_YES if we should continue to | ||
493 | * iterate, | ||
494 | * #GNUNET_NO if not. | ||
495 | */ | ||
496 | static int | ||
497 | intersection_iterator_element_removal (void *cls, | ||
498 | const struct GNUNET_HashCode *key, | ||
499 | void *value){ | ||
500 | struct ElementEntry *ee = value; | ||
501 | struct Operation *op = cls; | ||
502 | struct GNUNET_HashCode mutated_hash; | ||
503 | |||
504 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
505 | |||
506 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, | ||
507 | &mutated_hash)){ | ||
508 | op->state->contained_elements_count--; | ||
509 | GNUNET_CONTAINER_multihashmap_remove (op->state->contained_elements, | ||
510 | &ee->element_hash, | ||
511 | ee); | ||
512 | } | ||
513 | |||
514 | return GNUNET_YES; | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * removes element from a hashmap if it is not contained within the | ||
519 | * provided remote bloomfilter. | ||
520 | * | ||
521 | * @param cls closure | ||
522 | * @param key current key code | ||
523 | * @param value value in the hash map | ||
524 | * @return #GNUNET_YES if we should continue to | ||
525 | * iterate, | ||
526 | * #GNUNET_NO if not. | ||
527 | */ | ||
528 | static int | ||
529 | intersection_iterator_create_bf (void *cls, | ||
530 | const struct GNUNET_HashCode *key, | ||
531 | void *value){ | ||
532 | struct ElementEntry *ee = value; | ||
533 | struct Operation *op = cls; | ||
534 | struct GNUNET_HashCode mutated_hash; | ||
535 | |||
536 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | ||
537 | |||
538 | GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, | ||
539 | &mutated_hash); | ||
540 | |||
541 | return GNUNET_YES; | ||
542 | } | ||
543 | |||
544 | |||
545 | /** | 676 | /** |
546 | * Accept an union operation request from a remote peer. | 677 | * Accept an union operation request from a remote peer. |
547 | * Only initializes the private operation state. | 678 | * Only initializes the private operation state. |
@@ -551,18 +682,33 @@ intersection_iterator_create_bf (void *cls, | |||
551 | static void | 682 | static void |
552 | intersection_accept (struct Operation *op) | 683 | intersection_accept (struct Operation *op) |
553 | { | 684 | { |
685 | struct OperationRequestMessage * context = 1; | ||
554 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "accepting set union operation\n"); | 686 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "accepting set union operation\n"); |
555 | op->state = GNUNET_new (struct OperationState); | ||
556 | 687 | ||
557 | op->state->contained_elements = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES); | 688 | op->state = GNUNET_new (struct OperationState); |
558 | op->state-> = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES); | 689 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES); |
559 | |||
560 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init(NULL, , GNUNET_CONSTANTS_BLOOMFILTER_K); | ||
561 | 690 | ||
562 | GNUNET_CONTAINER_multihashmap_iterate(op->spec->set->elements, | 691 | GNUNET_CONTAINER_multihashmap_iterate(op->spec->set->elements, |
563 | &intersection_iterator_set_to_contained_bob, | 692 | &iterator_element_count, |
564 | op); | 693 | op); |
565 | /* kick off the operation */ | 694 | |
695 | // if we have more elements than our peer, he should start | ||
696 | if (op->spec->element_count < op->state->my_elements_count){ | ||
697 | op->state->phase = PHASE_INITIAL; | ||
698 | send_element_count(op); | ||
699 | return; | ||
700 | } | ||
701 | |||
702 | // create a new bloomfilter in case we have fewer elements | ||
703 | op->state->phase = PHASE_BF_EXCHANGE; | ||
704 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, | ||
705 | GNUNET_CRYPTO_HASH_LENGTH, | ||
706 | GNUNET_CONSTANTS_BLOOMFILTER_K); | ||
707 | |||
708 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | ||
709 | &iterator_initialization, | ||
710 | op); | ||
711 | |||
566 | send_bloomfilter (op); | 712 | send_bloomfilter (op); |
567 | } | 713 | } |
568 | 714 | ||
@@ -632,8 +778,8 @@ intersection_remove (struct SetState *set_state, struct ElementEntry *element) | |||
632 | * GNUNET_OK otherwise | 778 | * GNUNET_OK otherwise |
633 | */ | 779 | */ |
634 | int | 780 | int |
635 | intersection_handle_p2p_message (struct OperationState *eo, | 781 | intersection_handle_p2p_message (struct Operation *op, |
636 | const struct GNUNET_MessageHeader *mh) | 782 | const struct GNUNET_MessageHeader *mh) |
637 | { | 783 | { |
638 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received p2p message (t: %u, s: %u)\n", | 784 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received p2p message (t: %u, s: %u)\n", |
639 | ntohs (mh->type), ntohs (mh->size)); | 785 | ntohs (mh->type), ntohs (mh->size)); |
@@ -642,15 +788,18 @@ intersection_handle_p2p_message (struct OperationState *eo, | |||
642 | /* this message handler is not active until after we received an | 788 | /* this message handler is not active until after we received an |
643 | * operation request message, thus the ops request is not handled here | 789 | * operation request message, thus the ops request is not handled here |
644 | */ | 790 | */ |
645 | case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF: | 791 | case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO: |
646 | handle_p2p_bf (eo, mh); | 792 | handle_p2p_element_info (op, mh); |
647 | break; | 793 | break; |
648 | case GNUNET_MESSAGE_TYPE_SET_P2P_DONE: | 794 | case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF: |
649 | handle_p2p_done (eo, mh); | 795 | handle_p2p_bf (op, mh); |
650 | break; | 796 | break; |
651 | default: | 797 | case GNUNET_MESSAGE_TYPE_SET_P2P_DONE: |
652 | /* something wrong with mesh's message handlers? */ | 798 | handle_p2p_done (op, mh); |
653 | GNUNET_assert (0); | 799 | break; |
800 | default: | ||
801 | /* something wrong with mesh's message handlers? */ | ||
802 | GNUNET_assert (0); | ||
654 | } | 803 | } |
655 | return GNUNET_OK; | 804 | return GNUNET_OK; |
656 | } | 805 | } |
@@ -693,7 +842,7 @@ finish_and_destroy (struct Operation *op) | |||
693 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending full result set\n"); | 842 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending full result set\n"); |
694 | GNUNET_assert (NULL == op->state->full_result_iter); | 843 | GNUNET_assert (NULL == op->state->full_result_iter); |
695 | op->state->full_result_iter = | 844 | op->state->full_result_iter = |
696 | GNUNET_CONTAINER_multihashmap32_iterator_create (op->state->contained_elements); | 845 | GNUNET_CONTAINER_multihashmap32_iterator_create (op->state->my_elements); |
697 | return; | 846 | return; |
698 | } | 847 | } |
699 | send_done_and_destroy (op); | 848 | send_done_and_destroy (op); |
@@ -748,11 +897,11 @@ intersection_op_cancel (struct Operation *op) | |||
748 | GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); | 897 | GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); |
749 | op->state->local_bf = NULL; | 898 | op->state->local_bf = NULL; |
750 | } | 899 | } |
751 | if (NULL != op->state->contained_elements) | 900 | if (NULL != op->state->my_elements) |
752 | { | 901 | { |
753 | // no need to free the elements, they are still part of the set | 902 | // no need to free the elements, they are still part of the set |
754 | GNUNET_CONTAINER_multihashmap_destroy (op->state->contained_elements); | 903 | GNUNET_CONTAINER_multihashmap_destroy (op->state->my_elements); |
755 | op->state->contained_elements = NULL; | 904 | op->state->my_elements = NULL; |
756 | } | 905 | } |
757 | GNUNET_free (op->state); | 906 | GNUNET_free (op->state); |
758 | op->state = NULL; | 907 | op->state = NULL; |
diff --git a/src/set/set_protocol.h b/src/set/set_protocol.h index 4741eb5c2..d37551d2e 100644 --- a/src/set/set_protocol.h +++ b/src/set/set_protocol.h | |||
@@ -50,6 +50,11 @@ struct OperationRequestMessage | |||
50 | uint32_t salt; | 50 | uint32_t salt; |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * For Intersection: my element count | ||
54 | */ | ||
55 | uint32_t element_count; | ||
56 | |||
57 | /** | ||
53 | * Application-specific identifier of the request. | 58 | * Application-specific identifier of the request. |
54 | */ | 59 | */ |
55 | struct GNUNET_HashCode app_id; | 60 | struct GNUNET_HashCode app_id; |
@@ -103,17 +108,21 @@ struct BFMessage | |||
103 | /** | 108 | /** |
104 | * mutator used with this bloomfilter. | 109 | * mutator used with this bloomfilter. |
105 | */ | 110 | */ |
106 | uint64_t sender_element_count; | 111 | uint32_t sender_element_count GNUNET_PACKED; |
107 | 112 | ||
108 | /** | 113 | /** |
109 | * mutator used with this bloomfilter. | 114 | * mutator used with this bloomfilter. |
110 | */ | 115 | */ |
111 | uint32_t sender_mutator; | 116 | uint32_t sender_mutator GNUNET_PACKED; |
112 | 117 | ||
113 | /** | 118 | /** |
114 | * the sender's bloomfilter | 119 | * Length of the bloomfilter data block |
120 | */ | ||
121 | uint32_t bloomfilter_length GNUNET_PACKED; | ||
122 | |||
123 | /** | ||
124 | * rest: the sender's bloomfilter | ||
115 | */ | 125 | */ |
116 | char sender_bf_data[GNUNET_CRYPTO_HASH_LENGTH]; | ||
117 | }; | 126 | }; |
118 | 127 | ||
119 | GNUNET_NETWORK_STRUCT_END | 128 | GNUNET_NETWORK_STRUCT_END |