aboutsummaryrefslogtreecommitdiff
path: root/src/set
diff options
context:
space:
mode:
Diffstat (limited to 'src/set')
-rw-r--r--src/set/Makefile.am16
-rw-r--r--src/set/gnunet-service-set.c128
-rw-r--r--src/set/gnunet-service-set.h24
-rw-r--r--src/set/gnunet-service-set_protocol.h14
-rw-r--r--src/set/gnunet-service-set_union.c482
-rw-r--r--src/set/gnunet-set-profiler.c105
-rw-r--r--src/set/plugin_block_set_test.c123
-rw-r--r--src/set/set.h53
-rw-r--r--src/set/set_api.c27
-rw-r--r--src/set/test_set.conf1
-rw-r--r--src/set/test_set_api.c5
-rw-r--r--src/set/test_set_intersection_result_full.c4
-rw-r--r--src/set/test_set_union_result_symmetric.c4
13 files changed, 881 insertions, 105 deletions
diff --git a/src/set/Makefile.am b/src/set/Makefile.am
index 10f7ddc5d..cfe95bc1a 100644
--- a/src/set/Makefile.am
+++ b/src/set/Makefile.am
@@ -5,6 +5,8 @@ pkgcfgdir= $(pkgdatadir)/config.d/
5 5
6libexecdir= $(pkglibdir)/libexec/ 6libexecdir= $(pkglibdir)/libexec/
7 7
8plugindir = $(libdir)/gnunet
9
8pkgcfg_DATA = \ 10pkgcfg_DATA = \
9 set.conf 11 set.conf
10 12
@@ -112,5 +114,19 @@ test_set_union_copy_LDADD = \
112 $(top_builddir)/src/testing/libgnunettesting.la \ 114 $(top_builddir)/src/testing/libgnunettesting.la \
113 libgnunetset.la 115 libgnunetset.la
114 116
117plugin_LTLIBRARIES = \
118 libgnunet_plugin_block_set_test.la
119
120libgnunet_plugin_block_set_test_la_SOURCES = \
121 plugin_block_set_test.c
122libgnunet_plugin_block_set_test_la_LIBADD = \
123 $(top_builddir)/src/block/libgnunetblock.la \
124 $(top_builddir)/src/block/libgnunetblockgroup.la \
125 $(top_builddir)/src/util/libgnunetutil.la \
126 $(LTLIBINTL)
127libgnunet_plugin_block_set_test_la_LDFLAGS = \
128 $(GN_PLUGIN_LDFLAGS)
129
130
115EXTRA_DIST = \ 131EXTRA_DIST = \
116 test_set.conf 132 test_set.conf
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
index a545e8a06..b0f8b2091 100644
--- a/src/set/gnunet-service-set.c
+++ b/src/set/gnunet-service-set.c
@@ -223,6 +223,9 @@ listener_destroy (struct Listener *listener)
223 { 223 {
224 struct GNUNET_SERVICE_Client *client = listener->client; 224 struct GNUNET_SERVICE_Client *client = listener->client;
225 225
226 GNUNET_MQ_destroy (listener->client_mq);
227 listener->client_mq = NULL;
228
226 listener->client = NULL; 229 listener->client = NULL;
227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
228 "Disconnecting listener client\n"); 231 "Disconnecting listener client\n");
@@ -611,42 +614,6 @@ client_connect_cb (void *cls,
611 614
612 615
613/** 616/**
614 * Clean up after a client has disconnected
615 *
616 * @param cls closure, unused
617 * @param client the client to clean up after
618 * @param internal_cls our client-specific internal data structure
619 */
620static void
621client_disconnect_cb (void *cls,
622 struct GNUNET_SERVICE_Client *client,
623 void *internal_cls)
624{
625 struct Listener *listener;
626 struct Set *set;
627
628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
629 "client disconnected, cleaning up\n");
630 set = set_get (client);
631 if (NULL != set)
632 {
633 set->client = NULL;
634 set_destroy (set);
635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
636 "Client's set destroyed\n");
637 }
638 listener = listener_get (client);
639 if (NULL != listener)
640 {
641 listener->client = NULL;
642 listener_destroy (listener);
643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
644 "Client's listener destroyed\n");
645 }
646}
647
648
649/**
650 * Destroy an incoming request from a remote peer 617 * Destroy an incoming request from a remote peer
651 * 618 *
652 * @param incoming remote request to destroy 619 * @param incoming remote request to destroy
@@ -681,6 +648,52 @@ incoming_destroy (struct Operation *incoming)
681 648
682 649
683/** 650/**
651 * Clean up after a client has disconnected
652 *
653 * @param cls closure, unused
654 * @param client the client to clean up after
655 * @param internal_cls our client-specific internal data structure
656 */
657static void
658client_disconnect_cb (void *cls,
659 struct GNUNET_SERVICE_Client *client,
660 void *internal_cls)
661{
662 struct Set *set;
663
664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
665 "client disconnected, cleaning up\n");
666 set = set_get (client);
667 if (NULL != set)
668 {
669 set->client = NULL;
670 set_destroy (set);
671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
672 "Client's set destroyed\n");
673 }
674 struct Listener *listener = listener_get (client);
675 struct Operation *op = incoming_head;
676 if (NULL != listener)
677 {
678 /* destroy all incoming operations whose client just
679 * got destroyed */
680 while (NULL != op)
681 {
682 struct Operation *curr = op;
683 op = op->next;
684 if ( (GNUNET_YES == curr->is_incoming) &&
685 (curr->listener == listener) )
686 incoming_destroy (curr);
687 }
688 listener->client = NULL;
689 listener_destroy (listener);
690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
691 "Client's listener destroyed\n");
692 }
693}
694
695
696/**
684 * Suggest the given request to the listener. The listening client can 697 * Suggest the given request to the listener. The listening client can
685 * then accept or reject the remote request. 698 * then accept or reject the remote request.
686 * 699 *
@@ -781,7 +794,7 @@ handle_incoming_msg (struct Operation *op,
781 listener = op->listener; 794 listener = op->listener;
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
783 "Received P2P operation request (op %u, port %s) for active listener\n", 796 "Received P2P operation request (op %u, port %s) for active listener\n",
784 ntohl (msg->operation), 797 (uint32_t) ntohl (msg->operation),
785 GNUNET_h2s (&listener->app_id)); 798 GNUNET_h2s (&listener->app_id));
786 incoming_suggest (op, 799 incoming_suggest (op,
787 listener); 800 listener);
@@ -1075,7 +1088,7 @@ handle_client_create_set (void *cls,
1075 1088
1076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1077 "Client created new set (operation %u)\n", 1090 "Client created new set (operation %u)\n",
1078 ntohl (msg->operation)); 1091 (uint32_t) ntohl (msg->operation));
1079 if (NULL != set_get (client)) 1092 if (NULL != set_get (client))
1080 { 1093 {
1081 /* There can only be one set per client */ 1094 /* There can only be one set per client */
@@ -1371,6 +1384,14 @@ handle_client_listen (void *cls,
1371 struct GNUNET_MessageHeader, 1384 struct GNUNET_MessageHeader,
1372 NULL), 1385 NULL),
1373 GNUNET_MQ_hd_var_size (p2p_message, 1386 GNUNET_MQ_hd_var_size (p2p_message,
1387 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE,
1388 struct GNUNET_MessageHeader,
1389 NULL),
1390 GNUNET_MQ_hd_var_size (p2p_message,
1391 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL,
1392 struct GNUNET_MessageHeader,
1393 NULL),
1394 GNUNET_MQ_hd_var_size (p2p_message,
1374 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 1395 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE,
1375 struct GNUNET_MessageHeader, 1396 struct GNUNET_MessageHeader,
1376 NULL), 1397 NULL),
@@ -1379,6 +1400,10 @@ handle_client_listen (void *cls,
1379 struct GNUNET_MessageHeader, 1400 struct GNUNET_MessageHeader,
1380 NULL), 1401 NULL),
1381 GNUNET_MQ_hd_var_size (p2p_message, 1402 GNUNET_MQ_hd_var_size (p2p_message,
1403 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT,
1404 struct GNUNET_MessageHeader,
1405 NULL),
1406 GNUNET_MQ_hd_var_size (p2p_message,
1382 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 1407 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO,
1383 struct GNUNET_MessageHeader, 1408 struct GNUNET_MessageHeader,
1384 NULL), 1409 NULL),
@@ -1393,7 +1418,6 @@ handle_client_listen (void *cls,
1393 GNUNET_MQ_handler_end () 1418 GNUNET_MQ_handler_end ()
1394 }; 1419 };
1395 struct Listener *listener; 1420 struct Listener *listener;
1396 struct Operation *op;
1397 1421
1398 if (NULL != listener_get (client)) 1422 if (NULL != listener_get (client))
1399 { 1423 {
@@ -1422,7 +1446,7 @@ handle_client_listen (void *cls,
1422 &channel_end_cb, 1446 &channel_end_cb,
1423 cadet_handlers); 1447 cadet_handlers);
1424 /* check for existing incoming requests the listener might be interested in */ 1448 /* check for existing incoming requests the listener might be interested in */
1425 for (op = incoming_head; NULL != op; op = op->next) 1449 for (struct Operation *op = incoming_head; NULL != op; op = op->next)
1426 { 1450 {
1427 if (NULL == op->spec) 1451 if (NULL == op->spec)
1428 continue; /* no details available yet */ 1452 continue; /* no details available yet */
@@ -1634,6 +1658,18 @@ handle_client_evaluate (void *cls,
1634 struct GNUNET_MessageHeader, 1658 struct GNUNET_MessageHeader,
1635 op), 1659 op),
1636 GNUNET_MQ_hd_var_size (p2p_message, 1660 GNUNET_MQ_hd_var_size (p2p_message,
1661 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE,
1662 struct GNUNET_MessageHeader,
1663 op),
1664 GNUNET_MQ_hd_var_size (p2p_message,
1665 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL,
1666 struct GNUNET_MessageHeader,
1667 op),
1668 GNUNET_MQ_hd_var_size (p2p_message,
1669 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT,
1670 struct GNUNET_MessageHeader,
1671 op),
1672 GNUNET_MQ_hd_var_size (p2p_message,
1637 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 1673 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO,
1638 struct GNUNET_MessageHeader, 1674 struct GNUNET_MessageHeader,
1639 op), 1675 op),
@@ -1668,6 +1704,10 @@ handle_client_evaluate (void *cls,
1668 spec->set = set; 1704 spec->set = set;
1669 spec->result_mode = ntohl (msg->result_mode); 1705 spec->result_mode = ntohl (msg->result_mode);
1670 spec->client_request_id = ntohl (msg->request_id); 1706 spec->client_request_id = ntohl (msg->request_id);
1707 spec->byzantine = msg->byzantine;
1708 spec->byzantine_lower_bound = msg->byzantine_lower_bound;
1709 spec->force_full = msg->force_full;
1710 spec->force_delta = msg->force_delta;
1671 context = GNUNET_MQ_extract_nested_mh (msg); 1711 context = GNUNET_MQ_extract_nested_mh (msg);
1672 op->spec = spec; 1712 op->spec = spec;
1673 1713
@@ -1918,7 +1958,7 @@ handle_client_cancel (void *cls,
1918 } 1958 }
1919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1959 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1920 "Client requested cancel for op %u\n", 1960 "Client requested cancel for op %u\n",
1921 ntohl (msg->request_id)); 1961 (uint32_t) ntohl (msg->request_id));
1922 found = GNUNET_NO; 1962 found = GNUNET_NO;
1923 for (op = set->ops_head; NULL != op; op = op->next) 1963 for (op = set->ops_head; NULL != op; op = op->next)
1924 { 1964 {
@@ -1992,7 +2032,7 @@ handle_client_accept (void *cls,
1992 2032
1993 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1994 "Client accepting request %u\n", 2034 "Client accepting request %u\n",
1995 ntohl (msg->accept_reject_id)); 2035 (uint32_t) ntohl (msg->accept_reject_id));
1996 GNUNET_assert (GNUNET_YES == op->is_incoming); 2036 GNUNET_assert (GNUNET_YES == op->is_incoming);
1997 op->is_incoming = GNUNET_NO; 2037 op->is_incoming = GNUNET_NO;
1998 GNUNET_CONTAINER_DLL_remove (incoming_head, 2038 GNUNET_CONTAINER_DLL_remove (incoming_head,
@@ -2004,6 +2044,10 @@ handle_client_accept (void *cls,
2004 op); 2044 op);
2005 op->spec->client_request_id = ntohl (msg->request_id); 2045 op->spec->client_request_id = ntohl (msg->request_id);
2006 op->spec->result_mode = ntohl (msg->result_mode); 2046 op->spec->result_mode = ntohl (msg->result_mode);
2047 op->spec->byzantine = msg->byzantine;
2048 op->spec->byzantine_lower_bound = msg->byzantine_lower_bound;
2049 op->spec->force_full = msg->force_full;
2050 op->spec->force_delta = msg->force_delta;
2007 2051
2008 // Advance generation values, so that 2052 // Advance generation values, so that
2009 // mutations won't interfer with the running operation. 2053 // mutations won't interfer with the running operation.
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h
index 1460707fa..68d8fe81f 100644
--- a/src/set/gnunet-service-set.h
+++ b/src/set/gnunet-service-set.h
@@ -119,6 +119,30 @@ struct OperationSpecification
119 * When are elements sent to the client, and which elements are sent? 119 * When are elements sent to the client, and which elements are sent?
120 */ 120 */
121 enum GNUNET_SET_ResultMode result_mode; 121 enum GNUNET_SET_ResultMode result_mode;
122
123 /**
124 * Always use delta operation instead of sending full sets,
125 * even it it's less efficient.
126 */
127 int force_delta;
128
129 /**
130 * Always send full sets, even if delta operations would
131 * be more efficient.
132 */
133 int force_full;
134
135 /**
136 * #GNUNET_YES to fail operations where Byzantine faults
137 * are suspected
138 */
139 int byzantine;
140
141 /**
142 * Lower bound for the set size, used only when
143 * byzantine mode is enabled.
144 */
145 int byzantine_lower_bound;
122}; 146};
123 147
124 148
diff --git a/src/set/gnunet-service-set_protocol.h b/src/set/gnunet-service-set_protocol.h
index 748da15fc..0138b21c7 100644
--- a/src/set/gnunet-service-set_protocol.h
+++ b/src/set/gnunet-service-set_protocol.h
@@ -208,6 +208,20 @@ struct IntersectionDoneMessage
208 struct GNUNET_HashCode element_xor_hash; 208 struct GNUNET_HashCode element_xor_hash;
209}; 209};
210 210
211
212/**
213 * Strata estimator together with the peer's overall set size.
214 */
215struct StrataEstimatorMessage
216{
217 /**
218 * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE(C)
219 */
220 struct GNUNET_MessageHeader header;
221
222 uint64_t set_size;
223};
224
211GNUNET_NETWORK_STRUCT_END 225GNUNET_NETWORK_STRUCT_END
212 226
213#endif 227#endif
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c
index acaabd94a..f46713c31 100644
--- a/src/set/gnunet-service-set_union.c
+++ b/src/set/gnunet-service-set_union.c
@@ -85,6 +85,7 @@ enum UnionOperationPhase
85 * upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS. 85 * upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS.
86 * 86 *
87 * XXX: could use better wording. 87 * XXX: could use better wording.
88 * XXX: repurposed to also expect a "request full set" message, should be renamed
88 * 89 *
89 * After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS 90 * After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS
90 */ 91 */
@@ -115,14 +116,22 @@ enum UnionOperationPhase
115 * In the penultimate phase, 116 * In the penultimate phase,
116 * we wait until all our demands 117 * we wait until all our demands
117 * are satisfied. Then we send a done 118 * are satisfied. Then we send a done
118 * message, and wait for another done message.*/ 119 * message, and wait for another done message.
120 */
119 PHASE_FINISH_WAITING, 121 PHASE_FINISH_WAITING,
120 122
121 /** 123 /**
122 * In the ultimate phase, we wait until 124 * In the ultimate phase, we wait until
123 * our demands are satisfied and then 125 * our demands are satisfied and then
124 * quit (sending another DONE message). */ 126 * quit (sending another DONE message).
125 PHASE_DONE 127 */
128 PHASE_DONE,
129
130 /**
131 * After sending the full set, wait for responses with the elements
132 * that the local peer is missing.
133 */
134 PHASE_FULL_SENDING,
126}; 135};
127 136
128 137
@@ -148,7 +157,7 @@ struct OperationState
148 struct InvertibleBloomFilter *local_ibf; 157 struct InvertibleBloomFilter *local_ibf;
149 158
150 /** 159 /**
151 * Maps IBF-Keys (specific to the current salt) to elements. 160 * Maps unsalted IBF-Keys to elements.
152 * Used as a multihashmap, the keys being the lower 32bit of the IBF-Key. 161 * Used as a multihashmap, the keys being the lower 32bit of the IBF-Key.
153 * Colliding IBF-Keys are linked. 162 * Colliding IBF-Keys are linked.
154 */ 163 */
@@ -183,6 +192,23 @@ struct OperationState
183 * Salt for the IBF we've received and that we're currently decoding. 192 * Salt for the IBF we've received and that we're currently decoding.
184 */ 193 */
185 uint32_t salt_receive; 194 uint32_t salt_receive;
195
196 /**
197 * Number of elements we received from the other peer
198 * that were not in the local set yet.
199 */
200 uint32_t received_fresh;
201
202 /**
203 * Total number of elements received from the other peer.
204 */
205 uint32_t received_total;
206
207 /**
208 * Initial size of our set, just before
209 * the operation started.
210 */
211 uint64_t initial_size;
186}; 212};
187 213
188 214
@@ -203,6 +229,14 @@ struct KeyEntry
203 * is #GNUNET_YES. 229 * is #GNUNET_YES.
204 */ 230 */
205 struct ElementEntry *element; 231 struct ElementEntry *element;
232
233 /**
234 * Did we receive this element?
235 * Even if element->is_foreign is false, we might
236 * have received the element, so this indicates that
237 * the other peer has it.
238 */
239 int received;
206}; 240};
207 241
208 242
@@ -362,6 +396,16 @@ get_ibf_key (const struct GNUNET_HashCode *src)
362 396
363 397
364/** 398/**
399 * Context for #op_get_element_iterator
400 */
401struct GetElementContext
402{
403 struct GNUNET_HashCode hash;
404 struct KeyEntry *k;
405};
406
407
408/**
365 * Iterator over the mapping from IBF keys to element entries. Checks if we 409 * Iterator over the mapping from IBF keys to element entries. Checks if we
366 * have an element with a given GNUNET_HashCode. 410 * have an element with a given GNUNET_HashCode.
367 * 411 *
@@ -372,17 +416,20 @@ get_ibf_key (const struct GNUNET_HashCode *src)
372 * #GNUNET_NO if we've found the element. 416 * #GNUNET_NO if we've found the element.
373 */ 417 */
374static int 418static int
375op_has_element_iterator (void *cls, 419op_get_element_iterator (void *cls,
376 uint32_t key, 420 uint32_t key,
377 void *value) 421 void *value)
378{ 422{
379 struct GNUNET_HashCode *element_hash = cls; 423 struct GetElementContext *ctx = cls;
380 struct KeyEntry *k = value; 424 struct KeyEntry *k = value;
381 425
382 GNUNET_assert (NULL != k); 426 GNUNET_assert (NULL != k);
383 if (0 == GNUNET_CRYPTO_hash_cmp (&k->element->element_hash, 427 if (0 == GNUNET_CRYPTO_hash_cmp (&k->element->element_hash,
384 element_hash)) 428 &ctx->hash))
429 {
430 ctx->k = k;
385 return GNUNET_NO; 431 return GNUNET_NO;
432 }
386 return GNUNET_YES; 433 return GNUNET_YES;
387} 434}
388 435
@@ -395,23 +442,29 @@ op_has_element_iterator (void *cls,
395 * @param element_hash hash of the element to look for 442 * @param element_hash hash of the element to look for
396 * @return #GNUNET_YES if the element has been found, #GNUNET_NO otherwise 443 * @return #GNUNET_YES if the element has been found, #GNUNET_NO otherwise
397 */ 444 */
398static int 445static struct KeyEntry *
399op_has_element (struct Operation *op, 446op_get_element (struct Operation *op,
400 const struct GNUNET_HashCode *element_hash) 447 const struct GNUNET_HashCode *element_hash)
401{ 448{
402 int ret; 449 int ret;
403 struct IBF_Key ibf_key; 450 struct IBF_Key ibf_key;
451 struct GetElementContext ctx = {{{ 0 }} , 0};
452
453 ctx.hash = *element_hash;
404 454
405 ibf_key = get_ibf_key (element_hash); 455 ibf_key = get_ibf_key (element_hash);
406 ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element, 456 ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element,
407 (uint32_t) ibf_key.key_val, 457 (uint32_t) ibf_key.key_val,
408 op_has_element_iterator, 458 op_get_element_iterator,
409 (void *) element_hash); 459 &ctx);
410 460
411 /* was the iteration aborted because we found the element? */ 461 /* was the iteration aborted because we found the element? */
412 if (GNUNET_SYSERR == ret) 462 if (GNUNET_SYSERR == ret)
413 return GNUNET_YES; 463 {
414 return GNUNET_NO; 464 GNUNET_assert (NULL != ctx.k);
465 return ctx.k;
466 }
467 return NULL;
415} 468}
416 469
417 470
@@ -427,10 +480,12 @@ op_has_element (struct Operation *op,
427 * 480 *
428 * @param op the union operation 481 * @param op the union operation
429 * @param ee the element entry 482 * @param ee the element entry
483 * @parem received was this element received from the remote peer?
430 */ 484 */
431static void 485static void
432op_register_element (struct Operation *op, 486op_register_element (struct Operation *op,
433 struct ElementEntry *ee) 487 struct ElementEntry *ee,
488 int received)
434{ 489{
435 struct IBF_Key ibf_key; 490 struct IBF_Key ibf_key;
436 struct KeyEntry *k; 491 struct KeyEntry *k;
@@ -439,6 +494,7 @@ op_register_element (struct Operation *op,
439 k = GNUNET_new (struct KeyEntry); 494 k = GNUNET_new (struct KeyEntry);
440 k->element = ee; 495 k->element = ee;
441 k->ibf_key = ibf_key; 496 k->ibf_key = ibf_key;
497 k->received = received;
442 GNUNET_assert (GNUNET_OK == 498 GNUNET_assert (GNUNET_OK ==
443 GNUNET_CONTAINER_multihashmap32_put (op->state->key_to_element, 499 GNUNET_CONTAINER_multihashmap32_put (op->state->key_to_element,
444 (uint32_t) ibf_key.key_val, 500 (uint32_t) ibf_key.key_val,
@@ -524,12 +580,30 @@ init_key_to_element_iterator (void *cls,
524 580
525 GNUNET_assert (GNUNET_NO == ee->remote); 581 GNUNET_assert (GNUNET_NO == ee->remote);
526 582
527 op_register_element (op, ee); 583 op_register_element (op, ee, GNUNET_NO);
528 return GNUNET_YES; 584 return GNUNET_YES;
529} 585}
530 586
531 587
532/** 588/**
589 * Initialize the IBF key to element mapping local to this set
590 * operation.
591 *
592 * @param op the set union operation
593 */
594static void
595initialize_key_to_element (struct Operation *op)
596{
597 unsigned int len;
598
599 GNUNET_assert (NULL == op->state->key_to_element);
600 len = GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements);
601 op->state->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
602 GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements, init_key_to_element_iterator, op);
603}
604
605
606/**
533 * Create an ibf with the operation's elements 607 * Create an ibf with the operation's elements
534 * of the specified size 608 * of the specified size
535 * 609 *
@@ -541,15 +615,8 @@ static int
541prepare_ibf (struct Operation *op, 615prepare_ibf (struct Operation *op,
542 uint32_t size) 616 uint32_t size)
543{ 617{
544 if (NULL == op->state->key_to_element) 618 GNUNET_assert (NULL != op->state->key_to_element);
545 {
546 unsigned int len;
547 619
548 len = GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements);
549 op->state->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
550 GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements,
551 init_key_to_element_iterator, op);
552 }
553 if (NULL != op->state->local_ibf) 620 if (NULL != op->state->local_ibf)
554 ibf_destroy (op->state->local_ibf); 621 ibf_destroy (op->state->local_ibf);
555 op->state->local_ibf = ibf_create (size, SE_IBF_HASH_NUM); 622 op->state->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
@@ -648,7 +715,7 @@ send_strata_estimator (struct Operation *op)
648{ 715{
649 const struct StrataEstimator *se = op->state->se; 716 const struct StrataEstimator *se = op->state->se;
650 struct GNUNET_MQ_Envelope *ev; 717 struct GNUNET_MQ_Envelope *ev;
651 struct GNUNET_MessageHeader *strata_msg; 718 struct StrataEstimatorMessage *strata_msg;
652 char *buf; 719 char *buf;
653 size_t len; 720 size_t len;
654 uint16_t type; 721 uint16_t type;
@@ -660,13 +727,14 @@ send_strata_estimator (struct Operation *op)
660 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC; 727 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC;
661 else 728 else
662 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE; 729 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE;
663 ev = GNUNET_MQ_msg_header_extra (strata_msg, 730 ev = GNUNET_MQ_msg_extra (strata_msg,
664 len, 731 len,
665 type); 732 type);
666 GNUNET_memcpy (&strata_msg[1], 733 GNUNET_memcpy (&strata_msg[1],
667 buf, 734 buf,
668 len); 735 len);
669 GNUNET_free (buf); 736 GNUNET_free (buf);
737 strata_msg->set_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements));
670 GNUNET_MQ_send (op->mq, 738 GNUNET_MQ_send (op->mq,
671 ev); 739 ev);
672 op->state->phase = PHASE_EXPECT_IBF; 740 op->state->phase = PHASE_EXPECT_IBF;
@@ -693,7 +761,51 @@ get_order_from_difference (unsigned int diff)
693 ibf_order++; 761 ibf_order++;
694 if (ibf_order > MAX_IBF_ORDER) 762 if (ibf_order > MAX_IBF_ORDER)
695 ibf_order = MAX_IBF_ORDER; 763 ibf_order = MAX_IBF_ORDER;
696 return ibf_order; 764 // add one for correction
765 return ibf_order + 1;
766}
767
768
769/**
770 * Send a set element.
771 *
772 * @param cls the union operation `struct Operation *`
773 * @param key unused
774 * @param value the `struct ElementEntry *` to insert
775 * into the key-to-element mapping
776 * @return #GNUNET_YES (to continue iterating)
777 */
778static int
779send_element_iterator (void *cls,
780 const struct GNUNET_HashCode *key,
781 void *value)
782{
783 struct Operation *op = cls;
784 struct GNUNET_SET_ElementMessage *emsg;
785 struct ElementEntry *ee = value;
786 struct GNUNET_SET_Element *el = &ee->element;
787 struct GNUNET_MQ_Envelope *ev;
788
789
790 ev = GNUNET_MQ_msg_extra (emsg, el->size, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT);
791 emsg->element_type = htons (el->element_type);
792 GNUNET_memcpy (&emsg[1], el->data, el->size);
793 GNUNET_MQ_send (op->mq, ev);
794 return GNUNET_YES;
795}
796
797
798static void
799send_full_set (struct Operation *op)
800{
801 struct GNUNET_MQ_Envelope *ev;
802
803 op->state->phase = PHASE_FULL_SENDING;
804
805 (void) GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements,
806 &send_element_iterator, op);
807 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE);
808 GNUNET_MQ_send (op->mq, ev);
697} 809}
698 810
699 811
@@ -713,7 +825,9 @@ handle_p2p_strata_estimator (void *cls,
713{ 825{
714 struct Operation *op = cls; 826 struct Operation *op = cls;
715 struct StrataEstimator *remote_se; 827 struct StrataEstimator *remote_se;
716 int diff; 828 struct StrataEstimatorMessage *msg = (void *) mh;
829 unsigned int diff;
830 uint64_t other_size;
717 size_t len; 831 size_t len;
718 832
719 GNUNET_STATISTICS_update (_GSS_statistics, 833 GNUNET_STATISTICS_update (_GSS_statistics,
@@ -723,11 +837,11 @@ handle_p2p_strata_estimator (void *cls,
723 837
724 if (op->state->phase != PHASE_EXPECT_SE) 838 if (op->state->phase != PHASE_EXPECT_SE)
725 { 839 {
726 fail_union_operation (op);
727 GNUNET_break (0); 840 GNUNET_break (0);
841 fail_union_operation (op);
728 return GNUNET_SYSERR; 842 return GNUNET_SYSERR;
729 } 843 }
730 len = ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader); 844 len = ntohs (mh->size) - sizeof (struct StrataEstimatorMessage);
731 if ( (GNUNET_NO == is_compressed) && 845 if ( (GNUNET_NO == is_compressed) &&
732 (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE) ) 846 (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE) )
733 { 847 {
@@ -735,6 +849,7 @@ handle_p2p_strata_estimator (void *cls,
735 GNUNET_break (0); 849 GNUNET_break (0);
736 return GNUNET_SYSERR; 850 return GNUNET_SYSERR;
737 } 851 }
852 other_size = GNUNET_ntohll (msg->set_size);
738 remote_se = strata_estimator_create (SE_STRATA_COUNT, 853 remote_se = strata_estimator_create (SE_STRATA_COUNT,
739 SE_IBF_SIZE, 854 SE_IBF_SIZE,
740 SE_IBF_HASH_NUM); 855 SE_IBF_HASH_NUM);
@@ -745,7 +860,7 @@ handle_p2p_strata_estimator (void *cls,
745 return GNUNET_SYSERR; 860 return GNUNET_SYSERR;
746 } 861 }
747 if (GNUNET_OK != 862 if (GNUNET_OK !=
748 strata_estimator_read (&mh[1], 863 strata_estimator_read (&msg[1],
749 len, 864 len,
750 is_compressed, 865 is_compressed,
751 remote_se)) 866 remote_se))
@@ -758,6 +873,10 @@ handle_p2p_strata_estimator (void *cls,
758 GNUNET_assert (NULL != op->state->se); 873 GNUNET_assert (NULL != op->state->se);
759 diff = strata_estimator_difference (remote_se, 874 diff = strata_estimator_difference (remote_se,
760 op->state->se); 875 op->state->se);
876
877 if (diff > 200)
878 diff = diff * 3 / 2;
879
761 strata_estimator_destroy (remote_se); 880 strata_estimator_destroy (remote_se);
762 strata_estimator_destroy (op->state->se); 881 strata_estimator_destroy (op->state->se);
763 op->state->se = NULL; 882 op->state->se = NULL;
@@ -765,16 +884,55 @@ handle_p2p_strata_estimator (void *cls,
765 "got se diff=%d, using ibf size %d\n", 884 "got se diff=%d, using ibf size %d\n",
766 diff, 885 diff,
767 1<<get_order_from_difference (diff)); 886 1<<get_order_from_difference (diff));
768 if (GNUNET_OK != 887
769 send_ibf (op, 888 if ((GNUNET_YES == op->spec->byzantine) && (other_size < op->spec->byzantine_lower_bound))
770 get_order_from_difference (diff)))
771 { 889 {
772 /* Internal error, best we can do is shut the connection */ 890 GNUNET_break (0);
773 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
774 "Failed to send IBF, closing connection\n");
775 fail_union_operation (op); 891 fail_union_operation (op);
776 return GNUNET_SYSERR; 892 return GNUNET_SYSERR;
777 } 893 }
894
895
896 if ( (GNUNET_YES == op->spec->force_full) || (diff > op->state->initial_size / 4))
897 {
898 LOG (GNUNET_ERROR_TYPE_INFO,
899 "Sending full set (diff=%d, own set=%u)\n",
900 diff,
901 op->state->initial_size);
902 GNUNET_STATISTICS_update (_GSS_statistics,
903 "# of full sends",
904 1,
905 GNUNET_NO);
906 if (op->state->initial_size <= other_size)
907 {
908 send_full_set (op);
909 }
910 else
911 {
912 struct GNUNET_MQ_Envelope *ev;
913 op->state->phase = PHASE_EXPECT_IBF;
914 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL);
915 GNUNET_MQ_send (op->mq, ev);
916 }
917 }
918 else
919 {
920 GNUNET_STATISTICS_update (_GSS_statistics,
921 "# of ibf sends",
922 1,
923 GNUNET_NO);
924 if (GNUNET_OK !=
925 send_ibf (op,
926 get_order_from_difference (diff)))
927 {
928 /* Internal error, best we can do is shut the connection */
929 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
930 "Failed to send IBF, closing connection\n");
931 fail_union_operation (op);
932 return GNUNET_SYSERR;
933 }
934 }
935
778 return GNUNET_OK; 936 return GNUNET_OK;
779} 937}
780 938
@@ -1141,7 +1299,8 @@ send_client_element (struct Operation *op,
1141 } 1299 }
1142 rm->result_status = htons (status); 1300 rm->result_status = htons (status);
1143 rm->request_id = htonl (op->spec->client_request_id); 1301 rm->request_id = htonl (op->spec->client_request_id);
1144 rm->element_type = element->element_type; 1302 rm->element_type = htons (element->element_type);
1303 rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (op->state->key_to_element));
1145 GNUNET_memcpy (&rm[1], element->data, element->size); 1304 GNUNET_memcpy (&rm[1], element->data, element->size);
1146 GNUNET_MQ_send (op->spec->set->client_mq, ev); 1305 GNUNET_MQ_send (op->spec->set->client_mq, ev);
1147} 1306}
@@ -1164,6 +1323,7 @@ send_done_and_destroy (void *cls)
1164 rm->request_id = htonl (op->spec->client_request_id); 1323 rm->request_id = htonl (op->spec->client_request_id);
1165 rm->result_status = htons (GNUNET_SET_STATUS_DONE); 1324 rm->result_status = htons (GNUNET_SET_STATUS_DONE);
1166 rm->element_type = htons (0); 1325 rm->element_type = htons (0);
1326 rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (op->state->key_to_element));
1167 GNUNET_MQ_send (op->spec->set->client_mq, ev); 1327 GNUNET_MQ_send (op->spec->set->client_mq, ev);
1168 /* Will also call the union-specific cancel function. */ 1328 /* Will also call the union-specific cancel function. */
1169 _GSS_operation_destroy (op, GNUNET_YES); 1329 _GSS_operation_destroy (op, GNUNET_YES);
@@ -1210,6 +1370,8 @@ maybe_finish (struct Operation *op)
1210 1370
1211/** 1371/**
1212 * Handle an element message from a remote peer. 1372 * Handle an element message from a remote peer.
1373 * Sent by the other peer either because we decoded an IBF and placed a demand,
1374 * or because the other peer switched to full set transmission.
1213 * 1375 *
1214 * @param cls the union operation 1376 * @param cls the union operation
1215 * @param mh the message 1377 * @param mh the message
@@ -1273,7 +1435,11 @@ handle_p2p_elements (void *cls,
1273 1, 1435 1,
1274 GNUNET_NO); 1436 GNUNET_NO);
1275 1437
1276 if (GNUNET_YES == op_has_element (op, &ee->element_hash)) 1438 op->state->received_total += 1;
1439
1440 struct KeyEntry *ke = op_get_element (op, &ee->element_hash);
1441
1442 if (NULL != ke)
1277 { 1443 {
1278 /* Got repeated element. Should not happen since 1444 /* Got repeated element. Should not happen since
1279 * we track demands. */ 1445 * we track demands. */
@@ -1281,13 +1447,15 @@ handle_p2p_elements (void *cls,
1281 "# repeated elements", 1447 "# repeated elements",
1282 1, 1448 1,
1283 GNUNET_NO); 1449 GNUNET_NO);
1450 ke->received = GNUNET_YES;
1284 GNUNET_free (ee); 1451 GNUNET_free (ee);
1285 } 1452 }
1286 else 1453 else
1287 { 1454 {
1288 LOG (GNUNET_ERROR_TYPE_DEBUG, 1455 LOG (GNUNET_ERROR_TYPE_DEBUG,
1289 "Registering new element from remote peer\n"); 1456 "Registering new element from remote peer\n");
1290 op_register_element (op, ee); 1457 op->state->received_fresh += 1;
1458 op_register_element (op, ee, GNUNET_YES);
1291 /* only send results immediately if the client wants it */ 1459 /* only send results immediately if the client wants it */
1292 switch (op->spec->result_mode) 1460 switch (op->spec->result_mode)
1293 { 1461 {
@@ -1304,11 +1472,118 @@ handle_p2p_elements (void *cls,
1304 } 1472 }
1305 } 1473 }
1306 1474
1475 if (op->state->received_total > 8 && op->state->received_fresh < op->state->received_total / 3)
1476 {
1477 /* The other peer gave us lots of old elements, there's something wrong. */
1478 GNUNET_break_op (0);
1479 fail_union_operation (op);
1480 return;
1481 }
1482
1307 maybe_finish (op); 1483 maybe_finish (op);
1308} 1484}
1309 1485
1310 1486
1311/** 1487/**
1488 * Handle an element message from a remote peer.
1489 *
1490 * @param cls the union operation
1491 * @param mh the message
1492 */
1493static void
1494handle_p2p_full_element (void *cls,
1495 const struct GNUNET_MessageHeader *mh)
1496{
1497 struct Operation *op = cls;
1498 struct ElementEntry *ee;
1499 const struct GNUNET_SET_ElementMessage *emsg;
1500 uint16_t element_size;
1501
1502 if (ntohs (mh->size) < sizeof (struct GNUNET_SET_ElementMessage))
1503 {
1504 GNUNET_break_op (0);
1505 fail_union_operation (op);
1506 return;
1507 }
1508
1509 emsg = (const struct GNUNET_SET_ElementMessage *) mh;
1510
1511 element_size = ntohs (mh->size) - sizeof (struct GNUNET_SET_ElementMessage);
1512 ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size);
1513 GNUNET_memcpy (&ee[1], &emsg[1], element_size);
1514 ee->element.size = element_size;
1515 ee->element.data = &ee[1];
1516 ee->element.element_type = ntohs (emsg->element_type);
1517 ee->remote = GNUNET_YES;
1518 GNUNET_SET_element_hash (&ee->element, &ee->element_hash);
1519
1520 LOG (GNUNET_ERROR_TYPE_DEBUG,
1521 "Got element (full diff, size %u, hash %s) from peer\n",
1522 (unsigned int) element_size,
1523 GNUNET_h2s (&ee->element_hash));
1524
1525 GNUNET_STATISTICS_update (_GSS_statistics,
1526 "# received elements",
1527 1,
1528 GNUNET_NO);
1529 GNUNET_STATISTICS_update (_GSS_statistics,
1530 "# exchanged elements",
1531 1,
1532 GNUNET_NO);
1533
1534 op->state->received_total += 1;
1535
1536 struct KeyEntry *ke = op_get_element (op, &ee->element_hash);
1537
1538 if (NULL != ke)
1539 {
1540 /* Got repeated element. Should not happen since
1541 * we track demands. */
1542 GNUNET_STATISTICS_update (_GSS_statistics,
1543 "# repeated elements",
1544 1,
1545 GNUNET_NO);
1546 ke->received = GNUNET_YES;
1547 GNUNET_free (ee);
1548 }
1549 else
1550 {
1551 LOG (GNUNET_ERROR_TYPE_DEBUG,
1552 "Registering new element from remote peer\n");
1553 op->state->received_fresh += 1;
1554 op_register_element (op, ee, GNUNET_YES);
1555 /* only send results immediately if the client wants it */
1556 switch (op->spec->result_mode)
1557 {
1558 case GNUNET_SET_RESULT_ADDED:
1559 send_client_element (op, &ee->element, GNUNET_SET_STATUS_OK);
1560 break;
1561 case GNUNET_SET_RESULT_SYMMETRIC:
1562 send_client_element (op, &ee->element, GNUNET_SET_STATUS_ADD_LOCAL);
1563 break;
1564 default:
1565 /* Result mode not supported, should have been caught earlier. */
1566 GNUNET_break (0);
1567 break;
1568 }
1569 }
1570
1571 if ( (GNUNET_YES == op->spec->byzantine) &&
1572 (op->state->received_total > 384 + op->state->received_fresh * 4) &&
1573 (op->state->received_fresh < op->state->received_total / 6) )
1574 {
1575 /* The other peer gave us lots of old elements, there's something wrong. */
1576 LOG (GNUNET_ERROR_TYPE_ERROR,
1577 "Other peer sent only %llu/%llu fresh elements, failing operation\n",
1578 (unsigned long long) op->state->received_fresh,
1579 (unsigned long long) op->state->received_total);
1580 GNUNET_break_op (0);
1581 fail_union_operation (op);
1582 return;
1583 }
1584}
1585
1586/**
1312 * Send offers (for GNUNET_Hash-es) in response 1587 * Send offers (for GNUNET_Hash-es) in response
1313 * to inquiries (for IBF_Key-s). 1588 * to inquiries (for IBF_Key-s).
1314 * 1589 *
@@ -1355,7 +1630,116 @@ handle_p2p_inquiry (void *cls,
1355 1630
1356 1631
1357/** 1632/**
1358 * FIXME 1633 * Iterator over hash map entries, called to
1634 * destroy the linked list of colliding ibf key entries.
1635 *
1636 * @param cls closure
1637 * @param key current key code
1638 * @param value value in the hash map
1639 * @return #GNUNET_YES if we should continue to iterate,
1640 * #GNUNET_NO if not.
1641 */
1642static int
1643send_missing_elements_iter (void *cls,
1644 uint32_t key,
1645 void *value)
1646{
1647 struct Operation *op = cls;
1648 struct KeyEntry *ke = value;
1649 struct GNUNET_MQ_Envelope *ev;
1650 struct GNUNET_SET_ElementMessage *emsg;
1651 struct ElementEntry *ee = ke->element;
1652
1653 if (GNUNET_YES == ke->received)
1654 return GNUNET_YES;
1655
1656 ev = GNUNET_MQ_msg_extra (emsg, ee->element.size, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT);
1657 GNUNET_memcpy (&emsg[1], ee->element.data, ee->element.size);
1658 emsg->reserved = htons (0);
1659 emsg->element_type = htons (ee->element.element_type);
1660 GNUNET_MQ_send (op->mq, ev);
1661
1662 return GNUNET_YES;
1663}
1664
1665
1666/**
1667 * Handle a
1668 *
1669 * @parem cls closure, a set union operation
1670 * @param mh the demand message
1671 */
1672static void
1673handle_p2p_request_full (void *cls,
1674 const struct GNUNET_MessageHeader *mh)
1675{
1676 struct Operation *op = cls;
1677
1678 if (PHASE_EXPECT_IBF != op->state->phase)
1679 {
1680 fail_union_operation (op);
1681 GNUNET_break_op (0);
1682 return;
1683 }
1684
1685 // FIXME: we need to check that our set is larger than the
1686 // byzantine_lower_bound by some threshold
1687 send_full_set (op);
1688}
1689
1690
1691/**
1692 * Handle a "full done" message.
1693 *
1694 * @parem cls closure, a set union operation
1695 * @param mh the demand message
1696 */
1697static void
1698handle_p2p_full_done (void *cls,
1699 const struct GNUNET_MessageHeader *mh)
1700{
1701 struct Operation *op = cls;
1702
1703 if (PHASE_EXPECT_IBF == op->state->phase)
1704 {
1705 struct GNUNET_MQ_Envelope *ev;
1706
1707 LOG (GNUNET_ERROR_TYPE_DEBUG, "got FULL DONE, sending elements that other peer is missing\n");
1708
1709 /* send all the elements that did not come from the remote peer */
1710 GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element,
1711 &send_missing_elements_iter,
1712 op);
1713
1714 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE);
1715 GNUNET_MQ_send (op->mq, ev);
1716 op->state->phase = PHASE_DONE;
1717
1718 /* we now wait until the other peer shuts the tunnel down*/
1719 }
1720 else if (PHASE_FULL_SENDING == op->state->phase)
1721 {
1722 LOG (GNUNET_ERROR_TYPE_DEBUG, "got FULL DONE, finishing\n");
1723 /* We sent the full set, and got the response for that. We're done. */
1724 op->state->phase = PHASE_DONE;
1725 send_done_and_destroy (op);
1726 }
1727 else
1728 {
1729 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "handle full done phase is %u\n", (unsigned) op->state->phase);
1730 GNUNET_break_op (0);
1731 fail_union_operation (op);
1732 return;
1733 }
1734}
1735
1736
1737/**
1738 * Handle a demand by the other peer for elements based on a list
1739 * of GNUNET_HashCode-s.
1740 *
1741 * @parem cls closure, a set union operation
1742 * @param mh the demand message
1359 */ 1743 */
1360static void 1744static void
1361handle_p2p_demand (void *cls, 1745handle_p2p_demand (void *cls,
@@ -1607,6 +1991,9 @@ union_evaluate (struct Operation *op,
1607 else 1991 else
1608 LOG (GNUNET_ERROR_TYPE_DEBUG, 1992 LOG (GNUNET_ERROR_TYPE_DEBUG,
1609 "sent op request without context message\n"); 1993 "sent op request without context message\n");
1994
1995 initialize_key_to_element (op);
1996 op->state->initial_size = GNUNET_CONTAINER_multihashmap32_size (op->state->key_to_element);
1610} 1997}
1611 1998
1612 1999
@@ -1636,6 +2023,8 @@ union_accept (struct Operation *op)
1636 op->state->se = strata_estimator_dup (op->spec->set->state->se); 2023 op->state->se = strata_estimator_dup (op->spec->set->state->se);
1637 op->state->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 2024 op->state->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
1638 op->state->salt_receive = op->state->salt_send = 42; 2025 op->state->salt_receive = op->state->salt_send = 42;
2026 initialize_key_to_element (op);
2027 op->state->initial_size = GNUNET_CONTAINER_multihashmap32_size (op->state->key_to_element);
1639 /* kick off the operation */ 2028 /* kick off the operation */
1640 send_strata_estimator (op); 2029 send_strata_estimator (op);
1641} 2030}
@@ -1743,6 +2132,9 @@ union_handle_p2p_message (struct Operation *op,
1743 case GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS: 2132 case GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS:
1744 handle_p2p_elements (op, mh); 2133 handle_p2p_elements (op, mh);
1745 break; 2134 break;
2135 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT:
2136 handle_p2p_full_element (op, mh);
2137 break;
1746 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY: 2138 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY:
1747 handle_p2p_inquiry (op, mh); 2139 handle_p2p_inquiry (op, mh);
1748 break; 2140 break;
@@ -1755,6 +2147,12 @@ union_handle_p2p_message (struct Operation *op,
1755 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND: 2147 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND:
1756 handle_p2p_demand (op, mh); 2148 handle_p2p_demand (op, mh);
1757 break; 2149 break;
2150 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE:
2151 handle_p2p_full_done (op, mh);
2152 break;
2153 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL:
2154 handle_p2p_request_full (op, mh);
2155 break;
1758 default: 2156 default:
1759 /* Something wrong with cadet's message handlers? */ 2157 /* Something wrong with cadet's message handlers? */
1760 GNUNET_assert (0); 2158 GNUNET_assert (0);
diff --git a/src/set/gnunet-set-profiler.c b/src/set/gnunet-set-profiler.c
index f89817ff5..8404b191c 100644
--- a/src/set/gnunet-set-profiler.c
+++ b/src/set/gnunet-set-profiler.c
@@ -58,6 +58,11 @@ static struct GNUNET_PeerIdentity local_peer;
58 58
59static struct GNUNET_SET_ListenHandle *set_listener; 59static struct GNUNET_SET_ListenHandle *set_listener;
60 60
61static int byzantine;
62static int force_delta;
63static int force_full;
64static unsigned int element_size = 32;
65
61/** 66/**
62 * Handle to the statistics service. 67 * Handle to the statistics service.
63 */ 68 */
@@ -86,7 +91,7 @@ map_remove_iterator (void *cls,
86 91
87 GNUNET_assert (NULL != key); 92 GNUNET_assert (NULL != key);
88 93
89 ret = GNUNET_CONTAINER_multihashmap_remove (m, key, NULL); 94 ret = GNUNET_CONTAINER_multihashmap_remove_all (m, key);
90 if (GNUNET_OK != ret) 95 if (GNUNET_OK != ret)
91 printf ("spurious element\n"); 96 printf ("spurious element\n");
92 return GNUNET_YES; 97 return GNUNET_YES;
@@ -158,6 +163,7 @@ check_all_done (void)
158static void 163static void
159set_result_cb (void *cls, 164set_result_cb (void *cls,
160 const struct GNUNET_SET_Element *element, 165 const struct GNUNET_SET_Element *element,
166 uint64_t current_size,
161 enum GNUNET_SET_Status status) 167 enum GNUNET_SET_Status status)
162{ 168{
163 struct SetInfo *info = cls; 169 struct SetInfo *info = cls;
@@ -191,7 +197,7 @@ set_result_cb (void *cls,
191 GNUNET_assert (0); 197 GNUNET_assert (0);
192 } 198 }
193 199
194 if (element->size != sizeof (struct GNUNET_HashCode)) 200 if (element->size != element_size)
195 { 201 {
196 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 202 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
197 "wrong element size: %u, expected %u\n", 203 "wrong element size: %u, expected %u\n",
@@ -203,8 +209,10 @@ set_result_cb (void *cls,
203 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n", 209 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n",
204 info->id, GNUNET_h2s (element->data)); 210 info->id, GNUNET_h2s (element->data));
205 GNUNET_assert (NULL != element->data); 211 GNUNET_assert (NULL != element->data);
212 struct GNUNET_HashCode data_hash;
213 GNUNET_CRYPTO_hash (element->data, element_size, &data_hash);
206 GNUNET_CONTAINER_multihashmap_put (info->received, 214 GNUNET_CONTAINER_multihashmap_put (info->received,
207 element->data, NULL, 215 &data_hash, NULL,
208 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); 216 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
209} 217}
210 218
@@ -215,6 +223,10 @@ set_listen_cb (void *cls,
215 const struct GNUNET_MessageHeader *context_msg, 223 const struct GNUNET_MessageHeader *context_msg,
216 struct GNUNET_SET_Request *request) 224 struct GNUNET_SET_Request *request)
217{ 225{
226 /* max. 2 options plus terminator */
227 struct GNUNET_SET_Option opts[3] = {{0}};
228 unsigned int n_opts = 0;
229
218 if (NULL == request) 230 if (NULL == request)
219 { 231 {
220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 232 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -224,8 +236,24 @@ set_listen_cb (void *cls,
224 GNUNET_assert (NULL == info2.oh); 236 GNUNET_assert (NULL == info2.oh);
225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
226 "set listen cb called\n"); 238 "set listen cb called\n");
239 if (byzantine)
240 {
241 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_BYZANTINE };
242 }
243 GNUNET_assert (!(force_full && force_delta));
244 if (force_full)
245 {
246 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_FULL };
247 }
248 if (force_delta)
249 {
250 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_DELTA };
251 }
252
253 opts[n_opts].type = 0;
227 info2.oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_SYMMETRIC, 254 info2.oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_SYMMETRIC,
228 set_result_cb, &info2); 255 opts,
256 set_result_cb, &info2);
229 GNUNET_SET_commit (info2.oh, info2.set); 257 GNUNET_SET_commit (info2.oh, info2.set);
230} 258}
231 259
@@ -236,16 +264,12 @@ set_insert_iterator (void *cls,
236 void *value) 264 void *value)
237{ 265{
238 struct GNUNET_SET_Handle *set = cls; 266 struct GNUNET_SET_Handle *set = cls;
239 struct GNUNET_SET_Element *el; 267 struct GNUNET_SET_Element el;
240 268
241 el = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + 269 el.element_type = 0;
242 sizeof (struct GNUNET_HashCode)); 270 el.data = value;
243 el->element_type = 0; 271 el.size = element_size;
244 GNUNET_memcpy (&el[1], key, sizeof *key); 272 GNUNET_SET_add_element (set, &el, NULL, NULL);
245 el->data = &el[1];
246 el->size = sizeof *key;
247 GNUNET_SET_add_element (set, el, NULL, NULL);
248 GNUNET_free (el);
249 return GNUNET_YES; 273 return GNUNET_YES;
250} 274}
251 275
@@ -291,9 +315,14 @@ run (void *cls,
291{ 315{
292 unsigned int i; 316 unsigned int i;
293 struct GNUNET_HashCode hash; 317 struct GNUNET_HashCode hash;
318 /* max. 2 options plus terminator */
319 struct GNUNET_SET_Option opts[3] = {{0}};
320 unsigned int n_opts = 0;
294 321
295 config = cfg; 322 config = cfg;
296 323
324 GNUNET_assert (element_size > 0);
325
297 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer)) 326 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer))
298 { 327 {
299 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n"); 328 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
@@ -317,22 +346,28 @@ run (void *cls,
317 346
318 for (i = 0; i < num_a; i++) 347 for (i = 0; i < num_a; i++)
319 { 348 {
320 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &hash); 349 char *data = GNUNET_malloc (element_size);
321 GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, NULL, 350 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
351 GNUNET_CRYPTO_hash (data, element_size, &hash);
352 GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, data,
322 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); 353 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
323 } 354 }
324 355
325 for (i = 0; i < num_b; i++) 356 for (i = 0; i < num_b; i++)
326 { 357 {
327 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &hash); 358 char *data = GNUNET_malloc (element_size);
328 GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, NULL, 359 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
360 GNUNET_CRYPTO_hash (data, element_size, &hash);
361 GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, data,
329 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); 362 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
330 } 363 }
331 364
332 for (i = 0; i < num_c; i++) 365 for (i = 0; i < num_c; i++)
333 { 366 {
334 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &hash); 367 char *data = GNUNET_malloc (element_size);
335 GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, NULL, 368 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
369 GNUNET_CRYPTO_hash (data, element_size, &hash);
370 GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
336 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); 371 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
337 } 372 }
338 373
@@ -350,8 +385,26 @@ run (void *cls,
350 set_listener = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION, 385 set_listener = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION,
351 &app_id, set_listen_cb, NULL); 386 &app_id, set_listen_cb, NULL);
352 387
388
389 if (byzantine)
390 {
391 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_BYZANTINE };
392 }
393 GNUNET_assert (!(force_full && force_delta));
394 if (force_full)
395 {
396 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_FULL };
397 }
398 if (force_delta)
399 {
400 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_DELTA };
401 }
402
403 opts[n_opts].type = 0;
404
353 info1.oh = GNUNET_SET_prepare (&local_peer, &app_id, NULL, 405 info1.oh = GNUNET_SET_prepare (&local_peer, &app_id, NULL,
354 GNUNET_SET_RESULT_SYMMETRIC, 406 GNUNET_SET_RESULT_SYMMETRIC,
407 opts,
355 set_result_cb, &info1); 408 set_result_cb, &info1);
356 GNUNET_SET_commit (info1.oh, info1.set); 409 GNUNET_SET_commit (info1.oh, info1.set);
357 GNUNET_SET_destroy (info1.set); 410 GNUNET_SET_destroy (info1.set);
@@ -380,12 +433,24 @@ main (int argc, char **argv)
380 { 'B', "num-second", NULL, 433 { 'B', "num-second", NULL,
381 gettext_noop ("number of values"), 434 gettext_noop ("number of values"),
382 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_b }, 435 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_b },
436 { 'b', "byzantine", NULL,
437 gettext_noop ("use byzantine mode"),
438 GNUNET_NO, &GNUNET_GETOPT_set_one, &byzantine },
439 { 'f', "force-full", NULL,
440 gettext_noop ("force sending full set"),
441 GNUNET_NO, &GNUNET_GETOPT_set_uint, &force_full },
442 { 'd', "force-delta", NULL,
443 gettext_noop ("number delta operation"),
444 GNUNET_NO, &GNUNET_GETOPT_set_uint, &force_delta },
383 { 'C', "num-common", NULL, 445 { 'C', "num-common", NULL,
384 gettext_noop ("number of values"), 446 gettext_noop ("number of values"),
385 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_c }, 447 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_c },
386 { 'x', "operation", NULL, 448 { 'x', "operation", NULL,
387 gettext_noop ("operation to execute"), 449 gettext_noop ("operation to execute"),
388 GNUNET_YES, &GNUNET_GETOPT_set_string, &op_str }, 450 GNUNET_YES, &GNUNET_GETOPT_set_string, &op_str },
451 { 'w', "element-size", NULL,
452 gettext_noop ("element size"),
453 GNUNET_YES, &GNUNET_GETOPT_set_uint, &element_size },
389 { 's', "statistics", NULL, 454 { 's', "statistics", NULL,
390 gettext_noop ("write statistics to file"), 455 gettext_noop ("write statistics to file"),
391 GNUNET_YES, &GNUNET_GETOPT_set_filename, &statistics_filename }, 456 GNUNET_YES, &GNUNET_GETOPT_set_filename, &statistics_filename },
diff --git a/src/set/plugin_block_set_test.c b/src/set/plugin_block_set_test.c
new file mode 100644
index 000000000..01b0c8602
--- /dev/null
+++ b/src/set/plugin_block_set_test.c
@@ -0,0 +1,123 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file set/plugin_block_set_test.c
23 * @brief set test block, recognizes elements with non-zero first byte as invalid
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_block_plugin.h"
29#include "gnunet_block_group_lib.h"
30
31
32/**
33 * Function called to validate a reply or a request. For
34 * request evaluation, simply pass "NULL" for the reply_block.
35 *
36 * @param cls closure
37 * @param ctx block context
38 * @param type block type
39 * @param group block group to use
40 * @param eo control flags
41 * @param query original query (hash)
42 * @param xquery extrended query data (can be NULL, depending on type)
43 * @param xquery_size number of bytes in xquery
44 * @param reply_block response to validate
45 * @param reply_block_size number of bytes in reply block
46 * @return characterization of result
47 */
48static enum GNUNET_BLOCK_EvaluationResult
49block_plugin_set_test_evaluate (void *cls,
50 struct GNUNET_BLOCK_Context *ctx,
51 enum GNUNET_BLOCK_Type type,
52 struct GNUNET_BLOCK_Group *group,
53 enum GNUNET_BLOCK_EvaluationOptions eo,
54 const struct GNUNET_HashCode *query,
55 const void *xquery,
56 size_t xquery_size,
57 const void *reply_block,
58 size_t reply_block_size)
59{
60 if ( (NULL == reply_block) ||
61 (reply_block_size == 0) ||
62 (0 != ((char *) reply_block)[0]) )
63 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
64 return GNUNET_BLOCK_EVALUATION_OK_MORE;
65}
66
67
68/**
69 * Function called to obtain the key for a block.
70 *
71 * @param cls closure
72 * @param type block type
73 * @param block block to get the key for
74 * @param block_size number of bytes in block
75 * @param key set to the key (query) for the given block
76 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
77 * (or if extracting a key from a block of this type does not work)
78 */
79static int
80block_plugin_set_test_get_key (void *cls,
81 enum GNUNET_BLOCK_Type type,
82 const void *block,
83 size_t block_size,
84 struct GNUNET_HashCode *key)
85{
86 return GNUNET_SYSERR;
87}
88
89
90/**
91 * Entry point for the plugin.
92 */
93void *
94libgnunet_plugin_block_set_test_init (void *cls)
95{
96 static enum GNUNET_BLOCK_Type types[] =
97 {
98 GNUNET_BLOCK_TYPE_SET_TEST,
99 GNUNET_BLOCK_TYPE_ANY /* end of list */
100 };
101 struct GNUNET_BLOCK_PluginFunctions *api;
102
103 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
104 api->evaluate = &block_plugin_set_test_evaluate;
105 api->get_key = &block_plugin_set_test_get_key;
106 api->types = types;
107 return api;
108}
109
110
111/**
112 * Exit point from the plugin.
113 */
114void *
115libgnunet_plugin_block_set_test_done (void *cls)
116{
117 struct GNUNET_BLOCK_PluginFunctions *api = cls;
118
119 GNUNET_free (api);
120 return NULL;
121}
122
123/* end of plugin_block_set_test.c */
diff --git a/src/set/set.h b/src/set/set.h
index f31216cb8..258e2bff9 100644
--- a/src/set/set.h
+++ b/src/set/set.h
@@ -102,6 +102,30 @@ struct GNUNET_SET_AcceptMessage
102 * See `enum GNUNET_SET_ResultMode`. 102 * See `enum GNUNET_SET_ResultMode`.
103 */ 103 */
104 uint32_t result_mode GNUNET_PACKED; 104 uint32_t result_mode GNUNET_PACKED;
105
106 /**
107 * Always use delta operation instead of sending full sets,
108 * even it it's less efficient.
109 */
110 uint8_t force_delta;
111
112 /**
113 * Always send full sets, even if delta operations would
114 * be more efficient.
115 */
116 uint8_t force_full;
117
118 /**
119 * #GNUNET_YES to fail operations where Byzantine faults
120 * are suspected
121 */
122 uint8_t byzantine;
123
124 /**
125 * Lower bound for the set size, used only when
126 * byzantine mode is enabled.
127 */
128 uint8_t byzantine_lower_bound;
105}; 129};
106 130
107 131
@@ -184,6 +208,30 @@ struct GNUNET_SET_EvaluateMessage
184 */ 208 */
185 uint32_t request_id GNUNET_PACKED; 209 uint32_t request_id GNUNET_PACKED;
186 210
211 /**
212 * Always use delta operation instead of sending full sets,
213 * even it it's less efficient.
214 */
215 uint8_t force_delta;
216
217 /**
218 * Always send full sets, even if delta operations would
219 * be more efficient.
220 */
221 uint8_t force_full;
222
223 /**
224 * #GNUNET_YES to fail operations where Byzantine faults
225 * are suspected
226 */
227 uint8_t byzantine;
228
229 /**
230 * Lower bound for the set size, used only when
231 * byzantine mode is enabled.
232 */
233 uint8_t byzantine_lower_bound;
234
187 /* rest: context message, that is, application-specific 235 /* rest: context message, that is, application-specific
188 message to convince listener to pick up */ 236 message to convince listener to pick up */
189}; 237};
@@ -203,6 +251,11 @@ struct GNUNET_SET_ResultMessage
203 struct GNUNET_MessageHeader header; 251 struct GNUNET_MessageHeader header;
204 252
205 /** 253 /**
254 * Current set size.
255 */
256 uint64_t current_size;
257
258 /**
206 * id the result belongs to 259 * id the result belongs to
207 */ 260 */
208 uint32_t request_id GNUNET_PACKED; 261 uint32_t request_id GNUNET_PACKED;
diff --git a/src/set/set_api.c b/src/set/set_api.c
index baeee6da0..5b5b1b8ee 100644
--- a/src/set/set_api.c
+++ b/src/set/set_api.c
@@ -432,6 +432,7 @@ do_final:
432 { 432 {
433 oh->result_cb (oh->result_cls, 433 oh->result_cb (oh->result_cls,
434 NULL, 434 NULL,
435 GNUNET_ntohll (msg->current_size),
435 result_status); 436 result_status);
436 } 437 }
437 else 438 else
@@ -453,6 +454,7 @@ do_element:
453 if (NULL != oh->result_cb) 454 if (NULL != oh->result_cb)
454 oh->result_cb (oh->result_cls, 455 oh->result_cb (oh->result_cls,
455 &e, 456 &e,
457 GNUNET_ntohll (msg->current_size),
456 result_status); 458 result_status);
457} 459}
458 460
@@ -538,6 +540,7 @@ handle_client_set_error (void *cls,
538 if (NULL != set->ops_head->result_cb) 540 if (NULL != set->ops_head->result_cb)
539 set->ops_head->result_cb (set->ops_head->result_cls, 541 set->ops_head->result_cb (set->ops_head->result_cls,
540 NULL, 542 NULL,
543 0,
541 GNUNET_SET_STATUS_FAILURE); 544 GNUNET_SET_STATUS_FAILURE);
542 set_operation_destroy (set->ops_head); 545 set_operation_destroy (set->ops_head);
543 } 546 }
@@ -654,6 +657,8 @@ GNUNET_SET_add_element (struct GNUNET_SET_Handle *set,
654 struct GNUNET_MQ_Envelope *mqm; 657 struct GNUNET_MQ_Envelope *mqm;
655 struct GNUNET_SET_ElementMessage *msg; 658 struct GNUNET_SET_ElementMessage *msg;
656 659
660 LOG (GNUNET_ERROR_TYPE_INFO, "adding element of type %u\n", (unsigned) element->element_type);
661
657 if (GNUNET_YES == set->invalid) 662 if (GNUNET_YES == set->invalid)
658 { 663 {
659 if (NULL != cont) 664 if (NULL != cont)
@@ -766,12 +771,14 @@ GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
766 const struct GNUNET_HashCode *app_id, 771 const struct GNUNET_HashCode *app_id,
767 const struct GNUNET_MessageHeader *context_msg, 772 const struct GNUNET_MessageHeader *context_msg,
768 enum GNUNET_SET_ResultMode result_mode, 773 enum GNUNET_SET_ResultMode result_mode,
774 struct GNUNET_SET_Option options[],
769 GNUNET_SET_ResultIterator result_cb, 775 GNUNET_SET_ResultIterator result_cb,
770 void *result_cls) 776 void *result_cls)
771{ 777{
772 struct GNUNET_MQ_Envelope *mqm; 778 struct GNUNET_MQ_Envelope *mqm;
773 struct GNUNET_SET_OperationHandle *oh; 779 struct GNUNET_SET_OperationHandle *oh;
774 struct GNUNET_SET_EvaluateMessage *msg; 780 struct GNUNET_SET_EvaluateMessage *msg;
781 struct GNUNET_SET_Option *opt;
775 782
776 LOG (GNUNET_ERROR_TYPE_DEBUG, 783 LOG (GNUNET_ERROR_TYPE_DEBUG,
777 "Client prepares set operation (%d)\n", 784 "Client prepares set operation (%d)\n",
@@ -785,6 +792,25 @@ GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
785 msg->app_id = *app_id; 792 msg->app_id = *app_id;
786 msg->result_mode = htonl (result_mode); 793 msg->result_mode = htonl (result_mode);
787 msg->target_peer = *other_peer; 794 msg->target_peer = *other_peer;
795 for (opt = options; opt->type != 0; opt++)
796 {
797 switch (opt->type)
798 {
799 case GNUNET_SET_OPTION_BYZANTINE:
800 msg->byzantine = GNUNET_YES;
801 msg->byzantine_lower_bound = opt->v.num;
802 break;
803 case GNUNET_SET_OPTION_FORCE_FULL:
804 msg->force_full = GNUNET_YES;
805 break;
806 case GNUNET_SET_OPTION_FORCE_DELTA:
807 msg->force_delta = GNUNET_YES;
808 break;
809 default:
810 LOG (GNUNET_ERROR_TYPE_ERROR,
811 "Option with type %d not recognized\n", (int) opt->type);
812 }
813 }
788 oh->conclude_mqm = mqm; 814 oh->conclude_mqm = mqm;
789 oh->request_id_addr = &msg->request_id; 815 oh->request_id_addr = &msg->request_id;
790 816
@@ -1006,6 +1032,7 @@ GNUNET_SET_listen_cancel (struct GNUNET_SET_ListenHandle *lh)
1006struct GNUNET_SET_OperationHandle * 1032struct GNUNET_SET_OperationHandle *
1007GNUNET_SET_accept (struct GNUNET_SET_Request *request, 1033GNUNET_SET_accept (struct GNUNET_SET_Request *request,
1008 enum GNUNET_SET_ResultMode result_mode, 1034 enum GNUNET_SET_ResultMode result_mode,
1035 struct GNUNET_SET_Option options[],
1009 GNUNET_SET_ResultIterator result_cb, 1036 GNUNET_SET_ResultIterator result_cb,
1010 void *result_cls) 1037 void *result_cls)
1011{ 1038{
diff --git a/src/set/test_set.conf b/src/set/test_set.conf
index 69e7f5c52..e28dfc6e9 100644
--- a/src/set/test_set.conf
+++ b/src/set/test_set.conf
@@ -5,7 +5,6 @@ GNUNET_TEST_HOME = /tmp/test-gnunet-set/
5 5
6[set] 6[set]
7AUTOSTART = YES 7AUTOSTART = YES
8# PREFIX = valgrind
9#PREFIX = valgrind --leak-check=full 8#PREFIX = valgrind --leak-check=full
10#PREFIX = gdbserver :1234 9#PREFIX = gdbserver :1234
11OPTIONS = -L INFO 10OPTIONS = -L INFO
diff --git a/src/set/test_set_api.c b/src/set/test_set_api.c
index 21af45f8a..dd3f004f2 100644
--- a/src/set/test_set_api.c
+++ b/src/set/test_set_api.c
@@ -55,6 +55,7 @@ static struct GNUNET_SCHEDULER_Task *tt;
55static void 55static void
56result_cb_set1 (void *cls, 56result_cb_set1 (void *cls,
57 const struct GNUNET_SET_Element *element, 57 const struct GNUNET_SET_Element *element,
58 uint64_t size,
58 enum GNUNET_SET_Status status) 59 enum GNUNET_SET_Status status)
59{ 60{
60 switch (status) 61 switch (status)
@@ -101,6 +102,7 @@ result_cb_set1 (void *cls,
101static void 102static void
102result_cb_set2 (void *cls, 103result_cb_set2 (void *cls,
103 const struct GNUNET_SET_Element *element, 104 const struct GNUNET_SET_Element *element,
105 uint64_t size,
104 enum GNUNET_SET_Status status) 106 enum GNUNET_SET_Status status)
105{ 107{
106 switch (status) 108 switch (status)
@@ -149,6 +151,7 @@ listen_cb (void *cls,
149 listen_handle = NULL; 151 listen_handle = NULL;
150 oh2 = GNUNET_SET_accept (request, 152 oh2 = GNUNET_SET_accept (request,
151 GNUNET_SET_RESULT_ADDED, 153 GNUNET_SET_RESULT_ADDED,
154 (struct GNUNET_SET_Option[]) { 0 },
152 &result_cb_set2, 155 &result_cb_set2,
153 NULL); 156 NULL);
154 GNUNET_SET_commit (oh2, 157 GNUNET_SET_commit (oh2,
@@ -179,6 +182,7 @@ start (void *cls)
179 &app_id, 182 &app_id,
180 &context_msg, 183 &context_msg,
181 GNUNET_SET_RESULT_ADDED, 184 GNUNET_SET_RESULT_ADDED,
185 (struct GNUNET_SET_Option[]) { 0 },
182 &result_cb_set1, 186 &result_cb_set1,
183 NULL); 187 NULL);
184 GNUNET_SET_commit (oh1, 188 GNUNET_SET_commit (oh1,
@@ -378,6 +382,7 @@ run (void *cls,
378 &app_id, 382 &app_id,
379 NULL, 383 NULL,
380 GNUNET_SET_RESULT_ADDED, 384 GNUNET_SET_RESULT_ADDED,
385 (struct GNUNET_SET_Option[]) { 0 },
381 NULL, 386 NULL,
382 NULL); 387 NULL);
383 388
diff --git a/src/set/test_set_intersection_result_full.c b/src/set/test_set_intersection_result_full.c
index b2d6ce8a9..a36aae4d5 100644
--- a/src/set/test_set_intersection_result_full.c
+++ b/src/set/test_set_intersection_result_full.c
@@ -56,6 +56,7 @@ static struct GNUNET_SET_OperationHandle *oh2;
56static void 56static void
57result_cb_set1 (void *cls, 57result_cb_set1 (void *cls,
58 const struct GNUNET_SET_Element *element, 58 const struct GNUNET_SET_Element *element,
59 uint64_t current_size,
59 enum GNUNET_SET_Status status) 60 enum GNUNET_SET_Status status)
60{ 61{
61 static int count; 62 static int count;
@@ -89,6 +90,7 @@ result_cb_set1 (void *cls,
89static void 90static void
90result_cb_set2 (void *cls, 91result_cb_set2 (void *cls,
91 const struct GNUNET_SET_Element *element, 92 const struct GNUNET_SET_Element *element,
93 uint64_t current_size,
92 enum GNUNET_SET_Status status) 94 enum GNUNET_SET_Status status)
93{ 95{
94 static int count; 96 static int count;
@@ -133,6 +135,7 @@ listen_cb (void *cls,
133 listen_handle = NULL; 135 listen_handle = NULL;
134 oh2 = GNUNET_SET_accept (request, 136 oh2 = GNUNET_SET_accept (request,
135 GNUNET_SET_RESULT_FULL, 137 GNUNET_SET_RESULT_FULL,
138 (struct GNUNET_SET_Option[]) { 0 },
136 &result_cb_set2, 139 &result_cb_set2,
137 NULL); 140 NULL);
138 GNUNET_SET_commit (oh2, 141 GNUNET_SET_commit (oh2,
@@ -163,6 +166,7 @@ start (void *cls)
163 &app_id, 166 &app_id,
164 &context_msg, 167 &context_msg,
165 GNUNET_SET_RESULT_FULL, 168 GNUNET_SET_RESULT_FULL,
169 (struct GNUNET_SET_Option[]) { 0 },
166 &result_cb_set1, 170 &result_cb_set1,
167 NULL); 171 NULL);
168 GNUNET_SET_commit (oh1, 172 GNUNET_SET_commit (oh1,
diff --git a/src/set/test_set_union_result_symmetric.c b/src/set/test_set_union_result_symmetric.c
index ab191a34a..f81c7b8f7 100644
--- a/src/set/test_set_union_result_symmetric.c
+++ b/src/set/test_set_union_result_symmetric.c
@@ -77,6 +77,7 @@ static struct GNUNET_SCHEDULER_Task *timeout_task;
77static void 77static void
78result_cb_set1 (void *cls, 78result_cb_set1 (void *cls,
79 const struct GNUNET_SET_Element *element, 79 const struct GNUNET_SET_Element *element,
80 uint64_t current_size,
80 enum GNUNET_SET_Status status) 81 enum GNUNET_SET_Status status)
81{ 82{
82 switch (status) 83 switch (status)
@@ -125,6 +126,7 @@ result_cb_set1 (void *cls,
125static void 126static void
126result_cb_set2 (void *cls, 127result_cb_set2 (void *cls,
127 const struct GNUNET_SET_Element *element, 128 const struct GNUNET_SET_Element *element,
129 uint64_t current_size,
128 enum GNUNET_SET_Status status) 130 enum GNUNET_SET_Status status)
129{ 131{
130 switch (status) 132 switch (status)
@@ -184,6 +186,7 @@ listen_cb (void *cls,
184 listen_handle = NULL; 186 listen_handle = NULL;
185 oh2 = GNUNET_SET_accept (request, 187 oh2 = GNUNET_SET_accept (request,
186 GNUNET_SET_RESULT_SYMMETRIC, 188 GNUNET_SET_RESULT_SYMMETRIC,
189 (struct GNUNET_SET_Option[]) { 0 },
187 &result_cb_set2, 190 &result_cb_set2,
188 NULL); 191 NULL);
189 GNUNET_SET_commit (oh2, 192 GNUNET_SET_commit (oh2,
@@ -212,6 +215,7 @@ start (void *cls)
212 &app_id, 215 &app_id,
213 &context_msg, 216 &context_msg,
214 GNUNET_SET_RESULT_SYMMETRIC, 217 GNUNET_SET_RESULT_SYMMETRIC,
218 (struct GNUNET_SET_Option[]) { 0 },
215 &result_cb_set1, NULL); 219 &result_cb_set1, NULL);
216 GNUNET_SET_commit (oh1, set1); 220 GNUNET_SET_commit (oh1, set1);
217} 221}