GNUnet 0.26.2-102-g1031339ee
 
Loading...
Searching...
No Matches
gnunet-service-set_union.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
29#include "gnunet-service-set.h"
30#include "ibf.h"
34#include <gcrypt.h>
35
36
37#define LOG(kind, ...) GNUNET_log_from (kind, "set-union", __VA_ARGS__)
38
39
43#define SE_STRATA_COUNT 32
44
48#define SE_IBF_SIZE 80
49
53#define SE_IBF_HASH_NUM 4
54
58#define MAX_BUCKETS_PER_MESSAGE ((1 << 15) / IBF_BUCKET_SIZE)
59
65#define MAX_IBF_ORDER (20)
66
71#define IBF_ALPHA 4
72
73
137
138
142struct OperationState
143{
149
154
159
166
171
176
181
186
190 uint32_t salt_send;
191
195 uint32_t salt_receive;
196
202
207
212 uint64_t initial_size;
213};
214
215
220{
225
233
241};
242
243
249{
255
260 struct Operation *op;
261};
262
263
267struct SetState
268{
276};
277
278
289static int
291 uint32_t key,
292 void *value)
293{
294 struct KeyEntry *k = value;
295
296 GNUNET_assert (NULL != k);
297 if (GNUNET_YES == k->element->remote)
298 {
299 GNUNET_free (k->element);
300 k->element = NULL;
301 }
302 GNUNET_free (k);
303 return GNUNET_YES;
304}
305
306
313static void
315{
317 "destroying union op\n");
318 /* check if the op was canceled twice */
319 GNUNET_assert (NULL != op->state);
320 if (NULL != op->state->remote_ibf)
321 {
322 ibf_destroy (op->state->remote_ibf);
323 op->state->remote_ibf = NULL;
324 }
325 if (NULL != op->state->demanded_hashes)
326 {
327 GNUNET_CONTAINER_multihashmap_destroy (op->state->demanded_hashes);
328 op->state->demanded_hashes = NULL;
329 }
330 if (NULL != op->state->local_ibf)
331 {
332 ibf_destroy (op->state->local_ibf);
333 op->state->local_ibf = NULL;
334 }
335 if (NULL != op->state->se)
336 {
337 strata_estimator_destroy (op->state->se);
338 op->state->se = NULL;
339 }
340 if (NULL != op->state->key_to_element)
341 {
342 GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element,
344 NULL);
345 GNUNET_CONTAINER_multihashmap32_destroy (op->state->key_to_element);
346 op->state->key_to_element = NULL;
347 }
348 GNUNET_free (op->state);
349 op->state = NULL;
351 "destroying union op done\n");
352}
353
354
361static void
363{
364 struct GNUNET_MQ_Envelope *ev;
366
368 "union operation failed\n");
370 msg->result_status = htons (GNUNET_SET_STATUS_FAILURE);
371 msg->request_id = htonl (op->client_request_id);
372 msg->element_type = htons (0);
373 GNUNET_MQ_send (op->set->cs->mq,
374 ev);
376}
377
378
386static struct IBF_Key
387get_ibf_key (const struct GNUNET_HashCode *src)
388{
389 struct IBF_Key key;
390 uint16_t salt = 0;
391
394 &key,
395 sizeof(key),
396 src,
397 sizeof *src,
398 &salt,
399 sizeof(salt)));
400 return key;
401}
402
403
408{
413
417 struct KeyEntry *k;
418};
419
420
431static int
433 uint32_t key,
434 void *value)
435{
436 struct GetElementContext *ctx = cls;
437 struct KeyEntry *k = value;
438
439 GNUNET_assert (NULL != k);
441 &ctx->hash))
442 {
443 ctx->k = k;
444 return GNUNET_NO;
445 }
446 return GNUNET_YES;
447}
448
449
458static struct KeyEntry *
460 const struct GNUNET_HashCode *element_hash)
461{
462 int ret;
463 struct IBF_Key ibf_key;
464 struct GetElementContext ctx = { { { 0 } }, 0 };
465
466 ctx.hash = *element_hash;
467
468 ibf_key = get_ibf_key (element_hash);
469 ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element,
470 (uint32_t) ibf_key.key_val
471 ,
473 &ctx);
474
475 /* was the iteration aborted because we found the element? */
476 if (GNUNET_SYSERR == ret)
477 {
478 GNUNET_assert (NULL != ctx.k);
479 return ctx.k;
480 }
481 return NULL;
482}
483
484
499static void
501 struct ElementEntry *ee,
502 int received)
503{
504 struct IBF_Key ibf_key;
505 struct KeyEntry *k;
506
508 k = GNUNET_new (struct KeyEntry);
509 k->element = ee;
510 k->ibf_key = ibf_key;
511 k->received = received;
513 GNUNET_CONTAINER_multihashmap32_put (op->state->key_to_element,
514 (uint32_t) ibf_key.key_val
515 ,
516 k,
518}
519
520
524static void
525salt_key (const struct IBF_Key *k_in,
526 uint32_t salt,
527 struct IBF_Key *k_out)
528{
529 int s = salt % 64;
530 uint64_t x = k_in->key_val;
531
532 /* rotate ibf key */
533 x = (x >> s) | (x << (64 - s));
534 k_out->key_val = x;
535}
536
537
541static void
542unsalt_key (const struct IBF_Key *k_in,
543 uint32_t salt,
544 struct IBF_Key *k_out)
545{
546 int s = salt % 64;
547 uint64_t x = k_in->key_val;
548
549 x = (x << s) | (x >> (64 - s));
550 k_out->key_val = x;
551}
552
553
561static int
563 uint32_t key,
564 void *value)
565{
566 struct Operation *op = cls;
567 struct KeyEntry *ke = value;
568 struct IBF_Key salted_key;
569
571 "[OP %p] inserting %lx (hash %s) into ibf\n",
572 op,
573 (unsigned long) ke->ibf_key.key_val,
575 salt_key (&ke->ibf_key,
576 op->state->salt_send,
577 &salted_key);
578 ibf_insert (op->state->local_ibf, salted_key);
579 return GNUNET_YES;
580}
581
582
593static int
595 const struct GNUNET_HashCode *key,
596 void *value)
597{
598 struct Operation *op = cls;
599 struct ElementEntry *ee = value;
600
601 /* make sure that the element belongs to the set at the time
602 * of creating the operation */
603 if (GNUNET_NO ==
605 op))
606 return GNUNET_YES;
609 ee,
610 GNUNET_NO);
611 return GNUNET_YES;
612}
613
614
621static void
623{
624 unsigned int len;
625
626 GNUNET_assert (NULL == op->state->key_to_element);
627 len = GNUNET_CONTAINER_multihashmap_size (op->set->content->elements);
628 op->state->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
629 GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
631 op);
632}
633
634
643static int
645 uint32_t size)
646{
647 GNUNET_assert (NULL != op->state->key_to_element);
648
649 if (NULL != op->state->local_ibf)
650 ibf_destroy (op->state->local_ibf);
651 op->state->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
652 if (NULL == op->state->local_ibf)
653 {
655 "Failed to allocate local IBF\n");
656 return GNUNET_SYSERR;
657 }
658 GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element,
660 op);
661 return GNUNET_OK;
662}
663
664
674static int
676 uint16_t ibf_order)
677{
678 unsigned int buckets_sent = 0;
679 struct InvertibleBloomFilter *ibf;
680
681 if (GNUNET_OK !=
682 prepare_ibf (op, 1 << ibf_order))
683 {
684 /* allocation failed */
685 return GNUNET_SYSERR;
686 }
687
689 "sending ibf of size %u\n",
690 1 << ibf_order);
691
692 {
693 char name[64] = { 0 };
694 snprintf (name, sizeof(name), "# sent IBF (order %u)", ibf_order);
696 }
697
698 ibf = op->state->local_ibf;
699
700 while (buckets_sent < (1 << ibf_order))
701 {
702 unsigned int buckets_in_message;
703 struct GNUNET_MQ_Envelope *ev;
704 struct IBFMessage *msg;
705
706 buckets_in_message = (1 << ibf_order) - buckets_sent;
707 /* limit to maximum */
708 if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE)
709 buckets_in_message = MAX_BUCKETS_PER_MESSAGE;
710
712 buckets_in_message * IBF_BUCKET_SIZE,
714 msg->reserved1 = 0;
715 msg->reserved2 = 0;
716 msg->order = ibf_order;
717 msg->offset = htonl (buckets_sent);
718 msg->salt = htonl (op->state->salt_send);
719 ibf_write_slice (ibf, buckets_sent,
720 buckets_in_message, &msg[1]);
721 buckets_sent += buckets_in_message;
723 "ibf chunk size %u, %u/%u sent\n",
724 buckets_in_message,
725 buckets_sent,
726 1 << ibf_order);
727 GNUNET_MQ_send (op->mq, ev);
728 }
729
730 /* The other peer must decode the IBF, so
731 * we're passive. */
732 op->state->phase = PHASE_INVENTORY_PASSIVE;
733 return GNUNET_OK;
734}
735
736
744static unsigned int
745get_order_from_difference (unsigned int diff)
746{
747 unsigned int ibf_order;
748
749 ibf_order = 2;
750 while (((1 << ibf_order) < (IBF_ALPHA * diff) ||
751 ((1 << ibf_order) < SE_IBF_HASH_NUM)) &&
752 (ibf_order < MAX_IBF_ORDER))
753 ibf_order++;
754 // add one for correction
755 return ibf_order + 1;
756}
757
758
768static int
770 const struct GNUNET_HashCode *key,
771 void *value)
772{
773 struct Operation *op = cls;
774 struct GNUNET_SET_ElementMessage *emsg;
775 struct ElementEntry *ee = value;
776 struct GNUNET_SET_Element *el = &ee->element;
777 struct GNUNET_MQ_Envelope *ev;
778
780 "Sending element %s\n",
781 GNUNET_h2s (key));
782 ev = GNUNET_MQ_msg_extra (emsg,
783 el->size,
785 emsg->element_type = htons (el->element_type);
786 GNUNET_memcpy (&emsg[1],
787 el->data,
788 el->size);
789 GNUNET_MQ_send (op->mq,
790 ev);
791 return GNUNET_YES;
792}
793
794
800static void
802{
803 struct GNUNET_MQ_Envelope *ev;
804
805 op->state->phase = PHASE_FULL_SENDING;
807 "Dedicing to transmit the full set\n");
808 /* FIXME: use a more memory-friendly way of doing this with an
809 iterator, just as we do in the non-full case! */
810 (void) GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
812 op);
814 GNUNET_MQ_send (op->mq,
815 ev);
816}
817
818
825int
827 const struct StrataEstimatorMessage *msg)
828{
829 struct Operation *op = cls;
830 int is_compressed;
831 size_t len;
832
833 if (op->state->phase != PHASE_EXPECT_SE)
834 {
835 GNUNET_break (0);
836 return GNUNET_SYSERR;
837 }
838 is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons (
839 msg->header.type));
840 len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
841 if ((GNUNET_NO == is_compressed) &&
843 {
844 GNUNET_break (0);
845 return GNUNET_SYSERR;
846 }
847 return GNUNET_OK;
848}
849
850
857void
859 const struct StrataEstimatorMessage *msg)
860{
861 struct Operation *op = cls;
862 struct StrataEstimator *remote_se;
863 unsigned int diff;
864 uint64_t other_size;
865 size_t len;
866 int is_compressed;
867
868 is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons (
869 msg->header.type));
871 "# bytes of SE received",
872 ntohs (msg->header.size),
873 GNUNET_NO);
874 len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
875 other_size = GNUNET_ntohll (msg->set_size);
879 if (NULL == remote_se)
880 {
881 /* insufficient resources, fail */
883 return;
884 }
885 if (GNUNET_OK !=
887 len,
888 is_compressed,
889 remote_se))
890 {
891 /* decompression failed */
892 strata_estimator_destroy (remote_se);
894 return;
895 }
896 GNUNET_assert (NULL != op->state->se);
897 diff = strata_estimator_difference (remote_se,
898 op->state->se);
899
900 if (diff > 200)
901 diff = diff * 3 / 2;
902
903 strata_estimator_destroy (remote_se);
904 strata_estimator_destroy (op->state->se);
905 op->state->se = NULL;
907 "got se diff=%d, using ibf size %d\n",
908 diff,
909 1U << get_order_from_difference (diff));
910
911 {
912 char *set_debug;
913
914 set_debug = getenv ("GNUNET_SET_BENCHMARK");
915 if ((NULL != set_debug) &&
916 (0 == strcmp (set_debug, "1")))
917 {
918 FILE *f = fopen ("set.log", "a");
919 fprintf (f, "%llu\n", (unsigned long long) diff);
920 fclose (f);
921 }
922 }
923
924 if ((GNUNET_YES == op->byzantine) &&
925 (other_size < op->byzantine_lower_bound))
926 {
927 GNUNET_break (0);
929 return;
930 }
931
932 if ((GNUNET_YES == op->force_full) ||
933 (diff > op->state->initial_size / 4) ||
934 (0 == other_size))
935 {
937 "Deciding to go for full set transmission (diff=%d, own set=%llu)\n",
938 diff,
939 (unsigned long long) op->state->initial_size);
941 "# of full sends",
942 1,
943 GNUNET_NO);
944 if ((op->state->initial_size <= other_size) ||
945 (0 == other_size))
946 {
948 }
949 else
950 {
951 struct GNUNET_MQ_Envelope *ev;
952
954 "Telling other peer that we expect its full set\n");
955 op->state->phase = PHASE_EXPECT_IBF;
958 GNUNET_MQ_send (op->mq,
959 ev);
960 }
961 }
962 else
963 {
965 "# of ibf sends",
966 1,
967 GNUNET_NO);
968 if (GNUNET_OK !=
969 send_ibf (op,
971 {
972 /* Internal error, best we can do is shut the connection */
974 "Failed to send IBF, closing connection\n");
976 return;
977 }
978 }
979 GNUNET_CADET_receive_done (op->channel);
980}
981
982
990static int
992 uint32_t key,
993 void *value)
994{
995 struct SendElementClosure *sec = cls;
996 struct Operation *op = sec->op;
997 struct KeyEntry *ke = value;
998 struct GNUNET_MQ_Envelope *ev;
999 struct GNUNET_MessageHeader *mh;
1000
1001 /* Detect 32-bit key collision for the 64-bit IBF keys. */
1002 if (ke->ibf_key.key_val != sec->ibf_key.key_val)
1003 return GNUNET_YES;
1004
1006 sizeof(struct GNUNET_HashCode),
1008
1009 GNUNET_assert (NULL != ev);
1010 *(struct GNUNET_HashCode *) &mh[1] = ke->element->element_hash;
1012 "[OP %p] sending element offer (%s) to peer\n",
1013 op,
1015 GNUNET_MQ_send (op->mq, ev);
1016 return GNUNET_YES;
1017}
1018
1019
1026static void
1028 struct IBF_Key ibf_key)
1029{
1030 struct SendElementClosure send_cls;
1031
1032 send_cls.ibf_key = ibf_key;
1033 send_cls.op = op;
1035 op->state->key_to_element,
1036 (uint32_t) ibf_key.
1037 key_val,
1039 &send_cls);
1040}
1041
1042
1050static int
1052{
1053 struct IBF_Key key;
1054 struct IBF_Key last_key;
1055 int side;
1056 unsigned int num_decoded;
1057 struct InvertibleBloomFilter *diff_ibf;
1058
1059 GNUNET_assert (PHASE_INVENTORY_ACTIVE == op->state->phase);
1060
1061 if (GNUNET_OK !=
1062 prepare_ibf (op,
1063 op->state->remote_ibf->size))
1064 {
1065 GNUNET_break (0);
1066 /* allocation failed */
1067 return GNUNET_SYSERR;
1068 }
1069 diff_ibf = ibf_dup (op->state->local_ibf);
1070 ibf_subtract (diff_ibf,
1071 op->state->remote_ibf);
1072
1073 ibf_destroy (op->state->remote_ibf);
1074 op->state->remote_ibf = NULL;
1075
1077 "decoding IBF (size=%u)\n",
1078 diff_ibf->size);
1079
1080 num_decoded = 0;
1081 key.key_val = 0; /* just to avoid compiler thinking we use undef'ed variable */
1082
1083 while (1)
1084 {
1085 int res;
1086 int cycle_detected = GNUNET_NO;
1087
1088 last_key = key;
1089
1090 res = ibf_decode (diff_ibf, &side, &key);
1091 if (res == GNUNET_OK)
1092 {
1094 "decoded ibf key %lx\n",
1095 (unsigned long) key.key_val);
1096 num_decoded += 1;
1097 if ((num_decoded > diff_ibf->size) ||
1098 ((num_decoded > 1) &&
1099 (last_key.key_val == key.key_val)))
1100 {
1102 "detected cyclic ibf (decoded %u/%u)\n",
1103 num_decoded,
1104 diff_ibf->size);
1105 cycle_detected = GNUNET_YES;
1106 }
1107 }
1108 if ((GNUNET_SYSERR == res) ||
1109 (GNUNET_YES == cycle_detected))
1110 {
1111 int next_order;
1112 next_order = 0;
1113 while (1 << next_order < diff_ibf->size)
1114 next_order++;
1115 next_order++;
1116 if (next_order <= MAX_IBF_ORDER)
1117 {
1119 "decoding failed, sending larger ibf (size %u)\n",
1120 1 << next_order);
1122 "# of IBF retries",
1123 1,
1124 GNUNET_NO);
1125 op->state->salt_send++;
1126 if (GNUNET_OK !=
1127 send_ibf (op, next_order))
1128 {
1129 /* Internal error, best we can do is shut the connection */
1131 "Failed to send IBF, closing connection\n");
1133 ibf_destroy (diff_ibf);
1134 return GNUNET_SYSERR;
1135 }
1136 }
1137 else
1138 {
1140 "# of failed union operations (too large)",
1141 1,
1142 GNUNET_NO);
1143 // XXX: Send the whole set, element-by-element
1145 "set union failed: reached ibf limit\n");
1147 ibf_destroy (diff_ibf);
1148 return GNUNET_SYSERR;
1149 }
1150 break;
1151 }
1152 if (GNUNET_NO == res)
1153 {
1154 struct GNUNET_MQ_Envelope *ev;
1155
1157 "transmitted all values, sending DONE\n");
1159 GNUNET_MQ_send (op->mq, ev);
1160 /* We now wait until we get a DONE message back
1161 * and then wait for our MQ to be flushed and all our
1162 * demands be delivered. */
1163 break;
1164 }
1165 if (1 == side)
1166 {
1167 struct IBF_Key unsalted_key;
1168
1169 unsalt_key (&key,
1170 op->state->salt_receive,
1171 &unsalted_key);
1173 unsalted_key);
1174 }
1175 else if (-1 == side)
1176 {
1177 struct GNUNET_MQ_Envelope *ev;
1178 struct InquiryMessage *msg;
1179
1180 /* It may be nice to merge multiple requests, but with CADET's corking it is not worth
1181 * the effort additional complexity. */
1183 sizeof(struct IBF_Key),
1185 msg->salt = htonl (op->state->salt_receive);
1186 GNUNET_memcpy (&msg[1],
1187 &key,
1188 sizeof(struct IBF_Key));
1190 "sending element inquiry for IBF key %lx\n",
1191 (unsigned long) key.key_val);
1192 GNUNET_MQ_send (op->mq, ev);
1193 }
1194 else
1195 {
1196 GNUNET_assert (0);
1197 }
1198 }
1199 ibf_destroy (diff_ibf);
1200 return GNUNET_OK;
1201}
1202
1203
1214int
1216 const struct IBFMessage *msg)
1217{
1218 struct Operation *op = cls;
1219 unsigned int buckets_in_message;
1220
1221 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
1222 {
1223 GNUNET_break_op (0);
1224 return GNUNET_SYSERR;
1225 }
1226 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
1228 if (0 == buckets_in_message)
1229 {
1230 GNUNET_break_op (0);
1231 return GNUNET_SYSERR;
1232 }
1233 if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message
1235 {
1236 GNUNET_break_op (0);
1237 return GNUNET_SYSERR;
1238 }
1239 if (op->state->phase == PHASE_EXPECT_IBF_CONT)
1240 {
1241 if (ntohl (msg->offset) != op->state->ibf_buckets_received)
1242 {
1243 GNUNET_break_op (0);
1244 return GNUNET_SYSERR;
1245 }
1246 if (1 << msg->order != op->state->remote_ibf->size)
1247 {
1248 GNUNET_break_op (0);
1249 return GNUNET_SYSERR;
1250 }
1251 if (ntohl (msg->salt) != op->state->salt_receive)
1252 {
1253 GNUNET_break_op (0);
1254 return GNUNET_SYSERR;
1255 }
1256 }
1257 else if ((op->state->phase != PHASE_INVENTORY_PASSIVE) &&
1258 (op->state->phase != PHASE_EXPECT_IBF))
1259 {
1260 GNUNET_break_op (0);
1261 return GNUNET_SYSERR;
1262 }
1263
1264 return GNUNET_OK;
1265}
1266
1267
1277void
1279 const struct IBFMessage *msg)
1280{
1281 struct Operation *op = cls;
1282 unsigned int buckets_in_message;
1283
1284 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
1286 if ((op->state->phase == PHASE_INVENTORY_PASSIVE) ||
1287 (op->state->phase == PHASE_EXPECT_IBF))
1288 {
1289 op->state->phase = PHASE_EXPECT_IBF_CONT;
1290 GNUNET_assert (NULL == op->state->remote_ibf);
1292 "Creating new ibf of size %u\n",
1293 1 << msg->order);
1294 op->state->remote_ibf = ibf_create (1 << msg->order, SE_IBF_HASH_NUM);
1295 op->state->salt_receive = ntohl (msg->salt);
1297 "Receiving new IBF with salt %u\n",
1298 op->state->salt_receive);
1299 if (NULL == op->state->remote_ibf)
1300 {
1302 "Failed to parse remote IBF, closing connection\n");
1304 return;
1305 }
1306 op->state->ibf_buckets_received = 0;
1307 if (0 != ntohl (msg->offset))
1308 {
1309 GNUNET_break_op (0);
1311 return;
1312 }
1313 }
1314 else
1315 {
1316 GNUNET_assert (op->state->phase == PHASE_EXPECT_IBF_CONT);
1318 "Received more of IBF\n");
1319 }
1320 GNUNET_assert (NULL != op->state->remote_ibf);
1321
1322 ibf_read_slice (&msg[1],
1323 op->state->ibf_buckets_received,
1324 buckets_in_message,
1325 op->state->remote_ibf);
1326 op->state->ibf_buckets_received += buckets_in_message;
1327
1328 if (op->state->ibf_buckets_received == op->state->remote_ibf->size)
1329 {
1331 "received full ibf\n");
1332 op->state->phase = PHASE_INVENTORY_ACTIVE;
1333 if (GNUNET_OK !=
1335 {
1336 /* Internal error, best we can do is shut down */
1338 "Failed to decode IBF, closing connection\n");
1340 return;
1341 }
1342 }
1343 GNUNET_CADET_receive_done (op->channel);
1344}
1345
1346
1355static void
1357 struct GNUNET_SET_Element *element,
1358 int status)
1359{
1360 struct GNUNET_MQ_Envelope *ev;
1361 struct GNUNET_SET_ResultMessage *rm;
1362
1364 "sending element (size %u) to client\n",
1365 element->size);
1366 GNUNET_assert (0 != op->client_request_id);
1368 if (NULL == ev)
1369 {
1370 GNUNET_MQ_discard (ev);
1371 GNUNET_break (0);
1372 return;
1373 }
1374 rm->result_status = htons (status);
1375 rm->request_id = htonl (op->client_request_id);
1376 rm->element_type = htons (element->element_type);
1378 op->state->key_to_element));
1379 GNUNET_memcpy (&rm[1],
1380 element->data,
1381 element->size);
1382 GNUNET_MQ_send (op->set->cs->mq,
1383 ev);
1384}
1385
1386
1393static void
1395{
1396 struct Operation *op = cls;
1397 struct GNUNET_MQ_Envelope *ev;
1398 struct GNUNET_SET_ResultMessage *rm;
1399
1400 if (GNUNET_YES == op->state->client_done_sent)
1401 {
1402 return;
1403 }
1404
1405 if (PHASE_DONE != op->state->phase)
1406 {
1408 "Union operation failed\n");
1410 "# Union operations failed",
1411 1,
1412 GNUNET_NO);
1415 rm->request_id = htonl (op->client_request_id);
1416 rm->element_type = htons (0);
1417 GNUNET_MQ_send (op->set->cs->mq,
1418 ev);
1419 return;
1420 }
1421
1422 op->state->client_done_sent = GNUNET_YES;
1423
1425 "# Union operations succeeded",
1426 1,
1427 GNUNET_NO);
1429 "Signalling client that union operation is done\n");
1430 ev = GNUNET_MQ_msg (rm,
1432 rm->request_id = htonl (op->client_request_id);
1434 rm->element_type = htons (0);
1436 op->state->key_to_element));
1437 GNUNET_MQ_send (op->set->cs->mq,
1438 ev);
1439}
1440
1441
1447static void
1449{
1450 unsigned int num_demanded;
1451
1452 num_demanded = GNUNET_CONTAINER_multihashmap_size (
1453 op->state->demanded_hashes);
1454
1455 if (PHASE_FINISH_WAITING == op->state->phase)
1456 {
1458 "In PHASE_FINISH_WAITING, pending %u demands\n",
1459 num_demanded);
1460 if (0 == num_demanded)
1461 {
1462 struct GNUNET_MQ_Envelope *ev;
1463
1464 op->state->phase = PHASE_DONE;
1466 GNUNET_MQ_send (op->mq,
1467 ev);
1468 /* We now wait until the other peer sends P2P_OVER
1469 * after it got all elements from us. */
1470 }
1471 }
1472 if (PHASE_FINISH_CLOSING == op->state->phase)
1473 {
1475 "In PHASE_FINISH_CLOSING, pending %u demands\n",
1476 num_demanded);
1477 if (0 == num_demanded)
1478 {
1479 op->state->phase = PHASE_DONE;
1482 }
1483 }
1484}
1485
1486
1493int
1495 const struct GNUNET_SET_ElementMessage *emsg)
1496{
1497 struct Operation *op = cls;
1498
1499 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
1500 {
1501 GNUNET_break_op (0);
1502 return GNUNET_SYSERR;
1503 }
1504 if (0 == GNUNET_CONTAINER_multihashmap_size (op->state->demanded_hashes))
1505 {
1506 GNUNET_break_op (0);
1507 return GNUNET_SYSERR;
1508 }
1509 return GNUNET_OK;
1510}
1511
1512
1521void
1523 const struct GNUNET_SET_ElementMessage *emsg)
1524{
1525 struct Operation *op = cls;
1526 struct ElementEntry *ee;
1527 struct KeyEntry *ke;
1528 uint16_t element_size;
1529
1530 element_size = ntohs (emsg->header.size) - sizeof(struct
1532 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
1533 GNUNET_memcpy (&ee[1],
1534 &emsg[1],
1535 element_size);
1536 ee->element.size = element_size;
1537 ee->element.data = &ee[1];
1538 ee->element.element_type = ntohs (emsg->element_type);
1539 ee->remote = GNUNET_YES;
1541 &ee->element_hash);
1542 if (GNUNET_NO ==
1543 GNUNET_CONTAINER_multihashmap_remove (op->state->demanded_hashes,
1544 &ee->element_hash,
1545 NULL))
1546 {
1547 /* We got something we didn't demand, since it's not in our map. */
1548 GNUNET_break_op (0);
1550 return;
1551 }
1552
1554 "Got element (size %u, hash %s) from peer\n",
1555 (unsigned int) element_size,
1556 GNUNET_h2s (&ee->element_hash));
1557
1559 "# received elements",
1560 1,
1561 GNUNET_NO);
1563 "# exchanged elements",
1564 1,
1565 GNUNET_NO);
1566
1567 op->state->received_total++;
1568
1569 ke = op_get_element (op, &ee->element_hash);
1570 if (NULL != ke)
1571 {
1572 /* Got repeated element. Should not happen since
1573 * we track demands. */
1575 "# repeated elements",
1576 1,
1577 GNUNET_NO);
1578 ke->received = GNUNET_YES;
1579 GNUNET_free (ee);
1580 }
1581 else
1582 {
1584 "Registering new element from remote peer\n");
1585 op->state->received_fresh++;
1587 /* only send results immediately if the client wants it */
1588 switch (op->result_mode)
1589 {
1592 break;
1593
1596 break;
1597
1598 default:
1599 /* Result mode not supported, should have been caught earlier. */
1600 GNUNET_break (0);
1601 break;
1602 }
1603 }
1604
1605 if ((op->state->received_total > 8) &&
1606 (op->state->received_fresh < op->state->received_total / 3))
1607 {
1608 /* The other peer gave us lots of old elements, there's something wrong. */
1609 GNUNET_break_op (0);
1611 return;
1612 }
1613 GNUNET_CADET_receive_done (op->channel);
1614 maybe_finish (op);
1615}
1616
1617
1624int
1626 const struct GNUNET_SET_ElementMessage *emsg)
1627{
1628 struct Operation *op = cls;
1629
1630 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
1631 {
1632 GNUNET_break_op (0);
1633 return GNUNET_SYSERR;
1634 }
1635 // FIXME: check that we expect full elements here?
1636 return GNUNET_OK;
1637}
1638
1639
1646void
1648 const struct GNUNET_SET_ElementMessage *emsg)
1649{
1650 struct Operation *op = cls;
1651 struct ElementEntry *ee;
1652 struct KeyEntry *ke;
1653 uint16_t element_size;
1654
1655 element_size = ntohs (emsg->header.size) - sizeof(struct
1657 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
1658 GNUNET_memcpy (&ee[1], &emsg[1], element_size);
1659 ee->element.size = element_size;
1660 ee->element.data = &ee[1];
1661 ee->element.element_type = ntohs (emsg->element_type);
1662 ee->remote = GNUNET_YES;
1664
1666 "Got element (full diff, size %u, hash %s) from peer\n",
1667 (unsigned int) element_size,
1668 GNUNET_h2s (&ee->element_hash));
1669
1671 "# received elements",
1672 1,
1673 GNUNET_NO);
1675 "# exchanged elements",
1676 1,
1677 GNUNET_NO);
1678
1679 op->state->received_total++;
1680
1681 ke = op_get_element (op, &ee->element_hash);
1682 if (NULL != ke)
1683 {
1684 /* Got repeated element. Should not happen since
1685 * we track demands. */
1687 "# repeated elements",
1688 1,
1689 GNUNET_NO);
1690 ke->received = GNUNET_YES;
1691 GNUNET_free (ee);
1692 }
1693 else
1694 {
1696 "Registering new element from remote peer\n");
1697 op->state->received_fresh++;
1699 /* only send results immediately if the client wants it */
1700 switch (op->result_mode)
1701 {
1704 break;
1705
1708 break;
1709
1710 default:
1711 /* Result mode not supported, should have been caught earlier. */
1712 GNUNET_break (0);
1713 break;
1714 }
1715 }
1716
1717 if ((GNUNET_YES == op->byzantine) &&
1718 (op->state->received_total > 384 + op->state->received_fresh * 4) &&
1719 (op->state->received_fresh < op->state->received_total / 6))
1720 {
1721 /* The other peer gave us lots of old elements, there's something wrong. */
1723 "Other peer sent only %llu/%llu fresh elements, failing operation\n",
1724 (unsigned long long) op->state->received_fresh,
1725 (unsigned long long) op->state->received_total);
1726 GNUNET_break_op (0);
1728 return;
1729 }
1730 GNUNET_CADET_receive_done (op->channel);
1731}
1732
1733
1741int
1743 const struct InquiryMessage *msg)
1744{
1745 struct Operation *op = cls;
1746 unsigned int num_keys;
1747
1748 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
1749 {
1750 GNUNET_break_op (0);
1751 return GNUNET_SYSERR;
1752 }
1753 if (op->state->phase != PHASE_INVENTORY_PASSIVE)
1754 {
1755 GNUNET_break_op (0);
1756 return GNUNET_SYSERR;
1757 }
1758 num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
1759 / sizeof(struct IBF_Key);
1760 if ((ntohs (msg->header.size) - sizeof(struct InquiryMessage))
1761 != num_keys * sizeof(struct IBF_Key))
1762 {
1763 GNUNET_break_op (0);
1764 return GNUNET_SYSERR;
1765 }
1766 return GNUNET_OK;
1767}
1768
1769
1777void
1779 const struct InquiryMessage *msg)
1780{
1781 struct Operation *op = cls;
1782 const struct IBF_Key *ibf_key;
1783 unsigned int num_keys;
1784
1786 "Received union inquiry\n");
1787 num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
1788 / sizeof(struct IBF_Key);
1789 ibf_key = (const struct IBF_Key *) &msg[1];
1790 while (0 != num_keys--)
1791 {
1792 struct IBF_Key unsalted_key;
1793
1794 unsalt_key (ibf_key,
1795 ntohl (msg->salt),
1796 &unsalted_key);
1798 unsalted_key);
1799 ibf_key++;
1800 }
1801 GNUNET_CADET_receive_done (op->channel);
1802}
1803
1804
1815static int
1817 uint32_t key,
1818 void *value)
1819{
1820 struct Operation *op = cls;
1821 struct KeyEntry *ke = value;
1822 struct GNUNET_MQ_Envelope *ev;
1823 struct GNUNET_SET_ElementMessage *emsg;
1824 struct ElementEntry *ee = ke->element;
1825
1826 if (GNUNET_YES == ke->received)
1827 return GNUNET_YES;
1828 ev = GNUNET_MQ_msg_extra (emsg,
1829 ee->element.size,
1831 GNUNET_memcpy (&emsg[1],
1832 ee->element.data,
1833 ee->element.size);
1834 emsg->element_type = htons (ee->element.element_type);
1835 GNUNET_MQ_send (op->mq,
1836 ev);
1837 return GNUNET_YES;
1838}
1839
1840
1847void
1849 const struct GNUNET_MessageHeader *mh)
1850{
1851 struct Operation *op = cls;
1852
1854 "Received request for full set transmission\n");
1855 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
1856 {
1857 GNUNET_break_op (0);
1859 return;
1860 }
1861 if (PHASE_EXPECT_IBF != op->state->phase)
1862 {
1863 GNUNET_break_op (0);
1865 return;
1866 }
1867
1868 // FIXME: we need to check that our set is larger than the
1869 // byzantine_lower_bound by some threshold
1870 send_full_set (op);
1871 GNUNET_CADET_receive_done (op->channel);
1872}
1873
1874
1881void
1883 const struct GNUNET_MessageHeader *mh)
1884{
1885 struct Operation *op = cls;
1886
1887 switch (op->state->phase)
1888 {
1889 case PHASE_EXPECT_IBF:
1890 {
1891 struct GNUNET_MQ_Envelope *ev;
1892
1894 "got FULL DONE, sending elements that other peer is missing\n");
1895
1896 /* send all the elements that did not come from the remote peer */
1897 GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element,
1899 op);
1900
1902 GNUNET_MQ_send (op->mq,
1903 ev);
1904 op->state->phase = PHASE_DONE;
1905 /* we now wait until the other peer sends us the OVER message*/
1906 }
1907 break;
1908
1909 case PHASE_FULL_SENDING:
1910 {
1912 "got FULL DONE, finishing\n");
1913 /* We sent the full set, and got the response for that. We're done. */
1914 op->state->phase = PHASE_DONE;
1915 GNUNET_CADET_receive_done (op->channel);
1918 return;
1919 }
1920 break;
1921
1922 default:
1924 "Handle full done phase is %u\n",
1925 (unsigned) op->state->phase);
1926 GNUNET_break_op (0);
1928 return;
1929 }
1930 GNUNET_CADET_receive_done (op->channel);
1931}
1932
1933
1942int
1944 const struct GNUNET_MessageHeader *mh)
1945{
1946 struct Operation *op = cls;
1947 unsigned int num_hashes;
1948
1949 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
1950 {
1951 GNUNET_break_op (0);
1952 return GNUNET_SYSERR;
1953 }
1954 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
1955 / sizeof(struct GNUNET_HashCode);
1956 if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
1957 != num_hashes * sizeof(struct GNUNET_HashCode))
1958 {
1959 GNUNET_break_op (0);
1960 return GNUNET_SYSERR;
1961 }
1962 return GNUNET_OK;
1963}
1964
1965
1973void
1975 const struct GNUNET_MessageHeader *mh)
1976{
1977 struct Operation *op = cls;
1978 struct ElementEntry *ee;
1979 struct GNUNET_SET_ElementMessage *emsg;
1980 const struct GNUNET_HashCode *hash;
1981 unsigned int num_hashes;
1982 struct GNUNET_MQ_Envelope *ev;
1983
1984 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
1985 / sizeof(struct GNUNET_HashCode);
1986 for (hash = (const struct GNUNET_HashCode *) &mh[1];
1987 num_hashes > 0;
1988 hash++, num_hashes--)
1989 {
1990 ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
1991 hash);
1992 if (NULL == ee)
1993 {
1994 /* Demand for non-existing element. */
1995 GNUNET_break_op (0);
1997 return;
1998 }
2000 {
2001 /* Probably confused lazily copied sets. */
2002 GNUNET_break_op (0);
2004 return;
2005 }
2006 ev = GNUNET_MQ_msg_extra (emsg, ee->element.size,
2008 GNUNET_memcpy (&emsg[1], ee->element.data, ee->element.size);
2009 emsg->reserved = htons (0);
2010 emsg->element_type = htons (ee->element.element_type);
2012 "[OP %p] Sending demanded element (size %u, hash %s) to peer\n",
2013 op,
2014 (unsigned int) ee->element.size,
2015 GNUNET_h2s (&ee->element_hash));
2016 GNUNET_MQ_send (op->mq, ev);
2018 "# exchanged elements",
2019 1,
2020 GNUNET_NO);
2021
2022 switch (op->result_mode)
2023 {
2025 /* Nothing to do. */
2026 break;
2027
2030 break;
2031
2032 default:
2033 /* Result mode not supported, should have been caught earlier. */
2034 GNUNET_break (0);
2035 break;
2036 }
2037 }
2038 GNUNET_CADET_receive_done (op->channel);
2039}
2040
2041
2049int
2051 const struct GNUNET_MessageHeader *mh)
2052{
2053 struct Operation *op = cls;
2054 unsigned int num_hashes;
2055
2056 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
2057 {
2058 GNUNET_break_op (0);
2059 return GNUNET_SYSERR;
2060 }
2061 /* look up elements and send them */
2062 if ((op->state->phase != PHASE_INVENTORY_PASSIVE) &&
2063 (op->state->phase != PHASE_INVENTORY_ACTIVE))
2064 {
2065 GNUNET_break_op (0);
2066 return GNUNET_SYSERR;
2067 }
2068 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2069 / sizeof(struct GNUNET_HashCode);
2070 if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader)) !=
2071 num_hashes * sizeof(struct GNUNET_HashCode))
2072 {
2073 GNUNET_break_op (0);
2074 return GNUNET_SYSERR;
2075 }
2076 return GNUNET_OK;
2077}
2078
2079
2087void
2089 const struct GNUNET_MessageHeader *mh)
2090{
2091 struct Operation *op = cls;
2092 const struct GNUNET_HashCode *hash;
2093 unsigned int num_hashes;
2094
2095 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2096 / sizeof(struct GNUNET_HashCode);
2097 for (hash = (const struct GNUNET_HashCode *) &mh[1];
2098 num_hashes > 0;
2099 hash++, num_hashes--)
2100 {
2101 struct ElementEntry *ee;
2102 struct GNUNET_MessageHeader *demands;
2103 struct GNUNET_MQ_Envelope *ev;
2104
2105 ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
2106 hash);
2107 if (NULL != ee)
2109 continue;
2110
2111 if (GNUNET_YES ==
2112 GNUNET_CONTAINER_multihashmap_contains (op->state->demanded_hashes,
2113 hash))
2114 {
2116 "Skipped sending duplicate demand\n");
2117 continue;
2118 }
2119
2122 op->state->demanded_hashes,
2123 hash,
2124 NULL,
2126
2128 "[OP %p] Requesting element (hash %s)\n",
2129 op, GNUNET_h2s (hash));
2130 ev = GNUNET_MQ_msg_header_extra (demands,
2131 sizeof(struct GNUNET_HashCode),
2133 GNUNET_memcpy (&demands[1],
2134 hash,
2135 sizeof(struct GNUNET_HashCode));
2136 GNUNET_MQ_send (op->mq, ev);
2137 }
2138 GNUNET_CADET_receive_done (op->channel);
2139}
2140
2141
2148void
2150 const struct GNUNET_MessageHeader *mh)
2151{
2152 struct Operation *op = cls;
2153
2154 if (GNUNET_SET_OPERATION_UNION != op->set->operation)
2155 {
2156 GNUNET_break_op (0);
2158 return;
2159 }
2160 switch (op->state->phase)
2161 {
2163 /* We got all requests, but still have to send our elements in response. */
2164 op->state->phase = PHASE_FINISH_WAITING;
2165
2167 "got DONE (as passive partner), waiting for our demands to be satisfied\n");
2168 /* The active peer is done sending offers
2169 * and inquiries. This means that all
2170 * our responses to that (demands and offers)
2171 * must be in flight (queued or in mesh).
2172 *
2173 * We should notify the active peer once
2174 * all our demands are satisfied, so that the active
2175 * peer can quit if we gave it everything.
2176 */GNUNET_CADET_receive_done (op->channel);
2177 maybe_finish (op);
2178 return;
2179
2182 "got DONE (as active partner), waiting to finish\n");
2183 /* All demands of the other peer are satisfied,
2184 * and we processed all offers, thus we know
2185 * exactly what our demands must be.
2186 *
2187 * We'll close the channel
2188 * to the other peer once our demands are met.
2189 */op->state->phase = PHASE_FINISH_CLOSING;
2190 GNUNET_CADET_receive_done (op->channel);
2191 maybe_finish (op);
2192 return;
2193
2194 default:
2195 GNUNET_break_op (0);
2197 return;
2198 }
2199}
2200
2201
2202void
2204 const struct GNUNET_MessageHeader *mh)
2205{
2206 send_client_done (cls);
2207}
2208
2209
2217static struct OperationState *
2219 const struct GNUNET_MessageHeader *opaque_context)
2220{
2221 struct OperationState *state;
2222 struct GNUNET_MQ_Envelope *ev;
2224
2227 opaque_context);
2228 if (NULL == ev)
2229 {
2230 /* the context message is too large */
2231 GNUNET_break (0);
2232 return NULL;
2233 }
2234 state = GNUNET_new (struct OperationState);
2235 state->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32,
2236 GNUNET_NO);
2237 /* copy the current generation's strata estimator for this operation */
2238 state->se = strata_estimator_dup (op->set->state->se);
2239 /* we started the operation, thus we have to send the operation request */
2240 state->phase = PHASE_EXPECT_SE;
2241 state->salt_receive = state->salt_send = 42; // FIXME?????
2243 "Initiating union operation evaluation\n");
2245 "# of total union operations",
2246 1,
2247 GNUNET_NO);
2249 "# of initiated union operations",
2250 1,
2251 GNUNET_NO);
2252 msg->operation = htonl (GNUNET_SET_OPERATION_UNION);
2253 GNUNET_MQ_send (op->mq,
2254 ev);
2255
2256 if (NULL != opaque_context)
2258 "sent op request with context message\n");
2259 else
2261 "sent op request without context message\n");
2262
2263 op->state = state;
2266 state->key_to_element);
2267 return state;
2268}
2269
2270
2277static struct OperationState *
2279{
2280 struct OperationState *state;
2281 const struct StrataEstimator *se;
2282 struct GNUNET_MQ_Envelope *ev;
2283 struct StrataEstimatorMessage *strata_msg;
2284 char *buf;
2285 size_t len;
2286 uint16_t type;
2287
2289 "accepting set union operation\n");
2291 "# of accepted union operations",
2292 1,
2293 GNUNET_NO);
2295 "# of total union operations",
2296 1,
2297 GNUNET_NO);
2298
2299 state = GNUNET_new (struct OperationState);
2300 state->se = strata_estimator_dup (op->set->state->se);
2301 state->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32,
2302 GNUNET_NO);
2303 state->salt_receive = state->salt_send = 42; // FIXME?????
2304 op->state = state;
2307 state->key_to_element);
2308
2309 /* kick off the operation */
2310 se = state->se;
2312 len = strata_estimator_write (se,
2313 buf);
2314 if (len < se->strata_count * IBF_BUCKET_SIZE * se->ibf_size)
2316 else
2318 ev = GNUNET_MQ_msg_extra (strata_msg,
2319 len,
2320 type);
2321 GNUNET_memcpy (&strata_msg[1],
2322 buf,
2323 len);
2324 GNUNET_free (buf);
2325 strata_msg->set_size
2327 op->set->content->elements));
2328 GNUNET_MQ_send (op->mq,
2329 ev);
2330 state->phase = PHASE_EXPECT_IBF;
2331 return state;
2332}
2333
2334
2343static struct SetState *
2345{
2346 struct SetState *set_state;
2347
2349 "union set created\n");
2350 set_state = GNUNET_new (struct SetState);
2353 if (NULL == set_state->se)
2354 {
2356 "Failed to allocate strata estimator\n");
2357 GNUNET_free (set_state);
2358 return NULL;
2359 }
2360 return set_state;
2361}
2362
2363
2370static void
2371union_add (struct SetState *set_state,
2372 struct ElementEntry *ee)
2373{
2374 strata_estimator_insert (set_state->se,
2375 get_ibf_key (&ee->element_hash));
2376}
2377
2378
2386static void
2387union_remove (struct SetState *set_state,
2388 struct ElementEntry *ee)
2389{
2390 strata_estimator_remove (set_state->se,
2391 get_ibf_key (&ee->element_hash));
2392}
2393
2394
2400static void
2401union_set_destroy (struct SetState *set_state)
2402{
2403 if (NULL != set_state->se)
2404 {
2405 strata_estimator_destroy (set_state->se);
2406 set_state->se = NULL;
2407 }
2408 GNUNET_free (set_state);
2409}
2410
2411
2418static struct SetState *
2420{
2421 struct SetState *new_state;
2422
2423 GNUNET_assert ((NULL != state) &&
2424 (NULL != state->se));
2425 new_state = GNUNET_new (struct SetState);
2426 new_state->se = strata_estimator_dup (state->se);
2427
2428 return new_state;
2429}
2430
2431
2437static void
2444
2445
2452const struct SetVT *
2454{
2455 static const struct SetVT union_vt = {
2457 .add = &union_add,
2458 .remove = &union_remove,
2459 .destroy_set = &union_set_destroy,
2460 .evaluate = &union_evaluate,
2461 .accept = &union_accept,
2462 .cancel = &union_op_cancel,
2463 .copy_state = &union_copy_state,
2464 .channel_death = &union_channel_death
2465 };
2466
2467 return &union_vt;
2468}
struct GNUNET_MessageHeader * msg
Definition 005.c:2
void ibf_subtract(struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2)
Subtract ibf2 from ibf1, storing the result in ibf1.
Definition ibf.c:357
int ibf_decode(struct InvertibleBloomFilter *ibf, int *ret_side, struct IBF_Key *ret_id)
Decode and remove an element from the IBF, if possible.
Definition ibf.c:229
void ibf_read_slice(const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf)
Read buckets from a buffer into an ibf.
Definition ibf.c:324
void ibf_write_slice(const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf)
Write buckets from an ibf to a buffer.
Definition ibf.c:291
void ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
Insert a key into an IBF.
Definition ibf.c:168
struct InvertibleBloomFilter * ibf_dup(const struct InvertibleBloomFilter *ibf)
Create a copy of an IBF, the copy has to be destroyed properly.
Definition ibf.c:380
struct InvertibleBloomFilter * ibf_create(uint32_t size, uint8_t hash_num)
Create an invertible bloom filter.
Definition ibf.c:80
void ibf_destroy(struct InvertibleBloomFilter *ibf)
Destroy all resources associated with the invertible bloom filter.
Definition ibf.c:404
#define IBF_BUCKET_SIZE
Size of one ibf bucket in bytes.
Definition ibf.h:72
char * getenv()
static struct GNUNET_ARM_Operation * op
Current operation.
Definition gnunet-arm.c:143
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_CADET_Handle * mh
Cadet handle.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_FS_Handle * ctx
static char * name
Name (label) of the records to list.
static int state
The current state of the parser.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static int status
The program status; 0 for success.
Definition gnunet-nse.c:39
static struct GNUNET_IDENTITY_EgoLookup * el
Handle for our ego lookup.
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calculations.
void _GSS_operation_destroy2(struct Operation *op)
This function probably should not exist and be replaced by inlining more specific logic in the variou...
int _GSS_is_element_of_operation(struct ElementEntry *ee, struct Operation *op)
Is element ee part of the set used by op?
struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
void _GSS_operation_destroy(struct Operation *op, int gc)
Destroy the given operation.
common components for the implementation the different set operations
Peer-to-Peer messages for gnunet set.
void handle_union_p2p_strata_estimator(void *cls, const struct StrataEstimatorMessage *msg)
Handle a strata estimator from a remote peer.
void handle_union_p2p_offer(void *cls, const struct GNUNET_MessageHeader *mh)
Handle offers (of struct GNUNET_HashCodes) and respond with demands (of struct GNUNET_HashCodes).
int check_union_p2p_elements(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Check an element message from a remote peer.
static void union_set_destroy(struct SetState *set_state)
Destroy a set that supports the union operation.
#define MAX_BUCKETS_PER_MESSAGE
Number of buckets that can be transmitted in one message.
static int decode_and_send(struct Operation *op)
Decode which elements are missing on each side, and send the appropriate offers and inquiries.
void handle_union_p2p_ibf(void *cls, const struct IBFMessage *msg)
Handle an IBF message from a remote peer.
static int send_full_element_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Send a set element.
static struct OperationState * union_accept(struct Operation *op)
Accept an union operation request from a remote peer.
static struct OperationState * union_evaluate(struct Operation *op, const struct GNUNET_MessageHeader *opaque_context)
Initiate operation to evaluate a set union with a remote peer.
static void send_full_set(struct Operation *op)
Switch to full set transmission for op.
int check_union_p2p_strata_estimator(void *cls, const struct StrataEstimatorMessage *msg)
Handle a strata estimator from a remote peer.
int check_union_p2p_full_element(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Check a full element message from a remote peer.
void handle_union_p2p_full_element(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Handle an element message from a remote peer.
static struct IBF_Key get_ibf_key(const struct GNUNET_HashCode *src)
Derive the IBF key from a hash code and a salt.
static void maybe_finish(struct Operation *op)
Tests if the operation is finished, and if so notify.
static int init_key_to_element_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator for initializing the key-to-element mapping of a union operation.
void handle_union_p2p_done(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a done message from a remote peer.
static int send_offers_iterator(void *cls, uint32_t key, void *value)
Iterator to send elements to a remote peer.
static struct SetState * union_set_create(void)
Create a new set supporting the union operation.
const struct SetVT * _GSS_union_vt()
Get the table with implementing functions for set union.
#define SE_IBF_SIZE
Size of the IBFs in the strata estimator.
static int send_missing_full_elements_iter(void *cls, uint32_t key, void *value)
Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries.
int check_union_p2p_offer(void *cls, const struct GNUNET_MessageHeader *mh)
Check offer (of struct GNUNET_HashCodes).
void handle_union_p2p_over(void *cls, const struct GNUNET_MessageHeader *mh)
Handle an over message from a remote peer.
static void union_remove(struct SetState *set_state, struct ElementEntry *ee)
Remove the element given in the element message from the set.
static int send_ibf(struct Operation *op, uint16_t ibf_order)
Send an ibf of appropriate size.
static struct SetState * union_copy_state(struct SetState *state)
Copy union-specific set state.
static void union_channel_death(struct Operation *op)
Handle case where channel went down for an operation.
#define IBF_ALPHA
Number of buckets used in the ibf per estimated difference.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation.
static void send_client_done(void *cls)
Signal to the client that the operation has finished and destroy the operation.
void handle_union_p2p_inquiry(void *cls, const struct InquiryMessage *msg)
Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s).
static void unsalt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
FIXME.
static void salt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
FIXME.
static int prepare_ibf(struct Operation *op, uint32_t size)
Create an ibf with the operation's elements of the specified size.
static void op_register_element(struct Operation *op, struct ElementEntry *ee, int received)
Insert an element into the union operation's key-to-element mapping.
static void union_add(struct SetState *set_state, struct ElementEntry *ee)
Add the element from the given element message to the set.
static void initialize_key_to_element(struct Operation *op)
Initialize the IBF key to element mapping local to this set operation.
void handle_union_p2p_elements(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Handle an element message from a remote peer.
void handle_union_p2p_demand(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a demand by the other peer for elements based on a list of struct GNUNET_HashCodes.
static void send_offers_for_key(struct Operation *op, struct IBF_Key ibf_key)
Send offers (in the form of GNUNET_Hash-es) to the remote peer for the given IBF key.
void handle_union_p2p_full_done(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a "full done" message.
static int destroy_key_to_element_iter(void *cls, uint32_t key, void *value)
Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries.
static void union_op_cancel(struct Operation *op)
Destroy the union operation.
#define SE_STRATA_COUNT
Number of IBFs in a strata estimator.
int check_union_p2p_demand(void *cls, const struct GNUNET_MessageHeader *mh)
Check a demand by the other peer for elements based on a list of struct GNUNET_HashCodes.
int check_union_p2p_ibf(void *cls, const struct IBFMessage *msg)
Check an IBF message from a remote peer.
#define LOG(kind,...)
static struct KeyEntry * op_get_element(struct Operation *op, const struct GNUNET_HashCode *element_hash)
Determine whether the given element is already in the operation's element set.
UnionOperationPhase
Current phase we are in for a union operation.
@ PHASE_INVENTORY_PASSIVE
The other peer is decoding the IBF we just sent.
@ PHASE_FINISH_CLOSING
The protocol is almost finished, but we still have to flush our message queue and/or expect some elem...
@ PHASE_DONE
In the ultimate phase, we wait until our demands are satisfied and then quit (sending another DONE me...
@ PHASE_EXPECT_SE
We sent the request message, and expect a strata estimator.
@ PHASE_FINISH_WAITING
In the penultimate phase, we wait until all our demands are satisfied.
@ PHASE_EXPECT_IBF_CONT
Continuation for multi part IBFs.
@ PHASE_FULL_SENDING
After sending the full set, wait for responses with the elements that the local peer is missing.
@ PHASE_EXPECT_IBF
We sent the strata estimator, and expect an IBF.
@ PHASE_INVENTORY_ACTIVE
We are decoding an IBF.
static void send_client_element(struct Operation *op, struct GNUNET_SET_Element *element, int status)
Send a result message to the client indicating that there is a new element.
#define SE_IBF_HASH_NUM
The hash num parameter for the difference digests and strata estimators.
void handle_union_p2p_request_full(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a request for full set transmission.
static int op_get_element_iterator(void *cls, uint32_t key, void *value)
Iterator over the mapping from IBF keys to element entries.
static int prepare_ibf_iterator(void *cls, uint32_t key, void *value)
Insert a key into an ibf.
int check_union_p2p_inquiry(void *cls, const struct InquiryMessage *msg)
Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s).
#define MAX_IBF_ORDER
The maximum size of an ibf we use is 2^(MAX_IBF_ORDER).
static unsigned int get_order_from_difference(unsigned int diff)
Compute the necessary order of an ibf from the size of the symmetric set difference.
two-peer set operations
unsigned int strata_estimator_difference(const struct StrataEstimator *se1, const struct StrataEstimator *se2)
Estimate set difference with two strata estimators, i.e.
struct StrataEstimator * strata_estimator_create(unsigned int strata_count, uint32_t ibf_size, uint8_t ibf_hashnum)
Create a new strata estimator with the given parameters.
void strata_estimator_destroy(struct StrataEstimator *se)
Destroy a strata estimator, free all of its resources.
int strata_estimator_read(const void *buf, size_t buf_len, int is_compressed, struct StrataEstimator *se)
Read strata from the buffer into the given strata estimator.
size_t strata_estimator_write(const struct StrataEstimator *se, void *buf)
Write the given strata estimator to the buffer.
void strata_estimator_insert(struct StrataEstimator *se, struct IBF_Key key)
Add a key to the strata estimator.
struct StrataEstimator * strata_estimator_dup(struct StrataEstimator *se)
Make a copy of a strata estimator.
void strata_estimator_remove(struct StrataEstimator *se, struct IBF_Key key)
Remove a key from the strata estimator.
API to create, modify and access statistics.
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Indicate readiness to receive the next message on a channel.
Definition cadet_api.c:875
#define GNUNET_CRYPTO_hkdf_gnunet(result, out_len, xts, xts_len, skm, skm_len,...)
A peculiar HKDF instantiation that tried to mimic Truncated NMAC.
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
unsigned int GNUNET_CONTAINER_multihashmap32_size(const struct GNUNET_CONTAINER_MultiHashMap32 *map)
Get the number of key-value pairs in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition mq.c:285
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_msg_nested_mh(mvar, type, mh)
Allocate a GNUNET_MQ_Envelope, and append a payload message after the given message struct.
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MQ_msg_header_extra(mh, esize, type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header and extra space.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OFFER
Tell the other peer which hashes match a given IBF key.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY
Tell the other peer to send us a list of hashes that match an IBF key.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE
Strata estimator.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF
Invertible bloom filter.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE
Set operation is done.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC
Compressed strata estimator.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT
Send a set element, not as response to a demand but because we're sending the full set.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL
Demand the whole element from the other peer, given only the hash code.
#define GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS
Actual set elements.
#define GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
Request a set operation from a remote peer.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND
Demand the whole element from the other peer, given only the hash code.
#define GNUNET_MESSAGE_TYPE_SET_RESULT
Create an empty set.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE
Request all missing elements from the other peer, based on their sets and the elements we previously ...
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition set_api.c:1184
@ GNUNET_SET_STATUS_OK
Everything went ok, we are transmitting an element of the result (in set, or to be removed from set,...
@ GNUNET_SET_STATUS_FAILURE
The other peer refused to to the operation with us, or something went wrong.
@ GNUNET_SET_STATUS_ADD_REMOTE
Element should be added to the result set of the remote peer, i.e.
@ GNUNET_SET_STATUS_DONE
Success, all elements have been sent (and received).
@ GNUNET_SET_STATUS_ADD_LOCAL
Element should be added to the result set of the local peer, i.e.
@ GNUNET_SET_RESULT_SYMMETRIC
Client gets notified of the required changes for both the local and the remote set.
@ GNUNET_SET_RESULT_ADDED
Client gets only elements that have been added to the set.
@ GNUNET_SET_OPERATION_UNION
Set union, return all elements that are in at least one of the sets.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static unsigned int size
Size of the "table".
Definition peer.c:68
Information about an element element in the set.
int remote
GNUNET_YES if the element is a remote element, and does not belong to the operation's set.
struct GNUNET_SET_Element element
The actual element.
struct GNUNET_HashCode element_hash
Hash of the element.
Internal representation of the hash map.
Internal representation of the hash map.
A 512-bit hashcode.
Header for all communications.
Message sent by client to the service to add or remove an element to/from the set.
Definition set.h:281
uint16_t element_type
Type of the element to add or remove.
Definition set.h:291
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_ADD or GNUNET_MESSAGE_TYPE_SET_REMOVE.
Definition set.h:286
uint16_t reserved
For alignment, always zero.
Definition set.h:296
Element stored in a set.
uint16_t size
Number of bytes in the buffer pointed to by data.
const void * data
Actual data of the element.
uint16_t element_type
Application-specific element type.
Message sent by the service to the client to indicate an element that is removed (set intersection) o...
Definition set.h:245
uint32_t request_id
id the result belongs to
Definition set.h:259
uint16_t result_status
Was the evaluation successful? Contains an enum GNUNET_SET_Status in NBO.
Definition set.h:265
uint16_t element_type
Type of the element attached to the message, if any.
Definition set.h:270
uint64_t current_size
Current set size.
Definition set.h:254
Context for op_get_element_iterator.
struct GNUNET_HashCode hash
FIXME.
struct KeyEntry * k
FIXME.
Message containing buckets of an invertible bloom filter.
Keys that can be inserted into and removed from an IBF.
Definition ibf.h:46
uint64_t key_val
Definition ibf.h:47
estimate_best_mode_of_operation (uint64_t avg_element_size, uint64_t local_set_size,...
Invertible bloom filter (IBF).
Definition ibf.h:83
uint32_t size
How many cells does this IBF have?
Definition ibf.h:87
The key entry is used to associate an ibf key with an element.
struct ElementEntry * element
The actual element associated with the key.
struct IBF_Key ibf_key
IBF key for the entry, derived from the current salt.
int received
Did we receive this element? Even if element->is_foreign is false, we might have received the element...
State of an evaluate operation with another peer.
struct InvertibleBloomFilter * remote_ibf
The IBF we currently receive.
enum UnionOperationPhase phase
Current state of the operation.
struct StrataEstimator * se
Copy of the set's strata estimator at the time of creation of this operation.
uint32_t received_total
Total number of elements received from the other peer.
uint32_t salt_send
Salt that we're using for sending IBFs.
uint64_t initial_size
Initial size of our set, just before the operation started.
struct GNUNET_CONTAINER_MultiHashMap * demanded_hashes
Hashes for elements that we have demanded from the other peer.
struct InvertibleBloomFilter * local_ibf
The IBF with the local set's element.
struct GNUNET_CONTAINER_MultiHashMap32 * key_to_element
Maps unsalted IBF-Keys to elements.
uint32_t salt_receive
Salt for the IBF we've received and that we're currently decoding.
unsigned int ibf_buckets_received
Number of ibf buckets already received into the remote_ibf.
int client_done_sent
Did we send the client that we are done?
uint32_t received_fresh
Number of elements we received from the other peer that were not in the local set yet.
Operation context used to execute a set operation.
Used as a closure for sending elements with a specific IBF key.
struct Operation * op
Operation for which the elements should be sent.
struct IBF_Key ibf_key
The IBF key whose matching elements should be sent.
Extra state required for efficient set intersection.
struct StrataEstimator * se
The strata estimator is only generated once for each set.
Dispatch table for a specific set operation.
SetCreateImpl create
Callback for the set creation.
Strata estimator together with the peer's overall set size.
uint64_t set_size
Size of the local set.
A handle to a strata estimator.
unsigned int ibf_size
Size of each IBF stratum (in bytes)
unsigned int strata_count
Size of the IBF array in strata.