diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-11-27 20:17:24 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-11-27 20:17:24 +0000 |
commit | f23525cfc0c0a8931db0b20b35c1aabbfbc5ac4e (patch) | |
tree | 3ef89bce9f65613c8f697c04b4280e14091d1ace /src/set | |
parent | 1dc3a88ad71d1ca99bed5d38977d69f88de3d253 (diff) | |
download | gnunet-f23525cfc0c0a8931db0b20b35c1aabbfbc5ac4e.tar.gz gnunet-f23525cfc0c0a8931db0b20b35c1aabbfbc5ac4e.zip |
use separate struct for just sending #elements in set, and check message size before casting
Diffstat (limited to 'src/set')
-rw-r--r-- | src/set/gnunet-service-set_intersection.c | 576 | ||||
-rw-r--r-- | src/set/gnunet-service-set_protocol.h | 23 | ||||
-rw-r--r-- | src/set/set.h | 9 |
3 files changed, 337 insertions, 271 deletions
diff --git a/src/set/gnunet-service-set_intersection.c b/src/set/gnunet-service-set_intersection.c index 749f2e98d..19d6498f5 100644 --- a/src/set/gnunet-service-set_intersection.c +++ b/src/set/gnunet-service-set_intersection.c | |||
@@ -31,6 +31,15 @@ | |||
31 | 31 | ||
32 | #define BLOOMFILTER_SIZE GNUNET_CRYPTO_HASH_LENGTH | 32 | #define BLOOMFILTER_SIZE GNUNET_CRYPTO_HASH_LENGTH |
33 | 33 | ||
34 | /** | ||
35 | * Calculate the size of the bloom filter. | ||
36 | * | ||
37 | * @param A | ||
38 | * @param B | ||
39 | * @param s | ||
40 | * @param k | ||
41 | * @return | ||
42 | */ | ||
34 | #define CALCULATE_BF_SIZE(A, B, s, k) \ | 43 | #define CALCULATE_BF_SIZE(A, B, s, k) \ |
35 | do { \ | 44 | do { \ |
36 | k = ceil(1 + log2((double) (2*B / (double) A)));\ | 45 | k = ceil(1 + log2((double) (2*B / (double) A)));\ |
@@ -38,6 +47,7 @@ | |||
38 | s = ceil((double) (A * k / log(2))); \ | 47 | s = ceil((double) (A * k / log(2))); \ |
39 | } while (0) | 48 | } while (0) |
40 | 49 | ||
50 | |||
41 | /** | 51 | /** |
42 | * Current phase we are in for a intersection operation. | 52 | * Current phase we are in for a intersection operation. |
43 | */ | 53 | */ |
@@ -48,11 +58,13 @@ enum IntersectionOperationPhase | |||
48 | * and is waiting for a bf or session end. | 58 | * and is waiting for a bf or session end. |
49 | */ | 59 | */ |
50 | PHASE_INITIAL, | 60 | PHASE_INITIAL, |
61 | |||
51 | /** | 62 | /** |
52 | * Bob has accepted the operation, Bob and Alice are now exchanging bfs | 63 | * Bob has accepted the operation, Bob and Alice are now exchanging bfs |
53 | * until one notices the their element count is equal | 64 | * until one notices the their element count is equal |
54 | */ | 65 | */ |
55 | PHASE_BF_EXCHANGE, | 66 | PHASE_BF_EXCHANGE, |
67 | |||
56 | /** | 68 | /** |
57 | * if both peers have an equal peercount, they enter this state for | 69 | * if both peers have an equal peercount, they enter this state for |
58 | * one more turn, to see if they actually have agreed on a correct set. | 70 | * one more turn, to see if they actually have agreed on a correct set. |
@@ -60,6 +72,7 @@ enum IntersectionOperationPhase | |||
60 | * it ends the the session | 72 | * it ends the the session |
61 | */ | 73 | */ |
62 | PHASE_MAYBE_FINISHED, | 74 | PHASE_MAYBE_FINISHED, |
75 | |||
63 | /** | 76 | /** |
64 | * The protocol is over. | 77 | * The protocol is over. |
65 | * Results may still have to be sent to the client. | 78 | * Results may still have to be sent to the client. |
@@ -84,7 +97,13 @@ struct OperationState | |||
84 | struct GNUNET_CONTAINER_BloomFilter *local_bf; | 97 | struct GNUNET_CONTAINER_BloomFilter *local_bf; |
85 | 98 | ||
86 | /** | 99 | /** |
87 | * Iterator for sending elements on the key to element mapping to the client. | 100 | * Remaining elements in the intersection operation. |
101 | * Maps element-id-hashes to 'elements in our set'. | ||
102 | */ | ||
103 | struct GNUNET_CONTAINER_MultiHashMap *my_elements; | ||
104 | |||
105 | /** | ||
106 | * Iterator for sending the final set of @e my_elements to the client. | ||
88 | */ | 107 | */ |
89 | struct GNUNET_CONTAINER_MultiHashMapIterator *full_result_iter; | 108 | struct GNUNET_CONTAINER_MultiHashMapIterator *full_result_iter; |
90 | 109 | ||
@@ -104,11 +123,6 @@ struct OperationState | |||
104 | char *bf_data; | 123 | char *bf_data; |
105 | 124 | ||
106 | /** | 125 | /** |
107 | * Maps element-id-hashes to 'elements in our set'. | ||
108 | */ | ||
109 | struct GNUNET_CONTAINER_MultiHashMap *my_elements; | ||
110 | |||
111 | /** | ||
112 | * Current element count contained within @e my_elements | 126 | * Current element count contained within @e my_elements |
113 | */ | 127 | */ |
114 | uint32_t my_element_count; | 128 | uint32_t my_element_count; |
@@ -143,6 +157,7 @@ struct OperationState | |||
143 | 157 | ||
144 | /** | 158 | /** |
145 | * Extra state required for efficient set intersection. | 159 | * Extra state required for efficient set intersection. |
160 | * Merely tracks the total number of elements. | ||
146 | */ | 161 | */ |
147 | struct SetState | 162 | struct SetState |
148 | { | 163 | { |
@@ -154,140 +169,113 @@ struct SetState | |||
154 | 169 | ||
155 | 170 | ||
156 | /** | 171 | /** |
157 | * Send a result message to the client indicating | 172 | * If applicable in the current operation mode, send a result message |
158 | * we removed an element | 173 | * to the client indicating we removed an element. |
159 | * | 174 | * |
160 | * @param op union operation | 175 | * @param op intersection operation |
161 | * @param element element to send | 176 | * @param element element to send |
162 | */ | 177 | */ |
163 | static void | 178 | static void |
164 | send_client_element (struct Operation *op, | 179 | send_client_removed_element (struct Operation *op, |
165 | struct GNUNET_SET_Element *element) | 180 | struct GNUNET_SET_Element *element) |
166 | { | 181 | { |
167 | struct GNUNET_MQ_Envelope *ev; | 182 | struct GNUNET_MQ_Envelope *ev; |
168 | struct GNUNET_SET_ResultMessage *rm; | 183 | struct GNUNET_SET_ResultMessage *rm; |
169 | 184 | ||
185 | if (GNUNET_SET_RESULT_REMOVED != op->spec->result_mode) | ||
186 | return; /* Wrong mode for transmitting removed elements */ | ||
170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 187 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
171 | "sending removed element (size %u) to client\n", | 188 | "Sending removed element (size %u) to client\n", |
172 | element->size); | 189 | element->size); |
173 | GNUNET_assert (0 != op->spec->client_request_id); | 190 | GNUNET_assert (0 != op->spec->client_request_id); |
174 | ev = GNUNET_MQ_msg_extra (rm, element->size, GNUNET_MESSAGE_TYPE_SET_RESULT); | 191 | ev = GNUNET_MQ_msg_extra (rm, |
192 | element->size, | ||
193 | GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
175 | if (NULL == ev) | 194 | if (NULL == ev) |
176 | { | 195 | { |
177 | GNUNET_MQ_discard (ev); | ||
178 | GNUNET_break (0); | 196 | GNUNET_break (0); |
179 | return; | 197 | return; |
180 | } | 198 | } |
181 | rm->result_status = htons (GNUNET_SET_STATUS_OK); | 199 | rm->result_status = htons (GNUNET_SET_STATUS_OK); |
182 | rm->request_id = htonl (op->spec->client_request_id); | 200 | rm->request_id = htonl (op->spec->client_request_id); |
183 | rm->element_type = element->element_type; | 201 | rm->element_type = element->element_type; |
184 | memcpy (&rm[1], element->data, element->size); | 202 | memcpy (&rm[1], |
185 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 203 | element->data, |
204 | element->size); | ||
205 | GNUNET_MQ_send (op->spec->set->client_mq, | ||
206 | ev); | ||
186 | } | 207 | } |
187 | 208 | ||
188 | 209 | ||
189 | /** | 210 | /** |
190 | * Alice's version: | 211 | * Fills the "my_elements" hashmap with all relevant elements and |
212 | * adds their mutated hashes to our local bloomfilter with mutator+1. | ||
191 | * | 213 | * |
192 | * fills the contained-elements hashmap with all relevant | 214 | * @param cls the `struct Operation *` we are performing |
193 | * elements and adds their mutated hashes to our local bloomfilter with mutator+1 | ||
194 | * | ||
195 | * @param cls closure | ||
196 | * @param key current key code | 215 | * @param key current key code |
197 | * @param value value in the hash map | 216 | * @param value the `struct ElementEntry *` from the hash map |
198 | * @return #GNUNET_YES if we should continue to | 217 | * @return #GNUNET_YES (we should continue to iterate) |
199 | * iterate, | ||
200 | * #GNUNET_NO if not. | ||
201 | */ | 218 | */ |
202 | static int | 219 | static int |
203 | iterator_initialization_by_alice (void *cls, | 220 | filtered_map_and_bf_initialization (void *cls, |
204 | const struct GNUNET_HashCode *key, | 221 | const struct GNUNET_HashCode *key, |
205 | void *value) | 222 | void *value) |
206 | { | 223 | { |
207 | struct ElementEntry *ee = value; | ||
208 | struct Operation *op = cls; | 224 | struct Operation *op = cls; |
225 | struct ElementEntry *ee = value; | ||
209 | struct GNUNET_HashCode mutated_hash; | 226 | struct GNUNET_HashCode mutated_hash; |
210 | 227 | ||
211 | //only consider this element, if it is valid for us | 228 | if ( (op->generation_created < ee->generation_removed) && |
212 | if ((op->generation_created < ee->generation_removed) | 229 | (op->generation_created >= ee->generation_added) ) |
213 | && (op->generation_created >= ee->generation_added)) | 230 | return GNUNET_YES; /* element not valid in our operation's generation */ |
214 | return GNUNET_YES; | ||
215 | 231 | ||
216 | // not contained according to bob's bloomfilter | 232 | /* Test if element is in Bob's bloomfilter */ |
217 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, | 233 | // FIXME: where does this salt come from!? |
218 | op->spec->salt, | 234 | GNUNET_BLOCK_mingle_hash (&ee->element_hash, |
219 | &mutated_hash); | 235 | op->spec->salt, |
220 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, | 236 | &mutated_hash); |
221 | &mutated_hash)){ | 237 | if (GNUNET_NO == |
222 | if (GNUNET_SET_RESULT_REMOVED == op->spec->result_mode) | 238 | GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, |
223 | send_client_element (op, &ee->element); | 239 | &mutated_hash)) |
240 | { | ||
241 | /* remove this element */ | ||
242 | send_client_removed_element (op, | ||
243 | &ee->element); | ||
224 | return GNUNET_YES; | 244 | return GNUNET_YES; |
225 | } | 245 | } |
226 | |||
227 | op->state->my_element_count++; | 246 | op->state->my_element_count++; |
228 | GNUNET_assert (GNUNET_YES == | 247 | GNUNET_break (GNUNET_YES == |
229 | GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, | 248 | GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, |
230 | &ee->element_hash, ee, | 249 | &ee->element_hash, |
231 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 250 | ee, |
232 | 251 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | |
233 | return GNUNET_YES; | ||
234 | } | ||
235 | |||
236 | |||
237 | /** | ||
238 | * fills the contained-elements hashmap with all relevant | ||
239 | * elements and adds their mutated hashes to our local bloomfilter | ||
240 | * | ||
241 | * @param cls closure | ||
242 | * @param key current key code | ||
243 | * @param value value in the hash map | ||
244 | * @return #GNUNET_YES if we should continue to | ||
245 | * iterate, | ||
246 | * #GNUNET_NO if not. | ||
247 | */ | ||
248 | static int | ||
249 | iterator_initialization (void *cls, | ||
250 | const struct GNUNET_HashCode *key, | ||
251 | void *value) | ||
252 | { | ||
253 | struct ElementEntry *ee = value; | ||
254 | struct Operation *op = cls; | ||
255 | 252 | ||
256 | //only consider this element, if it is valid for us | ||
257 | if ((op->generation_created < ee->generation_removed) | ||
258 | && (op->generation_created >= ee->generation_added)) | ||
259 | return GNUNET_YES; | ||
260 | |||
261 | GNUNET_assert (GNUNET_YES == | ||
262 | GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, | ||
263 | &ee->element_hash, ee, | ||
264 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
265 | return GNUNET_YES; | 253 | return GNUNET_YES; |
266 | } | 254 | } |
267 | 255 | ||
268 | 256 | ||
269 | /** | 257 | /** |
270 | * removes element from a hashmap if it is not contained within the | 258 | * Removes elements from our hashmap if they are not contained within the |
271 | * provided remote bloomfilter. Then, fill our new bloomfilter. | 259 | * provided remote bloomfilter. |
272 | * | 260 | * |
273 | * @param cls closure | 261 | * @param cls closure with the `struct Operation *` |
274 | * @param key current key code | 262 | * @param key current key code |
275 | * @param value value in the hash map | 263 | * @param value value in the hash map |
276 | * @return #GNUNET_YES if we should continue to | 264 | * @return #GNUNET_YES (we should continue to iterate) |
277 | * iterate, | ||
278 | * #GNUNET_NO if not. | ||
279 | */ | 265 | */ |
280 | static int | 266 | static int |
281 | iterator_bf_reduce (void *cls, | 267 | iterator_bf_reduce (void *cls, |
282 | const struct GNUNET_HashCode *key, | 268 | const struct GNUNET_HashCode *key, |
283 | void *value) | 269 | void *value) |
284 | { | 270 | { |
285 | struct ElementEntry *ee = value; | ||
286 | struct Operation *op = cls; | 271 | struct Operation *op = cls; |
272 | struct ElementEntry *ee = value; | ||
287 | struct GNUNET_HashCode mutated_hash; | 273 | struct GNUNET_HashCode mutated_hash; |
288 | 274 | ||
289 | GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); | 275 | // FIXME: where does this salt come from!? |
290 | 276 | GNUNET_BLOCK_mingle_hash (&ee->element_hash, | |
277 | op->spec->salt, | ||
278 | &mutated_hash); | ||
291 | if (GNUNET_NO == | 279 | if (GNUNET_NO == |
292 | GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, | 280 | GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, |
293 | &mutated_hash)) | 281 | &mutated_hash)) |
@@ -297,33 +285,31 @@ iterator_bf_reduce (void *cls, | |||
297 | GNUNET_CONTAINER_multihashmap_remove (op->state->my_elements, | 285 | GNUNET_CONTAINER_multihashmap_remove (op->state->my_elements, |
298 | &ee->element_hash, | 286 | &ee->element_hash, |
299 | ee)); | 287 | ee)); |
300 | if (GNUNET_SET_RESULT_REMOVED == op->spec->result_mode) | 288 | send_client_removed_element (op, |
301 | send_client_element (op, &ee->element); | 289 | &ee->element); |
302 | } | 290 | } |
303 | |||
304 | return GNUNET_YES; | 291 | return GNUNET_YES; |
305 | } | 292 | } |
306 | 293 | ||
307 | 294 | ||
308 | /** | 295 | /** |
309 | * Create a bloomfilter based on the elements given | 296 | * Create initial bloomfilter based on all the elements given. |
310 | * | 297 | * |
311 | * @param cls closure | 298 | * @param cls the `struct Operation *` |
312 | * @param key current key code | 299 | * @param key current key code |
313 | * @param value value in the hash map | 300 | * @param value the `struct ElementEntry` to process |
314 | * @return #GNUNET_YES if we should continue to | 301 | * @return #GNUNET_YES (we should continue to iterate) |
315 | * iterate, | ||
316 | * #GNUNET_NO if not. | ||
317 | */ | 302 | */ |
318 | static int | 303 | static int |
319 | iterator_bf_create (void *cls, | 304 | iterator_bf_create (void *cls, |
320 | const struct GNUNET_HashCode *key, | 305 | const struct GNUNET_HashCode *key, |
321 | void *value) | 306 | void *value) |
322 | { | 307 | { |
323 | struct ElementEntry *ee = value; | ||
324 | struct Operation *op = cls; | 308 | struct Operation *op = cls; |
309 | struct ElementEntry *ee = value; | ||
325 | struct GNUNET_HashCode mutated_hash; | 310 | struct GNUNET_HashCode mutated_hash; |
326 | 311 | ||
312 | // FIXME: where does this salt come from!? | ||
327 | GNUNET_BLOCK_mingle_hash (&ee->element_hash, | 313 | GNUNET_BLOCK_mingle_hash (&ee->element_hash, |
328 | op->spec->salt, | 314 | op->spec->salt, |
329 | &mutated_hash); | 315 | &mutated_hash); |
@@ -334,7 +320,7 @@ iterator_bf_create (void *cls, | |||
334 | 320 | ||
335 | 321 | ||
336 | /** | 322 | /** |
337 | * Inform the client that the union operation has failed, | 323 | * Inform the client that the intersection operation has failed, |
338 | * and proceed to destroy the evaluate operation. | 324 | * and proceed to destroy the evaluate operation. |
339 | * | 325 | * |
340 | * @param op the intersection operation to fail | 326 | * @param op the intersection operation to fail |
@@ -345,23 +331,35 @@ fail_intersection_operation (struct Operation *op) | |||
345 | struct GNUNET_MQ_Envelope *ev; | 331 | struct GNUNET_MQ_Envelope *ev; |
346 | struct GNUNET_SET_ResultMessage *msg; | 332 | struct GNUNET_SET_ResultMessage *msg; |
347 | 333 | ||
348 | if (op->state->my_elements) | 334 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
335 | "Intersection operation failed\n"); | ||
336 | if (NULL != op->state->my_elements) | ||
349 | { | 337 | { |
350 | GNUNET_CONTAINER_multihashmap_destroy(op->state->my_elements); | 338 | GNUNET_CONTAINER_multihashmap_destroy (op->state->my_elements); |
351 | op->state->my_elements = NULL; | 339 | op->state->my_elements = NULL; |
352 | } | 340 | } |
353 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 341 | ev = GNUNET_MQ_msg (msg, |
354 | "intersection operation failed\n"); | 342 | GNUNET_MESSAGE_TYPE_SET_RESULT); |
355 | |||
356 | ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
357 | msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); | 343 | msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); |
358 | msg->request_id = htonl (op->spec->client_request_id); | 344 | msg->request_id = htonl (op->spec->client_request_id); |
359 | msg->element_type = htons (0); | 345 | msg->element_type = htons (0); |
360 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 346 | GNUNET_MQ_send (op->spec->set->client_mq, |
361 | _GSS_operation_destroy (op, GNUNET_YES); | 347 | ev); |
348 | _GSS_operation_destroy (op, | ||
349 | GNUNET_YES); | ||
362 | } | 350 | } |
363 | 351 | ||
364 | 352 | ||
353 | |||
354 | |||
355 | |||
356 | |||
357 | |||
358 | /** | ||
359 | * | ||
360 | * @param op | ||
361 | * @param offset | ||
362 | */ | ||
365 | static void | 363 | static void |
366 | send_bloomfilter_multipart (struct Operation *op, | 364 | send_bloomfilter_multipart (struct Operation *op, |
367 | uint32_t offset) | 365 | uint32_t offset) |
@@ -396,10 +394,8 @@ send_bloomfilter_multipart (struct Operation *op, | |||
396 | 394 | ||
397 | 395 | ||
398 | /** | 396 | /** |
399 | * Send a bloomfilter to our peer. | 397 | * Send a bloomfilter to our peer. After the result done message has |
400 | * that the operation is over. | 398 | * been sent to the client, destroy the evaluate operation. |
401 | * After the result done message has been sent to the client, | ||
402 | * destroy the evaluate operation. | ||
403 | * | 399 | * |
404 | * @param op intersection operation | 400 | * @param op intersection operation |
405 | */ | 401 | */ |
@@ -411,7 +407,7 @@ send_bloomfilter (struct Operation *op) | |||
411 | uint32_t bf_size; | 407 | uint32_t bf_size; |
412 | uint32_t bf_elementbits; | 408 | uint32_t bf_elementbits; |
413 | uint32_t chunk_size; | 409 | uint32_t chunk_size; |
414 | struct GNUNET_CONTAINER_BloomFilter * local_bf; | 410 | struct GNUNET_CONTAINER_BloomFilter *local_bf; |
415 | 411 | ||
416 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
417 | "sending bf of size %u\n"); | 413 | "sending bf of size %u\n"); |
@@ -435,7 +431,9 @@ send_bloomfilter (struct Operation *op) | |||
435 | { | 431 | { |
436 | // singlepart | 432 | // singlepart |
437 | chunk_size = bf_size; | 433 | chunk_size = bf_size; |
438 | ev = GNUNET_MQ_msg_extra (msg, chunk_size, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); | 434 | ev = GNUNET_MQ_msg_extra (msg, |
435 | chunk_size, | ||
436 | GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); | ||
439 | GNUNET_assert (GNUNET_SYSERR != | 437 | GNUNET_assert (GNUNET_SYSERR != |
440 | GNUNET_CONTAINER_bloomfilter_get_raw_data (local_bf, | 438 | GNUNET_CONTAINER_bloomfilter_get_raw_data (local_bf, |
441 | (char*)&msg[1], | 439 | (char*)&msg[1], |
@@ -445,7 +443,9 @@ send_bloomfilter (struct Operation *op) | |||
445 | { | 443 | { |
446 | //multipart | 444 | //multipart |
447 | chunk_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct BFMessage); | 445 | chunk_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct BFMessage); |
448 | ev = GNUNET_MQ_msg_extra (msg, chunk_size, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); | 446 | ev = GNUNET_MQ_msg_extra (msg, |
447 | chunk_size, | ||
448 | GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); | ||
449 | op->state->bf_data = (char *) GNUNET_malloc (bf_size); | 449 | op->state->bf_data = (char *) GNUNET_malloc (bf_size); |
450 | GNUNET_assert (GNUNET_SYSERR != | 450 | GNUNET_assert (GNUNET_SYSERR != |
451 | GNUNET_CONTAINER_bloomfilter_get_raw_data (local_bf, | 451 | GNUNET_CONTAINER_bloomfilter_get_raw_data (local_bf, |
@@ -482,57 +482,65 @@ send_client_done_and_destroy (void *cls) | |||
482 | struct GNUNET_MQ_Envelope *ev; | 482 | struct GNUNET_MQ_Envelope *ev; |
483 | struct GNUNET_SET_ResultMessage *rm; | 483 | struct GNUNET_SET_ResultMessage *rm; |
484 | 484 | ||
485 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); | 485 | ev = GNUNET_MQ_msg (rm, |
486 | GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
486 | rm->request_id = htonl (op->spec->client_request_id); | 487 | rm->request_id = htonl (op->spec->client_request_id); |
487 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); | 488 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); |
488 | rm->element_type = htons (0); | 489 | rm->element_type = htons (0); |
489 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 490 | GNUNET_MQ_send (op->spec->set->client_mq, |
490 | _GSS_operation_destroy (op, GNUNET_YES); | 491 | ev); |
492 | _GSS_operation_destroy (op, | ||
493 | GNUNET_YES); | ||
491 | } | 494 | } |
492 | 495 | ||
493 | 496 | ||
494 | /** | 497 | /** |
495 | * Send all elements in the full result iterator. | 498 | * Send all elements in the full result iterator. |
496 | * | 499 | * |
497 | * @param cls operation | 500 | * @param cls the `struct Operation *` |
498 | */ | 501 | */ |
499 | static void | 502 | static void |
500 | send_remaining_elements (void *cls) | 503 | send_remaining_elements (void *cls) |
501 | { | 504 | { |
502 | struct Operation *op = cls; | 505 | struct Operation *op = cls; |
503 | struct ElementEntry *remaining; //TODO rework this, key entry does not exist here | 506 | const void *nxt; |
507 | const struct ElementEntry *ee; | ||
504 | struct GNUNET_MQ_Envelope *ev; | 508 | struct GNUNET_MQ_Envelope *ev; |
505 | struct GNUNET_SET_ResultMessage *rm; | 509 | struct GNUNET_SET_ResultMessage *rm; |
506 | struct GNUNET_SET_Element *element; | 510 | const struct GNUNET_SET_Element *element; |
507 | int res; | 511 | int res; |
508 | 512 | ||
509 | res = GNUNET_CONTAINER_multihashmap_iterator_next (op->state->full_result_iter, | 513 | res = GNUNET_CONTAINER_multihashmap_iterator_next (op->state->full_result_iter, |
510 | NULL, | 514 | NULL, |
511 | (const void **) &remaining); | 515 | &nxt); |
512 | if (GNUNET_NO == res) | 516 | if (GNUNET_NO == res) |
513 | { | 517 | { |
514 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 518 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
515 | "sending done and destroy because iterator ran out\n"); | 519 | "Sending done and destroy because iterator ran out\n"); |
516 | send_client_done_and_destroy (op); | 520 | send_client_done_and_destroy (op); |
517 | return; | 521 | return; |
518 | } | 522 | } |
519 | 523 | ee = nxt; | |
520 | element = &remaining->element; | 524 | element = &ee->element; |
521 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 525 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
522 | "sending element (size %u) to client (full set)\n", | 526 | "Sending element (size %u) to client (full set)\n", |
523 | element->size); | 527 | element->size); |
524 | GNUNET_assert (0 != op->spec->client_request_id); | 528 | GNUNET_assert (0 != op->spec->client_request_id); |
525 | 529 | ev = GNUNET_MQ_msg_extra (rm, | |
526 | ev = GNUNET_MQ_msg_extra (rm, element->size, GNUNET_MESSAGE_TYPE_SET_RESULT); | 530 | element->size, |
531 | GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
527 | GNUNET_assert (NULL != ev); | 532 | GNUNET_assert (NULL != ev); |
528 | |||
529 | rm->result_status = htons (GNUNET_SET_STATUS_OK); | 533 | rm->result_status = htons (GNUNET_SET_STATUS_OK); |
530 | rm->request_id = htonl (op->spec->client_request_id); | 534 | rm->request_id = htonl (op->spec->client_request_id); |
531 | rm->element_type = element->element_type; | 535 | rm->element_type = element->element_type; |
532 | memcpy (&rm[1], element->data, element->size); | 536 | memcpy (&rm[1], |
533 | 537 | element->data, | |
534 | GNUNET_MQ_notify_sent (ev, send_remaining_elements, op); | 538 | element->size); |
535 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 539 | GNUNET_MQ_notify_sent (ev, |
540 | &send_remaining_elements, | ||
541 | op); | ||
542 | GNUNET_MQ_send (op->spec->set->client_mq, | ||
543 | ev); | ||
536 | } | 544 | } |
537 | 545 | ||
538 | 546 | ||
@@ -558,7 +566,7 @@ send_peer_done (struct Operation *op) | |||
558 | 566 | ||
559 | 567 | ||
560 | /** | 568 | /** |
561 | * Process a Bloomfilter once we got all the chunks | 569 | * Process a Bloomfilter once we got all the chunks. |
562 | * | 570 | * |
563 | * @param op the intersection operation | 571 | * @param op the intersection operation |
564 | */ | 572 | */ |
@@ -573,16 +581,18 @@ process_bf (struct Operation *op) | |||
573 | switch (op->state->phase) | 581 | switch (op->state->phase) |
574 | { | 582 | { |
575 | case PHASE_INITIAL: | 583 | case PHASE_INITIAL: |
576 | // If we are ot our first msg | 584 | /* This is the first BF being sent, build our |
577 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (op->state->my_element_count, GNUNET_YES); | 585 | initial map with filtering in place */ |
578 | 586 | op->state->my_elements | |
587 | = GNUNET_CONTAINER_multihashmap_create (op->spec->remote_element_count, | ||
588 | GNUNET_YES); | ||
579 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | 589 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, |
580 | &iterator_initialization_by_alice, | 590 | &filtered_map_and_bf_initialization, |
581 | op); | 591 | op); |
582 | break; | 592 | break; |
583 | case PHASE_BF_EXCHANGE: | 593 | case PHASE_BF_EXCHANGE: |
584 | case PHASE_MAYBE_FINISHED: | 594 | case PHASE_MAYBE_FINISHED: |
585 | // if we are bob or alice and are continuing operation | 595 | /* Update our set by reduction */ |
586 | GNUNET_CONTAINER_multihashmap_iterate (op->state->my_elements, | 596 | GNUNET_CONTAINER_multihashmap_iterate (op->state->my_elements, |
587 | &iterator_bf_reduce, | 597 | &iterator_bf_reduce, |
588 | op); | 598 | op); |
@@ -626,7 +636,8 @@ process_bf (struct Operation *op) | |||
626 | * @param mh the header of the message | 636 | * @param mh the header of the message |
627 | */ | 637 | */ |
628 | static void | 638 | static void |
629 | handle_p2p_bf_part (void *cls, const struct GNUNET_MessageHeader *mh) | 639 | handle_p2p_bf_part (void *cls, |
640 | const struct GNUNET_MessageHeader *mh) | ||
630 | { | 641 | { |
631 | struct Operation *op = cls; | 642 | struct Operation *op = cls; |
632 | const struct BFPart *msg = (const struct BFPart *) mh; | 643 | const struct BFPart *msg = (const struct BFPart *) mh; |
@@ -716,7 +727,37 @@ handle_p2p_bf (void *cls, | |||
716 | 727 | ||
717 | 728 | ||
718 | /** | 729 | /** |
719 | * Handle an BF message from a remote peer. | 730 | * Fills the "my_elements" hashmap with the initial set of |
731 | * (non-deleted) elements from the set of the specification. | ||
732 | * | ||
733 | * @param cls closure with the `struct Operation *` | ||
734 | * @param key current key code for the element | ||
735 | * @param value value in the hash map with the `struct ElementEntry *` | ||
736 | * @return #GNUNET_YES (we should continue to iterate) | ||
737 | */ | ||
738 | static int | ||
739 | initialize_map (void *cls, | ||
740 | const struct GNUNET_HashCode *key, | ||
741 | void *value) | ||
742 | { | ||
743 | struct ElementEntry *ee = value; | ||
744 | struct Operation *op = cls; | ||
745 | |||
746 | if ( (op->generation_created < ee->generation_removed) && | ||
747 | (op->generation_created >= ee->generation_added) ) | ||
748 | return GNUNET_YES; /* element not live in operation's generation */ | ||
749 | GNUNET_break (GNUNET_YES == | ||
750 | GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, | ||
751 | &ee->element_hash, | ||
752 | ee, | ||
753 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
754 | return GNUNET_YES; | ||
755 | } | ||
756 | |||
757 | |||
758 | /** | ||
759 | * Handle the initial `struct IntersectionElementInfoMessage` from a | ||
760 | * remote peer. | ||
720 | * | 761 | * |
721 | * @param cls the intersection operation | 762 | * @param cls the intersection operation |
722 | * @param mh the header of the message | 763 | * @param mh the header of the message |
@@ -726,13 +767,20 @@ handle_p2p_element_info (void *cls, | |||
726 | const struct GNUNET_MessageHeader *mh) | 767 | const struct GNUNET_MessageHeader *mh) |
727 | { | 768 | { |
728 | struct Operation *op = cls; | 769 | struct Operation *op = cls; |
729 | const struct BFMessage *msg = (const struct BFMessage *) mh; | 770 | const struct IntersectionElementInfoMessage *msg; |
730 | 771 | ||
731 | op->spec->remote_element_count = ntohl(msg->sender_element_count); | 772 | if (ntohs (mh->size) != sizeof (struct IntersectionElementInfoMessage)) |
732 | if ((op->state->phase != PHASE_INITIAL) | 773 | { |
733 | || (op->state->my_element_count > op->spec->remote_element_count) | 774 | GNUNET_break_op (0); |
734 | || (0 == op->state->my_element_count) | 775 | fail_intersection_operation(op); |
735 | || (0 == op->spec->remote_element_count)) | 776 | return; |
777 | } | ||
778 | msg = (const struct IntersectionElementInfoMessage *) mh; | ||
779 | op->spec->remote_element_count = ntohl (msg->sender_element_count); | ||
780 | if ( (PHASE_INITIAL != op->state->phase) || | ||
781 | (op->state->my_element_count > op->spec->remote_element_count) || | ||
782 | (0 == op->state->my_element_count) || | ||
783 | (0 == op->spec->remote_element_count) ) | ||
736 | { | 784 | { |
737 | GNUNET_break_op (0); | 785 | GNUNET_break_op (0); |
738 | fail_intersection_operation(op); | 786 | fail_intersection_operation(op); |
@@ -740,12 +788,12 @@ handle_p2p_element_info (void *cls, | |||
740 | } | 788 | } |
741 | 789 | ||
742 | op->state->phase = PHASE_BF_EXCHANGE; | 790 | op->state->phase = PHASE_BF_EXCHANGE; |
743 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | 791 | // FIXME... -- why a new map here!? |
744 | 792 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, | |
793 | GNUNET_YES); | ||
745 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | 794 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, |
746 | &iterator_initialization, | 795 | &initialize_map, // FIXME: filtering!? |
747 | op); | 796 | op); |
748 | |||
749 | GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); | 797 | GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); |
750 | op->state->remote_bf = NULL; | 798 | op->state->remote_bf = NULL; |
751 | 799 | ||
@@ -765,26 +813,21 @@ static void | |||
765 | send_element_count (struct Operation *op) | 813 | send_element_count (struct Operation *op) |
766 | { | 814 | { |
767 | struct GNUNET_MQ_Envelope *ev; | 815 | struct GNUNET_MQ_Envelope *ev; |
768 | struct BFMessage *msg; | 816 | struct IntersectionElementInfoMessage *msg; |
769 | 817 | ||
770 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 818 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
771 | "sending element count (bf_msg)\n"); | 819 | "Sending our element count (bf_msg)\n"); |
772 | 820 | ev = GNUNET_MQ_msg (msg, | |
773 | // just send our element count, as the other peer must start | 821 | GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO); |
774 | ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO); | ||
775 | msg->sender_element_count = htonl (op->state->my_element_count); | 822 | msg->sender_element_count = htonl (op->state->my_element_count); |
776 | msg->bloomfilter_length = htonl (0); | ||
777 | msg->sender_mutator = htonl (0); | ||
778 | |||
779 | GNUNET_MQ_send (op->mq, ev); | 823 | GNUNET_MQ_send (op->mq, ev); |
780 | } | 824 | } |
781 | 825 | ||
782 | 826 | ||
783 | /** | 827 | /** |
784 | * Send a result message to the client indicating | 828 | * Send a result message to the client indicating that the operation |
785 | * that the operation is over. | 829 | * is over. After the result done message has been sent to the |
786 | * After the result done message has been sent to the client, | 830 | * client, destroy the evaluate operation. |
787 | * destroy the evaluate operation. | ||
788 | * | 831 | * |
789 | * @param op intersection operation | 832 | * @param op intersection operation |
790 | */ | 833 | */ |
@@ -796,9 +839,9 @@ finish_and_destroy (struct Operation *op) | |||
796 | if (GNUNET_SET_RESULT_FULL == op->spec->result_mode) | 839 | if (GNUNET_SET_RESULT_FULL == op->spec->result_mode) |
797 | { | 840 | { |
798 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 841 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
799 | "sending full result set\n"); | 842 | "Sending full result set\n"); |
800 | op->state->full_result_iter = | 843 | op->state->full_result_iter |
801 | GNUNET_CONTAINER_multihashmap_iterator_create (op->state->my_elements); | 844 | = GNUNET_CONTAINER_multihashmap_iterator_create (op->state->my_elements); |
802 | send_remaining_elements (op); | 845 | send_remaining_elements (op); |
803 | return; | 846 | return; |
804 | } | 847 | } |
@@ -809,7 +852,7 @@ finish_and_destroy (struct Operation *op) | |||
809 | /** | 852 | /** |
810 | * Handle a done message from a remote peer | 853 | * Handle a done message from a remote peer |
811 | * | 854 | * |
812 | * @param cls the union operation | 855 | * @param cls the intersection operation |
813 | * @param mh the message | 856 | * @param mh the message |
814 | */ | 857 | */ |
815 | static void | 858 | static void |
@@ -822,19 +865,17 @@ handle_p2p_done (void *cls, | |||
822 | (op->state->phase = PHASE_MAYBE_FINISHED) ) | 865 | (op->state->phase = PHASE_MAYBE_FINISHED) ) |
823 | { | 866 | { |
824 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 867 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
825 | "got final DONE\n"); | 868 | "Got final DONE\n"); |
826 | |||
827 | finish_and_destroy (op); | 869 | finish_and_destroy (op); |
828 | return; | 870 | return; |
829 | } | 871 | } |
830 | |||
831 | GNUNET_break_op (0); | 872 | GNUNET_break_op (0); |
832 | fail_intersection_operation (op); | 873 | fail_intersection_operation (op); |
833 | } | 874 | } |
834 | 875 | ||
835 | 876 | ||
836 | /** | 877 | /** |
837 | * Initiate a set union operation with a remote peer. | 878 | * Initiate a set intersection operation with a remote peer. |
838 | * | 879 | * |
839 | * @param op operation that is created, should be initialized to | 880 | * @param op operation that is created, should be initialized to |
840 | * begin the evaluation | 881 | * begin the evaluation |
@@ -861,119 +902,66 @@ intersection_evaluate (struct Operation *op, | |||
861 | opaque_context); | 902 | opaque_context); |
862 | if (NULL == ev) | 903 | if (NULL == ev) |
863 | { | 904 | { |
864 | /* the context message is too large */ | 905 | /* the context message is too large!? */ |
865 | GNUNET_break (0); | 906 | GNUNET_break (0); |
866 | GNUNET_SERVER_client_disconnect (op->spec->set->client); | 907 | GNUNET_SERVER_client_disconnect (op->spec->set->client); |
867 | return; | 908 | return; |
868 | } | 909 | } |
869 | msg->operation = htonl (GNUNET_SET_OPERATION_INTERSECTION); | 910 | msg->operation = htonl (GNUNET_SET_OPERATION_INTERSECTION); |
870 | msg->app_id = op->spec->app_id; | 911 | msg->app_id = op->spec->app_id; |
912 | // FIXME: where does this 'salt' come from? | ||
871 | msg->salt = htonl (op->spec->salt); | 913 | msg->salt = htonl (op->spec->salt); |
872 | msg->element_count = htonl(op->state->my_element_count); | 914 | msg->element_count = htonl (op->state->my_element_count); |
873 | GNUNET_MQ_send (op->mq, ev); | 915 | GNUNET_MQ_send (op->mq, |
916 | ev); | ||
874 | if (NULL != opaque_context) | 917 | if (NULL != opaque_context) |
875 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 918 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
876 | "sent op request with context message\n"); | 919 | "Sent op request with context message\n"); |
877 | else | 920 | else |
878 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 921 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
879 | "sent op request without context message\n"); | 922 | "Sent op request without context message\n"); |
880 | } | 923 | } |
881 | 924 | ||
882 | 925 | ||
883 | /** | 926 | /** |
884 | * Accept an union operation request from a remote peer. | 927 | * Accept an intersection operation request from a remote peer. Only |
885 | * Only initializes the private operation state. | 928 | * initializes the private operation state. |
886 | * | 929 | * |
887 | * @param op operation that will be accepted as a union operation | 930 | * @param op operation that will be accepted as an intersection operation |
888 | */ | 931 | */ |
889 | static void | 932 | static void |
890 | intersection_accept (struct Operation *op) | 933 | intersection_accept (struct Operation *op) |
891 | { | 934 | { |
892 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 935 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
893 | "accepting set union operation\n"); | 936 | "Accepting set intersection operation\n"); |
894 | op->state = GNUNET_new (struct OperationState); | 937 | op->state = GNUNET_new (struct OperationState); |
895 | op->state->my_elements = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES); | 938 | op->state->my_element_count |
896 | op->state->my_element_count = op->spec->set->state->current_set_element_count; | 939 | = op->spec->set->state->current_set_element_count; |
897 | 940 | op->state->my_elements | |
898 | // if Alice (the peer) has more elements than Bob (us), she should start | 941 | = GNUNET_CONTAINER_multihashmap_create (GNUNET_MIN (op->state->my_element_count, |
899 | if (op->spec->remote_element_count < op->state->my_element_count){ | 942 | op->spec->remote_element_count), |
943 | GNUNET_YES); | ||
944 | if (op->spec->remote_element_count < op->state->my_element_count) | ||
945 | { | ||
946 | /* If the other peer (Alice) has fewer elements than us (Bob), | ||
947 | we just send the count as Alice should send the first BF */ | ||
900 | op->state->phase = PHASE_INITIAL; | 948 | op->state->phase = PHASE_INITIAL; |
901 | send_element_count(op); | 949 | send_element_count (op); |
902 | return; | 950 | return; |
903 | } | 951 | } |
904 | // create a new bloomfilter in case we have fewer elements | 952 | /* We have fewer elements, so we start with the BF */ |
905 | op->state->phase = PHASE_BF_EXCHANGE; | 953 | op->state->phase = PHASE_BF_EXCHANGE; |
906 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, | 954 | op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, |
907 | BLOOMFILTER_SIZE, | 955 | BLOOMFILTER_SIZE, |
908 | GNUNET_CONSTANTS_BLOOMFILTER_K); | 956 | GNUNET_CONSTANTS_BLOOMFILTER_K); |
909 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, | 957 | GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, |
910 | &iterator_initialization, | 958 | &initialize_map, |
911 | op); | 959 | op); |
912 | send_bloomfilter (op); | 960 | send_bloomfilter (op); |
913 | } | 961 | } |
914 | 962 | ||
915 | 963 | ||
916 | /** | 964 | /** |
917 | * Create a new set supporting the intersection operation | ||
918 | * | ||
919 | * @return the newly created set | ||
920 | */ | ||
921 | static struct SetState * | ||
922 | intersection_set_create () | ||
923 | { | ||
924 | struct SetState *set_state; | ||
925 | |||
926 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
927 | "intersection set created\n"); | ||
928 | set_state = GNUNET_new (struct SetState); | ||
929 | set_state->current_set_element_count = 0; | ||
930 | |||
931 | return set_state; | ||
932 | } | ||
933 | |||
934 | |||
935 | /** | ||
936 | * Add the element from the given element message to the set. | ||
937 | * | ||
938 | * @param set_state state of the set want to add to | ||
939 | * @param ee the element to add to the set | ||
940 | */ | ||
941 | static void | ||
942 | intersection_add (struct SetState *set_state, | ||
943 | struct ElementEntry *ee) | ||
944 | { | ||
945 | set_state->current_set_element_count++; | ||
946 | } | ||
947 | |||
948 | |||
949 | /** | ||
950 | * Destroy a set that supports the intersection operation | ||
951 | * | ||
952 | * @param set_state the set to destroy | ||
953 | */ | ||
954 | static void | ||
955 | intersection_set_destroy (struct SetState *set_state) | ||
956 | { | ||
957 | GNUNET_free (set_state); | ||
958 | } | ||
959 | |||
960 | |||
961 | /** | ||
962 | * Remove the element given in the element message from the set. | ||
963 | * | ||
964 | * @param set_state state of the set to remove from | ||
965 | * @param element set element to remove | ||
966 | */ | ||
967 | static void | ||
968 | intersection_remove (struct SetState *set_state, | ||
969 | struct ElementEntry *element) | ||
970 | { | ||
971 | GNUNET_assert(0 < set_state->current_set_element_count); | ||
972 | set_state->current_set_element_count--; | ||
973 | } | ||
974 | |||
975 | |||
976 | /** | ||
977 | * Dispatch messages for a intersection operation. | 965 | * Dispatch messages for a intersection operation. |
978 | * | 966 | * |
979 | * @param op the state of the intersection evaluate operation | 967 | * @param op the state of the intersection evaluate operation |
@@ -986,7 +974,7 @@ intersection_handle_p2p_message (struct Operation *op, | |||
986 | const struct GNUNET_MessageHeader *mh) | 974 | const struct GNUNET_MessageHeader *mh) |
987 | { | 975 | { |
988 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 976 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
989 | "received p2p message (t: %u, s: %u)\n", | 977 | "Received p2p message (t: %u, s: %u)\n", |
990 | ntohs (mh->type), ntohs (mh->size)); | 978 | ntohs (mh->type), ntohs (mh->size)); |
991 | switch (ntohs (mh->type)) | 979 | switch (ntohs (mh->type)) |
992 | { | 980 | { |
@@ -1014,7 +1002,9 @@ intersection_handle_p2p_message (struct Operation *op, | |||
1014 | 1002 | ||
1015 | 1003 | ||
1016 | /** | 1004 | /** |
1017 | * handler for peer-disconnects, notifies the client about the aborted operation | 1005 | * Handler for peer-disconnects, notifies the client about the aborted |
1006 | * operation. If we did not expect anything from the other peer, we | ||
1007 | * gracefully terminate the operation. | ||
1018 | * | 1008 | * |
1019 | * @param op the destroyed operation | 1009 | * @param op the destroyed operation |
1020 | */ | 1010 | */ |
@@ -1023,37 +1013,26 @@ intersection_peer_disconnect (struct Operation *op) | |||
1023 | { | 1013 | { |
1024 | if (PHASE_FINISHED != op->state->phase) | 1014 | if (PHASE_FINISHED != op->state->phase) |
1025 | { | 1015 | { |
1026 | struct GNUNET_MQ_Envelope *ev; | 1016 | fail_intersection_operation (op); |
1027 | struct GNUNET_SET_ResultMessage *msg; | ||
1028 | |||
1029 | ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
1030 | msg->request_id = htonl (op->spec->client_request_id); | ||
1031 | msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); | ||
1032 | msg->element_type = htons (0); | ||
1033 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | ||
1034 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1035 | "other peer disconnected prematurely\n"); | ||
1036 | _GSS_operation_destroy (op, GNUNET_YES); | ||
1037 | return; | 1017 | return; |
1038 | } | 1018 | } |
1039 | // else: the session has already been concluded | 1019 | /* the session has already been concluded */ |
1040 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1020 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1041 | "other peer disconnected (finished)\n"); | 1021 | "Other peer disconnected (finished)\n"); |
1042 | if (GNUNET_NO == op->state->client_done_sent) | 1022 | if (GNUNET_NO == op->state->client_done_sent) |
1043 | finish_and_destroy (op); | 1023 | finish_and_destroy (op); |
1044 | } | 1024 | } |
1045 | 1025 | ||
1046 | 1026 | ||
1047 | /** | 1027 | /** |
1048 | * Destroy the union operation. Only things specific to the union operation are destroyed. | 1028 | * Destroy the intersection operation. Only things specific to the |
1029 | * intersection operation are destroyed. | ||
1049 | * | 1030 | * |
1050 | * @param op union operation to destroy | 1031 | * @param op intersection operation to destroy |
1051 | */ | 1032 | */ |
1052 | static void | 1033 | static void |
1053 | intersection_op_cancel (struct Operation *op) | 1034 | intersection_op_cancel (struct Operation *op) |
1054 | { | 1035 | { |
1055 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1056 | "destroying intersection op\n"); | ||
1057 | /* check if the op was canceled twice */ | 1036 | /* check if the op was canceled twice */ |
1058 | GNUNET_assert (NULL != op->state); | 1037 | GNUNET_assert (NULL != op->state); |
1059 | if (NULL != op->state->remote_bf) | 1038 | if (NULL != op->state->remote_bf) |
@@ -1066,16 +1045,75 @@ intersection_op_cancel (struct Operation *op) | |||
1066 | GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); | 1045 | GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); |
1067 | op->state->local_bf = NULL; | 1046 | op->state->local_bf = NULL; |
1068 | } | 1047 | } |
1069 | /* if (NULL != op->state->my_elements) | 1048 | if (NULL != op->state->my_elements) |
1070 | { | 1049 | { |
1071 | // no need to free the elements, they are still part of the set | ||
1072 | GNUNET_CONTAINER_multihashmap_destroy (op->state->my_elements); | 1050 | GNUNET_CONTAINER_multihashmap_destroy (op->state->my_elements); |
1073 | op->state->my_elements = NULL; | 1051 | op->state->my_elements = NULL; |
1074 | }*/ | 1052 | } |
1075 | GNUNET_free (op->state); | 1053 | GNUNET_free (op->state); |
1076 | op->state = NULL; | 1054 | op->state = NULL; |
1077 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1055 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1078 | "destroying intersection op done\n"); | 1056 | "Destroying intersection op state done\n"); |
1057 | } | ||
1058 | |||
1059 | |||
1060 | /** | ||
1061 | * Create a new set supporting the intersection operation. | ||
1062 | * | ||
1063 | * @return the newly created set | ||
1064 | */ | ||
1065 | static struct SetState * | ||
1066 | intersection_set_create () | ||
1067 | { | ||
1068 | struct SetState *set_state; | ||
1069 | |||
1070 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1071 | "Intersection set created\n"); | ||
1072 | set_state = GNUNET_new (struct SetState); | ||
1073 | set_state->current_set_element_count = 0; | ||
1074 | |||
1075 | return set_state; | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /** | ||
1080 | * Add the element from the given element message to the set. | ||
1081 | * | ||
1082 | * @param set_state state of the set want to add to | ||
1083 | * @param ee the element to add to the set | ||
1084 | */ | ||
1085 | static void | ||
1086 | intersection_add (struct SetState *set_state, | ||
1087 | struct ElementEntry *ee) | ||
1088 | { | ||
1089 | set_state->current_set_element_count++; | ||
1090 | } | ||
1091 | |||
1092 | |||
1093 | /** | ||
1094 | * Destroy a set that supports the intersection operation | ||
1095 | * | ||
1096 | * @param set_state the set to destroy | ||
1097 | */ | ||
1098 | static void | ||
1099 | intersection_set_destroy (struct SetState *set_state) | ||
1100 | { | ||
1101 | GNUNET_free (set_state); | ||
1102 | } | ||
1103 | |||
1104 | |||
1105 | /** | ||
1106 | * Remove the element given in the element message from the set. | ||
1107 | * | ||
1108 | * @param set_state state of the set to remove from | ||
1109 | * @param element set element to remove | ||
1110 | */ | ||
1111 | static void | ||
1112 | intersection_remove (struct SetState *set_state, | ||
1113 | struct ElementEntry *element) | ||
1114 | { | ||
1115 | GNUNET_assert (0 < set_state->current_set_element_count); | ||
1116 | set_state->current_set_element_count--; | ||
1079 | } | 1117 | } |
1080 | 1118 | ||
1081 | 1119 | ||
diff --git a/src/set/gnunet-service-set_protocol.h b/src/set/gnunet-service-set_protocol.h index 73332b4c3..f02c61718 100644 --- a/src/set/gnunet-service-set_protocol.h +++ b/src/set/gnunet-service-set_protocol.h | |||
@@ -95,6 +95,29 @@ struct IBFMessage | |||
95 | }; | 95 | }; |
96 | 96 | ||
97 | 97 | ||
98 | /** | ||
99 | * During intersection, the first (and possibly second) message | ||
100 | * send it the number of elements in the set, to allow the peers | ||
101 | * to decide who should start with the Bloom filter. | ||
102 | */ | ||
103 | struct IntersectionElementInfoMessage | ||
104 | { | ||
105 | /** | ||
106 | * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO | ||
107 | */ | ||
108 | struct GNUNET_MessageHeader header; | ||
109 | |||
110 | /** | ||
111 | * mutator used with this bloomfilter. | ||
112 | */ | ||
113 | uint32_t sender_element_count GNUNET_PACKED; | ||
114 | |||
115 | }; | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Bloom filter messages exchanged for set intersection calculation. | ||
120 | */ | ||
98 | struct BFMessage | 121 | struct BFMessage |
99 | { | 122 | { |
100 | /** | 123 | /** |
diff --git a/src/set/set.h b/src/set/set.h index 944881b63..f688ccf72 100644 --- a/src/set/set.h +++ b/src/set/set.h | |||
@@ -188,6 +188,12 @@ struct GNUNET_SET_EvaluateMessage | |||
188 | }; | 188 | }; |
189 | 189 | ||
190 | 190 | ||
191 | /** | ||
192 | * Message sent by the service to the client to indicate an | ||
193 | * element that is removed (set intersection) or added | ||
194 | * (set union) or part of the final result, depending on | ||
195 | * options specified for the operation. | ||
196 | */ | ||
191 | struct GNUNET_SET_ResultMessage | 197 | struct GNUNET_SET_ResultMessage |
192 | { | 198 | { |
193 | /** | 199 | /** |
@@ -207,8 +213,7 @@ struct GNUNET_SET_ResultMessage | |||
207 | uint16_t result_status GNUNET_PACKED; | 213 | uint16_t result_status GNUNET_PACKED; |
208 | 214 | ||
209 | /** | 215 | /** |
210 | * Type of the element attachted to the message, | 216 | * Type of the element attachted to the message, if any. |
211 | * if any. | ||
212 | */ | 217 | */ |
213 | uint16_t element_type GNUNET_PACKED; | 218 | uint16_t element_type GNUNET_PACKED; |
214 | 219 | ||