GNUnet  0.10.x
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 
78 {
83 
94 
99 
104 
109 
115 
123 
130 
136 };
137 
138 
142 struct OperationState
143 {
149 
154 
159 
166 
171 
175  int client_done_sent;
176 
180  unsigned int ibf_buckets_received;
181 
186 
190  uint32_t salt_send;
191 
195  uint32_t salt_receive;
196 
201  uint32_t received_fresh;
202 
206  uint32_t received_total;
207 
212  uint64_t initial_size;
213 };
214 
215 
219 struct KeyEntry
220 {
224  struct IBF_Key ibf_key;
225 
233 
240  int received;
241 };
242 
243 
249 {
254  struct IBF_Key ibf_key;
255 
260  struct Operation *op;
261 };
262 
263 
267 struct SetState
268 {
276 };
277 
278 
289 static 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 
313 static 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  {
323  op->state->remote_ibf = NULL;
324  }
325  if (NULL != op->state->demanded_hashes)
326  {
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  {
338  op->state->se = NULL;
339  }
340  if (NULL != op->state->key_to_element)
341  {
344  NULL);
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 
361 static void
363 {
364  struct GNUNET_MQ_Envelope *ev;
366 
368  "union operation failed\n");
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 
386 static struct IBF_Key
387 get_ibf_key (const struct GNUNET_HashCode *src)
388 {
389  struct IBF_Key key;
390  uint16_t salt = 0;
391 
393  GNUNET_CRYPTO_kdf (&key, sizeof (key),
394  src, sizeof *src,
395  &salt, sizeof (salt),
396  NULL, 0));
397  return key;
398 }
399 
400 
405 {
409  struct GNUNET_HashCode hash;
410 
414  struct KeyEntry *k;
415 };
416 
417 
428 static int
430  uint32_t key,
431  void *value)
432 {
433  struct GetElementContext *ctx = cls;
434  struct KeyEntry *k = value;
435 
436  GNUNET_assert (NULL != k);
438  &ctx->hash))
439  {
440  ctx->k = k;
441  return GNUNET_NO;
442  }
443  return GNUNET_YES;
444 }
445 
446 
455 static struct KeyEntry *
457  const struct GNUNET_HashCode *element_hash)
458 {
459  int ret;
460  struct IBF_Key ibf_key;
461  struct GetElementContext ctx = {{{ 0 }} , 0};
462 
463  ctx.hash = *element_hash;
464 
465  ibf_key = get_ibf_key (element_hash);
467  (uint32_t) ibf_key.key_val,
469  &ctx);
470 
471  /* was the iteration aborted because we found the element? */
472  if (GNUNET_SYSERR == ret)
473  {
474  GNUNET_assert (NULL != ctx.k);
475  return ctx.k;
476  }
477  return NULL;
478 }
479 
480 
495 static void
497  struct ElementEntry *ee,
498  int received)
499 {
500  struct IBF_Key ibf_key;
501  struct KeyEntry *k;
502 
503  ibf_key = get_ibf_key (&ee->element_hash);
504  k = GNUNET_new (struct KeyEntry);
505  k->element = ee;
506  k->ibf_key = ibf_key;
507  k->received = received;
510  (uint32_t) ibf_key.key_val,
511  k,
513 }
514 
515 
519 static void
520 salt_key (const struct IBF_Key *k_in,
521  uint32_t salt,
522  struct IBF_Key *k_out)
523 {
524  int s = salt % 64;
525  uint64_t x = k_in->key_val;
526  /* rotate ibf key */
527  x = (x >> s) | (x << (64 - s));
528  k_out->key_val = x;
529 }
530 
531 
535 static void
536 unsalt_key (const struct IBF_Key *k_in,
537  uint32_t salt,
538  struct IBF_Key *k_out)
539 {
540  int s = salt % 64;
541  uint64_t x = k_in->key_val;
542  x = (x << s) | (x >> (64 - s));
543  k_out->key_val = x;
544 }
545 
546 
554 static int
556  uint32_t key,
557  void *value)
558 {
559  struct Operation *op = cls;
560  struct KeyEntry *ke = value;
561  struct IBF_Key salted_key;
562 
564  "[OP %x] inserting %lx (hash %s) into ibf\n",
565  (void *) op,
566  (unsigned long) ke->ibf_key.key_val,
568  salt_key (&ke->ibf_key,
569  op->state->salt_send,
570  &salted_key);
571  ibf_insert (op->state->local_ibf, salted_key);
572  return GNUNET_YES;
573 }
574 
575 
586 static int
588  const struct GNUNET_HashCode *key,
589  void *value)
590 {
591  struct Operation *op = cls;
592  struct ElementEntry *ee = value;
593 
594  /* make sure that the element belongs to the set at the time
595  * of creating the operation */
596  if (GNUNET_NO ==
598  op))
599  return GNUNET_YES;
600  GNUNET_assert (GNUNET_NO == ee->remote);
602  ee,
603  GNUNET_NO);
604  return GNUNET_YES;
605 }
606 
607 
614 static void
616 {
617  unsigned int len;
618 
619  GNUNET_assert (NULL == op->state->key_to_element);
624  op);
625 }
626 
627 
636 static int
638  uint32_t size)
639 {
640  GNUNET_assert (NULL != op->state->key_to_element);
641 
642  if (NULL != op->state->local_ibf)
643  ibf_destroy (op->state->local_ibf);
644  op->state->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
645  if (NULL == op->state->local_ibf)
646  {
648  "Failed to allocate local IBF\n");
649  return GNUNET_SYSERR;
650  }
653  op);
654  return GNUNET_OK;
655 }
656 
657 
667 static int
669  uint16_t ibf_order)
670 {
671  unsigned int buckets_sent = 0;
672  struct InvertibleBloomFilter *ibf;
673 
674  if (GNUNET_OK !=
675  prepare_ibf (op, 1<<ibf_order))
676  {
677  /* allocation failed */
678  return GNUNET_SYSERR;
679  }
680 
682  "sending ibf of size %u\n",
683  1<<ibf_order);
684 
685  {
686  char name[64] = { 0 };
687  snprintf (name, sizeof (name), "# sent IBF (order %u)", ibf_order);
689  }
690 
691  ibf = op->state->local_ibf;
692 
693  while (buckets_sent < (1 << ibf_order))
694  {
695  unsigned int buckets_in_message;
696  struct GNUNET_MQ_Envelope *ev;
697  struct IBFMessage *msg;
698 
699  buckets_in_message = (1 << ibf_order) - buckets_sent;
700  /* limit to maximum */
701  if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE)
702  buckets_in_message = MAX_BUCKETS_PER_MESSAGE;
703 
704  ev = GNUNET_MQ_msg_extra (msg,
705  buckets_in_message * IBF_BUCKET_SIZE,
707  msg->reserved1 = 0;
708  msg->reserved2 = 0;
709  msg->order = ibf_order;
710  msg->offset = htonl (buckets_sent);
711  msg->salt = htonl (op->state->salt_send);
712  ibf_write_slice (ibf, buckets_sent,
713  buckets_in_message, &msg[1]);
714  buckets_sent += buckets_in_message;
716  "ibf chunk size %u, %u/%u sent\n",
717  buckets_in_message,
718  buckets_sent,
719  1<<ibf_order);
720  GNUNET_MQ_send (op->mq, ev);
721  }
722 
723  /* The other peer must decode the IBF, so
724  * we're passive. */
726  return GNUNET_OK;
727 }
728 
729 
737 static unsigned int
738 get_order_from_difference (unsigned int diff)
739 {
740  unsigned int ibf_order;
741 
742  ibf_order = 2;
743  while ( ( (1<<ibf_order) < (IBF_ALPHA * diff) ||
744  ((1<<ibf_order) < SE_IBF_HASH_NUM) ) &&
745  (ibf_order < MAX_IBF_ORDER) )
746  ibf_order++;
747  // add one for correction
748  return ibf_order + 1;
749 }
750 
751 
761 static int
763  const struct GNUNET_HashCode *key,
764  void *value)
765 {
766  struct Operation *op = cls;
767  struct GNUNET_SET_ElementMessage *emsg;
768  struct ElementEntry *ee = value;
769  struct GNUNET_SET_Element *el = &ee->element;
770  struct GNUNET_MQ_Envelope *ev;
771 
773  "Sending element %s\n",
774  GNUNET_h2s (key));
775  ev = GNUNET_MQ_msg_extra (emsg,
776  el->size,
778  emsg->element_type = htons (el->element_type);
779  GNUNET_memcpy (&emsg[1],
780  el->data,
781  el->size);
782  GNUNET_MQ_send (op->mq,
783  ev);
784  return GNUNET_YES;
785 }
786 
787 
793 static void
795 {
796  struct GNUNET_MQ_Envelope *ev;
797 
800  "Dedicing to transmit the full set\n");
801  /* FIXME: use a more memory-friendly way of doing this with an
802  iterator, just as we do in the non-full case! */
805  op);
807  GNUNET_MQ_send (op->mq,
808  ev);
809 }
810 
811 
818 int
820  const struct StrataEstimatorMessage *msg)
821 {
822  struct Operation *op = cls;
823  int is_compressed;
824  size_t len;
825 
826  if (op->state->phase != PHASE_EXPECT_SE)
827  {
828  GNUNET_break (0);
829  return GNUNET_SYSERR;
830  }
831  is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons (msg->header.type));
832  len = ntohs (msg->header.size) - sizeof (struct StrataEstimatorMessage);
833  if ( (GNUNET_NO == is_compressed) &&
835  {
836  GNUNET_break (0);
837  return GNUNET_SYSERR;
838  }
839  return GNUNET_OK;
840 }
841 
842 
849 void
851  const struct StrataEstimatorMessage *msg)
852 {
853  struct Operation *op = cls;
854  struct StrataEstimator *remote_se;
855  unsigned int diff;
856  uint64_t other_size;
857  size_t len;
858  int is_compressed;
859 
860  is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons (msg->header.type));
862  "# bytes of SE received",
863  ntohs (msg->header.size),
864  GNUNET_NO);
865  len = ntohs (msg->header.size) - sizeof (struct StrataEstimatorMessage);
866  other_size = GNUNET_ntohll (msg->set_size);
868  SE_IBF_SIZE,
870  if (NULL == remote_se)
871  {
872  /* insufficient resources, fail */
874  return;
875  }
876  if (GNUNET_OK !=
877  strata_estimator_read (&msg[1],
878  len,
879  is_compressed,
880  remote_se))
881  {
882  /* decompression failed */
883  strata_estimator_destroy (remote_se);
885  return;
886  }
887  GNUNET_assert (NULL != op->state->se);
888  diff = strata_estimator_difference (remote_se,
889  op->state->se);
890 
891  if (diff > 200)
892  diff = diff * 3 / 2;
893 
894  strata_estimator_destroy (remote_se);
896  op->state->se = NULL;
898  "got se diff=%d, using ibf size %d\n",
899  diff,
900  1U << get_order_from_difference (diff));
901 
902  {
903  char *set_debug;
904 
905  set_debug = getenv ("GNUNET_SET_BENCHMARK");
906  if ( (NULL != set_debug) &&
907  (0 == strcmp (set_debug, "1")) )
908  {
909  FILE *f = fopen ("set.log", "a");
910  fprintf (f, "%llu\n", (unsigned long long) diff);
911  fclose (f);
912  }
913  }
914 
915  if ( (GNUNET_YES == op->byzantine) &&
916  (other_size < op->byzantine_lower_bound) )
917  {
918  GNUNET_break (0);
920  return;
921  }
922 
923  if ( (GNUNET_YES == op->force_full) ||
924  (diff > op->state->initial_size / 4) ||
925  (0 == other_size) )
926  {
928  "Deciding to go for full set transmission (diff=%d, own set=%u)\n",
929  diff,
930  op->state->initial_size);
932  "# of full sends",
933  1,
934  GNUNET_NO);
935  if ( (op->state->initial_size <= other_size) ||
936  (0 == other_size) )
937  {
938  send_full_set (op);
939  }
940  else
941  {
942  struct GNUNET_MQ_Envelope *ev;
943 
945  "Telling other peer that we expect its full set\n");
948  GNUNET_MQ_send (op->mq,
949  ev);
950  }
951  }
952  else
953  {
955  "# of ibf sends",
956  1,
957  GNUNET_NO);
958  if (GNUNET_OK !=
959  send_ibf (op,
961  {
962  /* Internal error, best we can do is shut the connection */
964  "Failed to send IBF, closing connection\n");
966  return;
967  }
968  }
970 }
971 
972 
980 static int
982  uint32_t key,
983  void *value)
984 {
985  struct SendElementClosure *sec = cls;
986  struct Operation *op = sec->op;
987  struct KeyEntry *ke = value;
988  struct GNUNET_MQ_Envelope *ev;
989  struct GNUNET_MessageHeader *mh;
990 
991  /* Detect 32-bit key collision for the 64-bit IBF keys. */
992  if (ke->ibf_key.key_val != sec->ibf_key.key_val)
993  return GNUNET_YES;
994 
996  sizeof (struct GNUNET_HashCode),
998 
999  GNUNET_assert (NULL != ev);
1000  *(struct GNUNET_HashCode *) &mh[1] = ke->element->element_hash;
1002  "[OP %x] sending element offer (%s) to peer\n",
1003  (void *) op,
1004  GNUNET_h2s (&ke->element->element_hash));
1005  GNUNET_MQ_send (op->mq, ev);
1006  return GNUNET_YES;
1007 }
1008 
1009 
1016 static void
1018  struct IBF_Key ibf_key)
1019 {
1020  struct SendElementClosure send_cls;
1021 
1022  send_cls.ibf_key = ibf_key;
1023  send_cls.op = op;
1025  (uint32_t) ibf_key.key_val,
1027  &send_cls);
1028 }
1029 
1030 
1038 static int
1040 {
1041  struct IBF_Key key;
1042  struct IBF_Key last_key;
1043  int side;
1044  unsigned int num_decoded;
1045  struct InvertibleBloomFilter *diff_ibf;
1046 
1048 
1049  if (GNUNET_OK !=
1050  prepare_ibf (op,
1051  op->state->remote_ibf->size))
1052  {
1053  GNUNET_break (0);
1054  /* allocation failed */
1055  return GNUNET_SYSERR;
1056  }
1057  diff_ibf = ibf_dup (op->state->local_ibf);
1058  ibf_subtract (diff_ibf,
1059  op->state->remote_ibf);
1060 
1061  ibf_destroy (op->state->remote_ibf);
1062  op->state->remote_ibf = NULL;
1063 
1065  "decoding IBF (size=%u)\n",
1066  diff_ibf->size);
1067 
1068  num_decoded = 0;
1069  key.key_val = 0; /* just to avoid compiler thinking we use undef'ed variable */
1070 
1071  while (1)
1072  {
1073  int res;
1074  int cycle_detected = GNUNET_NO;
1075 
1076  last_key = key;
1077 
1078  res = ibf_decode (diff_ibf, &side, &key);
1079  if (res == GNUNET_OK)
1080  {
1082  "decoded ibf key %lx\n",
1083  (unsigned long) key.key_val);
1084  num_decoded += 1;
1085  if ( (num_decoded > diff_ibf->size) ||
1086  ( (num_decoded > 1) &&
1087  (last_key.key_val == key.key_val) ) )
1088  {
1090  "detected cyclic ibf (decoded %u/%u)\n",
1091  num_decoded,
1092  diff_ibf->size);
1093  cycle_detected = GNUNET_YES;
1094  }
1095  }
1096  if ( (GNUNET_SYSERR == res) ||
1097  (GNUNET_YES == cycle_detected) )
1098  {
1099  int next_order;
1100  next_order = 0;
1101  while (1<<next_order < diff_ibf->size)
1102  next_order++;
1103  next_order++;
1104  if (next_order <= MAX_IBF_ORDER)
1105  {
1107  "decoding failed, sending larger ibf (size %u)\n",
1108  1<<next_order);
1110  "# of IBF retries",
1111  1,
1112  GNUNET_NO);
1113  op->state->salt_send++;
1114  if (GNUNET_OK !=
1115  send_ibf (op, next_order))
1116  {
1117  /* Internal error, best we can do is shut the connection */
1119  "Failed to send IBF, closing connection\n");
1120  fail_union_operation (op);
1121  ibf_destroy (diff_ibf);
1122  return GNUNET_SYSERR;
1123  }
1124  }
1125  else
1126  {
1128  "# of failed union operations (too large)",
1129  1,
1130  GNUNET_NO);
1131  // XXX: Send the whole set, element-by-element
1133  "set union failed: reached ibf limit\n");
1134  fail_union_operation (op);
1135  ibf_destroy (diff_ibf);
1136  return GNUNET_SYSERR;
1137  }
1138  break;
1139  }
1140  if (GNUNET_NO == res)
1141  {
1142  struct GNUNET_MQ_Envelope *ev;
1143 
1145  "transmitted all values, sending DONE\n");
1147  GNUNET_MQ_send (op->mq, ev);
1148  /* We now wait until we get a DONE message back
1149  * and then wait for our MQ to be flushed and all our
1150  * demands be delivered. */
1151  break;
1152  }
1153  if (1 == side)
1154  {
1155  struct IBF_Key unsalted_key;
1156 
1157  unsalt_key (&key,
1158  op->state->salt_receive,
1159  &unsalted_key);
1160  send_offers_for_key (op,
1161  unsalted_key);
1162  }
1163  else if (-1 == side)
1164  {
1165  struct GNUNET_MQ_Envelope *ev;
1166  struct InquiryMessage *msg;
1167 
1168  /* It may be nice to merge multiple requests, but with CADET's corking it is not worth
1169  * the effort additional complexity. */
1170  ev = GNUNET_MQ_msg_extra (msg,
1171  sizeof (struct IBF_Key),
1173  msg->salt = htonl (op->state->salt_receive);
1174  GNUNET_memcpy (&msg[1],
1175  &key,
1176  sizeof (struct IBF_Key));
1178  "sending element inquiry for IBF key %lx\n",
1179  (unsigned long) key.key_val);
1180  GNUNET_MQ_send (op->mq, ev);
1181  }
1182  else
1183  {
1184  GNUNET_assert (0);
1185  }
1186  }
1187  ibf_destroy (diff_ibf);
1188  return GNUNET_OK;
1189 }
1190 
1191 
1202 int
1204  const struct IBFMessage *msg)
1205 {
1206  struct Operation *op = cls;
1207  unsigned int buckets_in_message;
1208 
1210  {
1211  GNUNET_break_op (0);
1212  return GNUNET_SYSERR;
1213  }
1214  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE;
1215  if (0 == buckets_in_message)
1216  {
1217  GNUNET_break_op (0);
1218  return GNUNET_SYSERR;
1219  }
1220  if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message * IBF_BUCKET_SIZE)
1221  {
1222  GNUNET_break_op (0);
1223  return GNUNET_SYSERR;
1224  }
1225  if (op->state->phase == PHASE_EXPECT_IBF_CONT)
1226  {
1227  if (ntohl (msg->offset) != op->state->ibf_buckets_received)
1228  {
1229  GNUNET_break_op (0);
1230  return GNUNET_SYSERR;
1231  }
1232  if (1<<msg->order != op->state->remote_ibf->size)
1233  {
1234  GNUNET_break_op (0);
1235  return GNUNET_SYSERR;
1236  }
1237  if (ntohl (msg->salt) != op->state->salt_receive)
1238  {
1239  GNUNET_break_op (0);
1240  return GNUNET_SYSERR;
1241  }
1242  }
1243  else if ( (op->state->phase != PHASE_INVENTORY_PASSIVE) &&
1244  (op->state->phase != PHASE_EXPECT_IBF) )
1245  {
1246  GNUNET_break_op (0);
1247  return GNUNET_SYSERR;
1248  }
1249 
1250  return GNUNET_OK;
1251 }
1252 
1253 
1263 void
1265  const struct IBFMessage *msg)
1266 {
1267  struct Operation *op = cls;
1268  unsigned int buckets_in_message;
1269 
1270  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE;
1271  if ( (op->state->phase == PHASE_INVENTORY_PASSIVE) ||
1272  (op->state->phase == PHASE_EXPECT_IBF) )
1273  {
1275  GNUNET_assert (NULL == op->state->remote_ibf);
1277  "Creating new ibf of size %u\n",
1278  1 << msg->order);
1279  op->state->remote_ibf = ibf_create (1<<msg->order, SE_IBF_HASH_NUM);
1280  op->state->salt_receive = ntohl (msg->salt);
1282  "Receiving new IBF with salt %u\n",
1283  op->state->salt_receive);
1284  if (NULL == op->state->remote_ibf)
1285  {
1287  "Failed to parse remote IBF, closing connection\n");
1288  fail_union_operation (op);
1289  return;
1290  }
1291  op->state->ibf_buckets_received = 0;
1292  if (0 != ntohl (msg->offset))
1293  {
1294  GNUNET_break_op (0);
1295  fail_union_operation (op);
1296  return;
1297  }
1298  }
1299  else
1300  {
1303  "Received more of IBF\n");
1304  }
1305  GNUNET_assert (NULL != op->state->remote_ibf);
1306 
1307  ibf_read_slice (&msg[1],
1309  buckets_in_message,
1310  op->state->remote_ibf);
1311  op->state->ibf_buckets_received += buckets_in_message;
1312 
1313  if (op->state->ibf_buckets_received == op->state->remote_ibf->size)
1314  {
1316  "received full ibf\n");
1318  if (GNUNET_OK !=
1319  decode_and_send (op))
1320  {
1321  /* Internal error, best we can do is shut down */
1323  "Failed to decode IBF, closing connection\n");
1324  fail_union_operation (op);
1325  return;
1326  }
1327  }
1329 }
1330 
1331 
1340 static void
1342  struct GNUNET_SET_Element *element,
1343  int status)
1344 {
1345  struct GNUNET_MQ_Envelope *ev;
1346  struct GNUNET_SET_ResultMessage *rm;
1347 
1349  "sending element (size %u) to client\n",
1350  element->size);
1351  GNUNET_assert (0 != op->client_request_id);
1353  if (NULL == ev)
1354  {
1355  GNUNET_MQ_discard (ev);
1356  GNUNET_break (0);
1357  return;
1358  }
1359  rm->result_status = htons (status);
1360  rm->request_id = htonl (op->client_request_id);
1361  rm->element_type = htons (element->element_type);
1363  GNUNET_memcpy (&rm[1],
1364  element->data,
1365  element->size);
1366  GNUNET_MQ_send (op->set->cs->mq,
1367  ev);
1368 }
1369 
1370 
1377 static void
1378 send_client_done (void *cls)
1379 {
1380  struct Operation *op = cls;
1381  struct GNUNET_MQ_Envelope *ev;
1382  struct GNUNET_SET_ResultMessage *rm;
1383 
1384  if (GNUNET_YES == op->state->client_done_sent)
1385  {
1386  return;
1387  }
1388 
1389  if (PHASE_DONE != op->state->phase) {
1391  "Union operation failed\n");
1393  "# Union operations failed",
1394  1,
1395  GNUNET_NO);
1398  rm->request_id = htonl (op->client_request_id);
1399  rm->element_type = htons (0);
1400  GNUNET_MQ_send (op->set->cs->mq,
1401  ev);
1402  return;
1403  }
1404 
1406 
1408  "# Union operations succeeded",
1409  1,
1410  GNUNET_NO);
1412  "Signalling client that union operation is done\n");
1413  ev = GNUNET_MQ_msg (rm,
1415  rm->request_id = htonl (op->client_request_id);
1416  rm->result_status = htons (GNUNET_SET_STATUS_DONE);
1417  rm->element_type = htons (0);
1419  GNUNET_MQ_send (op->set->cs->mq,
1420  ev);
1421 }
1422 
1423 
1429 static void
1431 {
1432  unsigned int num_demanded;
1433 
1435 
1436  if (PHASE_FINISH_WAITING == op->state->phase)
1437  {
1439  "In PHASE_FINISH_WAITING, pending %u demands\n",
1440  num_demanded);
1441  if (0 == num_demanded)
1442  {
1443  struct GNUNET_MQ_Envelope *ev;
1444 
1445  op->state->phase = PHASE_DONE;
1447  GNUNET_MQ_send (op->mq,
1448  ev);
1449  /* We now wait until the other peer sends P2P_OVER
1450  * after it got all elements from us. */
1451  }
1452  }
1453  if (PHASE_FINISH_CLOSING == op->state->phase)
1454  {
1456  "In PHASE_FINISH_CLOSING, pending %u demands\n",
1457  num_demanded);
1458  if (0 == num_demanded)
1459  {
1460  op->state->phase = PHASE_DONE;
1461  send_client_done (op);
1463  }
1464  }
1465 }
1466 
1467 
1474 int
1476  const struct GNUNET_SET_ElementMessage *emsg)
1477 {
1478  struct Operation *op = cls;
1479 
1481  {
1482  GNUNET_break_op (0);
1483  return GNUNET_SYSERR;
1484  }
1486  {
1487  GNUNET_break_op (0);
1488  return GNUNET_SYSERR;
1489  }
1490  return GNUNET_OK;
1491 }
1492 
1493 
1502 void
1504  const struct GNUNET_SET_ElementMessage *emsg)
1505 {
1506  struct Operation *op = cls;
1507  struct ElementEntry *ee;
1508  struct KeyEntry *ke;
1509  uint16_t element_size;
1510 
1511  element_size = ntohs (emsg->header.size) - sizeof (struct GNUNET_SET_ElementMessage);
1512  ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size);
1513  GNUNET_memcpy (&ee[1],
1514  &emsg[1],
1515  element_size);
1516  ee->element.size = element_size;
1517  ee->element.data = &ee[1];
1518  ee->element.element_type = ntohs (emsg->element_type);
1519  ee->remote = GNUNET_YES;
1521  &ee->element_hash);
1522  if (GNUNET_NO ==
1524  &ee->element_hash,
1525  NULL))
1526  {
1527  /* We got something we didn't demand, since it's not in our map. */
1528  GNUNET_break_op (0);
1529  fail_union_operation (op);
1530  return;
1531  }
1532 
1534  "Got element (size %u, hash %s) from peer\n",
1535  (unsigned int) element_size,
1536  GNUNET_h2s (&ee->element_hash));
1537 
1539  "# received elements",
1540  1,
1541  GNUNET_NO);
1543  "# exchanged elements",
1544  1,
1545  GNUNET_NO);
1546 
1547  op->state->received_total++;
1548 
1549  ke = op_get_element (op, &ee->element_hash);
1550  if (NULL != ke)
1551  {
1552  /* Got repeated element. Should not happen since
1553  * we track demands. */
1555  "# repeated elements",
1556  1,
1557  GNUNET_NO);
1558  ke->received = GNUNET_YES;
1559  GNUNET_free (ee);
1560  }
1561  else
1562  {
1564  "Registering new element from remote peer\n");
1565  op->state->received_fresh++;
1566  op_register_element (op, ee, GNUNET_YES);
1567  /* only send results immediately if the client wants it */
1568  switch (op->result_mode)
1569  {
1572  break;
1575  break;
1576  default:
1577  /* Result mode not supported, should have been caught earlier. */
1578  GNUNET_break (0);
1579  break;
1580  }
1581  }
1582 
1583  if ( (op->state->received_total > 8) &&
1584  (op->state->received_fresh < op->state->received_total / 3) )
1585  {
1586  /* The other peer gave us lots of old elements, there's something wrong. */
1587  GNUNET_break_op (0);
1588  fail_union_operation (op);
1589  return;
1590  }
1592  maybe_finish (op);
1593 }
1594 
1595 
1602 int
1604  const struct GNUNET_SET_ElementMessage *emsg)
1605 {
1606  struct Operation *op = cls;
1607 
1609  {
1610  GNUNET_break_op (0);
1611  return GNUNET_SYSERR;
1612  }
1613  // FIXME: check that we expect full elements here?
1614  return GNUNET_OK;
1615 }
1616 
1617 
1624 void
1626  const struct GNUNET_SET_ElementMessage *emsg)
1627 {
1628  struct Operation *op = cls;
1629  struct ElementEntry *ee;
1630  struct KeyEntry *ke;
1631  uint16_t element_size;
1632 
1633  element_size = ntohs (emsg->header.size) - sizeof (struct GNUNET_SET_ElementMessage);
1634  ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size);
1635  GNUNET_memcpy (&ee[1], &emsg[1], element_size);
1636  ee->element.size = element_size;
1637  ee->element.data = &ee[1];
1638  ee->element.element_type = ntohs (emsg->element_type);
1639  ee->remote = GNUNET_YES;
1641 
1643  "Got element (full diff, size %u, hash %s) from peer\n",
1644  (unsigned int) element_size,
1645  GNUNET_h2s (&ee->element_hash));
1646 
1648  "# received elements",
1649  1,
1650  GNUNET_NO);
1652  "# exchanged elements",
1653  1,
1654  GNUNET_NO);
1655 
1656  op->state->received_total++;
1657 
1658  ke = op_get_element (op, &ee->element_hash);
1659  if (NULL != ke)
1660  {
1661  /* Got repeated element. Should not happen since
1662  * we track demands. */
1664  "# repeated elements",
1665  1,
1666  GNUNET_NO);
1667  ke->received = GNUNET_YES;
1668  GNUNET_free (ee);
1669  }
1670  else
1671  {
1673  "Registering new element from remote peer\n");
1674  op->state->received_fresh++;
1675  op_register_element (op, ee, GNUNET_YES);
1676  /* only send results immediately if the client wants it */
1677  switch (op->result_mode)
1678  {
1681  break;
1684  break;
1685  default:
1686  /* Result mode not supported, should have been caught earlier. */
1687  GNUNET_break (0);
1688  break;
1689  }
1690  }
1691 
1692  if ( (GNUNET_YES == op->byzantine) &&
1693  (op->state->received_total > 384 + op->state->received_fresh * 4) &&
1694  (op->state->received_fresh < op->state->received_total / 6) )
1695  {
1696  /* The other peer gave us lots of old elements, there's something wrong. */
1698  "Other peer sent only %llu/%llu fresh elements, failing operation\n",
1699  (unsigned long long) op->state->received_fresh,
1700  (unsigned long long) op->state->received_total);
1701  GNUNET_break_op (0);
1702  fail_union_operation (op);
1703  return;
1704  }
1706 }
1707 
1708 
1716 int
1718  const struct InquiryMessage *msg)
1719 {
1720  struct Operation *op = cls;
1721  unsigned int num_keys;
1722 
1724  {
1725  GNUNET_break_op (0);
1726  return GNUNET_SYSERR;
1727  }
1728  if (op->state->phase != PHASE_INVENTORY_PASSIVE)
1729  {
1730  GNUNET_break_op (0);
1731  return GNUNET_SYSERR;
1732  }
1733  num_keys = (ntohs (msg->header.size) - sizeof (struct InquiryMessage))
1734  / sizeof (struct IBF_Key);
1735  if ((ntohs (msg->header.size) - sizeof (struct InquiryMessage))
1736  != num_keys * sizeof (struct IBF_Key))
1737  {
1738  GNUNET_break_op (0);
1739  return GNUNET_SYSERR;
1740  }
1741  return GNUNET_OK;
1742 }
1743 
1744 
1752 void
1754  const struct InquiryMessage *msg)
1755 {
1756  struct Operation *op = cls;
1757  const struct IBF_Key *ibf_key;
1758  unsigned int num_keys;
1759 
1761  "Received union inquiry\n");
1762  num_keys = (ntohs (msg->header.size) - sizeof (struct InquiryMessage))
1763  / sizeof (struct IBF_Key);
1764  ibf_key = (const struct IBF_Key *) &msg[1];
1765  while (0 != num_keys--)
1766  {
1767  struct IBF_Key unsalted_key;
1768 
1769  unsalt_key (ibf_key,
1770  ntohl (msg->salt),
1771  &unsalted_key);
1772  send_offers_for_key (op,
1773  unsalted_key);
1774  ibf_key++;
1775  }
1777 }
1778 
1779 
1790 static int
1792  uint32_t key,
1793  void *value)
1794 {
1795  struct Operation *op = cls;
1796  struct KeyEntry *ke = value;
1797  struct GNUNET_MQ_Envelope *ev;
1798  struct GNUNET_SET_ElementMessage *emsg;
1799  struct ElementEntry *ee = ke->element;
1800 
1801  if (GNUNET_YES == ke->received)
1802  return GNUNET_YES;
1803  ev = GNUNET_MQ_msg_extra (emsg,
1804  ee->element.size,
1806  GNUNET_memcpy (&emsg[1],
1807  ee->element.data,
1808  ee->element.size);
1809  emsg->element_type = htons (ee->element.element_type);
1810  GNUNET_MQ_send (op->mq,
1811  ev);
1812  return GNUNET_YES;
1813 }
1814 
1815 
1822 void
1824  const struct GNUNET_MessageHeader *mh)
1825 {
1826  struct Operation *op = cls;
1827 
1829  "Received request for full set transmission\n");
1831  {
1832  GNUNET_break_op (0);
1833  fail_union_operation (op);
1834  return;
1835  }
1836  if (PHASE_EXPECT_IBF != op->state->phase)
1837  {
1838  GNUNET_break_op (0);
1839  fail_union_operation (op);
1840  return;
1841  }
1842 
1843  // FIXME: we need to check that our set is larger than the
1844  // byzantine_lower_bound by some threshold
1845  send_full_set (op);
1847 }
1848 
1849 
1856 void
1858  const struct GNUNET_MessageHeader *mh)
1859 {
1860  struct Operation *op = cls;
1861 
1862  switch (op->state->phase)
1863  {
1864  case PHASE_EXPECT_IBF:
1865  {
1866  struct GNUNET_MQ_Envelope *ev;
1867 
1869  "got FULL DONE, sending elements that other peer is missing\n");
1870 
1871  /* send all the elements that did not come from the remote peer */
1874  op);
1875 
1877  GNUNET_MQ_send (op->mq,
1878  ev);
1879  op->state->phase = PHASE_DONE;
1880  /* we now wait until the other peer sends us the OVER message*/
1881  }
1882  break;
1883  case PHASE_FULL_SENDING:
1884  {
1886  "got FULL DONE, finishing\n");
1887  /* We sent the full set, and got the response for that. We're done. */
1888  op->state->phase = PHASE_DONE;
1890  send_client_done (op);
1892  return;
1893  }
1894  break;
1895  default:
1897  "Handle full done phase is %u\n",
1898  (unsigned) op->state->phase);
1899  GNUNET_break_op (0);
1900  fail_union_operation (op);
1901  return;
1902  }
1904 }
1905 
1906 
1915 int
1917  const struct GNUNET_MessageHeader *mh)
1918 {
1919  struct Operation *op = cls;
1920  unsigned int num_hashes;
1921 
1923  {
1924  GNUNET_break_op (0);
1925  return GNUNET_SYSERR;
1926  }
1927  num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1928  / sizeof (struct GNUNET_HashCode);
1929  if ((ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1930  != num_hashes * sizeof (struct GNUNET_HashCode))
1931  {
1932  GNUNET_break_op (0);
1933  return GNUNET_SYSERR;
1934  }
1935  return GNUNET_OK;
1936 }
1937 
1938 
1946 void
1948  const struct GNUNET_MessageHeader *mh)
1949 {
1950  struct Operation *op = cls;
1951  struct ElementEntry *ee;
1952  struct GNUNET_SET_ElementMessage *emsg;
1953  const struct GNUNET_HashCode *hash;
1954  unsigned int num_hashes;
1955  struct GNUNET_MQ_Envelope *ev;
1956 
1957  num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
1958  / sizeof (struct GNUNET_HashCode);
1959  for (hash = (const struct GNUNET_HashCode *) &mh[1];
1960  num_hashes > 0;
1961  hash++, num_hashes--)
1962  {
1964  hash);
1965  if (NULL == ee)
1966  {
1967  /* Demand for non-existing element. */
1968  GNUNET_break_op (0);
1969  fail_union_operation (op);
1970  return;
1971  }
1972  if (GNUNET_NO == _GSS_is_element_of_operation (ee, op))
1973  {
1974  /* Probably confused lazily copied sets. */
1975  GNUNET_break_op (0);
1976  fail_union_operation (op);
1977  return;
1978  }
1980  GNUNET_memcpy (&emsg[1], ee->element.data, ee->element.size);
1981  emsg->reserved = htons (0);
1982  emsg->element_type = htons (ee->element.element_type);
1984  "[OP %x] Sending demanded element (size %u, hash %s) to peer\n",
1985  (void *) op,
1986  (unsigned int) ee->element.size,
1987  GNUNET_h2s (&ee->element_hash));
1988  GNUNET_MQ_send (op->mq, ev);
1990  "# exchanged elements",
1991  1,
1992  GNUNET_NO);
1993 
1994  switch (op->result_mode)
1995  {
1997  /* Nothing to do. */
1998  break;
2001  break;
2002  default:
2003  /* Result mode not supported, should have been caught earlier. */
2004  GNUNET_break (0);
2005  break;
2006  }
2007  }
2009 }
2010 
2011 
2019 int
2021  const struct GNUNET_MessageHeader *mh)
2022 {
2023  struct Operation *op = cls;
2024  unsigned int num_hashes;
2025 
2027  {
2028  GNUNET_break_op (0);
2029  return GNUNET_SYSERR;
2030  }
2031  /* look up elements and send them */
2032  if ( (op->state->phase != PHASE_INVENTORY_PASSIVE) &&
2034  {
2035  GNUNET_break_op (0);
2036  return GNUNET_SYSERR;
2037  }
2038  num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
2039  / sizeof (struct GNUNET_HashCode);
2040  if ((ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader)) !=
2041  num_hashes * sizeof (struct GNUNET_HashCode))
2042  {
2043  GNUNET_break_op (0);
2044  return GNUNET_SYSERR;
2045  }
2046  return GNUNET_OK;
2047 }
2048 
2049 
2057 void
2059  const struct GNUNET_MessageHeader *mh)
2060 {
2061  struct Operation *op = cls;
2062  const struct GNUNET_HashCode *hash;
2063  unsigned int num_hashes;
2064 
2065  num_hashes = (ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader))
2066  / sizeof (struct GNUNET_HashCode);
2067  for (hash = (const struct GNUNET_HashCode *) &mh[1];
2068  num_hashes > 0;
2069  hash++, num_hashes--)
2070  {
2071  struct ElementEntry *ee;
2072  struct GNUNET_MessageHeader *demands;
2073  struct GNUNET_MQ_Envelope *ev;
2074 
2076  hash);
2077  if (NULL != ee)
2078  if (GNUNET_YES == _GSS_is_element_of_operation (ee, op))
2079  continue;
2080 
2081  if (GNUNET_YES ==
2083  hash))
2084  {
2086  "Skipped sending duplicate demand\n");
2087  continue;
2088  }
2089 
2092  hash,
2093  NULL,
2095 
2097  "[OP %x] Requesting element (hash %s)\n",
2098  (void *) op, GNUNET_h2s (hash));
2099  ev = GNUNET_MQ_msg_header_extra (demands,
2100  sizeof (struct GNUNET_HashCode),
2102  GNUNET_memcpy (&demands[1],
2103  hash,
2104  sizeof (struct GNUNET_HashCode));
2105  GNUNET_MQ_send (op->mq, ev);
2106  }
2108 }
2109 
2110 
2117 void
2119  const struct GNUNET_MessageHeader *mh)
2120 {
2121  struct Operation *op = cls;
2122 
2124  {
2125  GNUNET_break_op (0);
2126  fail_union_operation (op);
2127  return;
2128  }
2129  switch (op->state->phase)
2130  {
2132  /* We got all requests, but still have to send our elements in response. */
2134 
2136  "got DONE (as passive partner), waiting for our demands to be satisfied\n");
2137  /* The active peer is done sending offers
2138  * and inquiries. This means that all
2139  * our responses to that (demands and offers)
2140  * must be in flight (queued or in mesh).
2141  *
2142  * We should notify the active peer once
2143  * all our demands are satisfied, so that the active
2144  * peer can quit if we gave it everything.
2145  */
2147  maybe_finish (op);
2148  return;
2151  "got DONE (as active partner), waiting to finish\n");
2152  /* All demands of the other peer are satisfied,
2153  * and we processed all offers, thus we know
2154  * exactly what our demands must be.
2155  *
2156  * We'll close the channel
2157  * to the other peer once our demands are met.
2158  */
2161  maybe_finish (op);
2162  return;
2163  default:
2164  GNUNET_break_op (0);
2165  fail_union_operation (op);
2166  return;
2167  }
2168 }
2169 
2176 void
2178  const struct GNUNET_MessageHeader *mh)
2179 {
2180  send_client_done (cls);
2181 }
2182 
2183 
2191 static struct OperationState *
2193  const struct GNUNET_MessageHeader *opaque_context)
2194 {
2195  struct OperationState *state;
2196  struct GNUNET_MQ_Envelope *ev;
2197  struct OperationRequestMessage *msg;
2198 
2199  ev = GNUNET_MQ_msg_nested_mh (msg,
2201  opaque_context);
2202  if (NULL == ev)
2203  {
2204  /* the context message is too large */
2205  GNUNET_break (0);
2206  return NULL;
2207  }
2208  state = GNUNET_new (struct OperationState);
2210  GNUNET_NO);
2211  /* copy the current generation's strata estimator for this operation */
2212  state->se = strata_estimator_dup (op->set->state->se);
2213  /* we started the operation, thus we have to send the operation request */
2214  state->phase = PHASE_EXPECT_SE;
2215  state->salt_receive = state->salt_send = 42; // FIXME?????
2217  "Initiating union operation evaluation\n");
2219  "# of total union operations",
2220  1,
2221  GNUNET_NO);
2223  "# of initiated union operations",
2224  1,
2225  GNUNET_NO);
2226  msg->operation = htonl (GNUNET_SET_OPERATION_UNION);
2227  GNUNET_MQ_send (op->mq,
2228  ev);
2229 
2230  if (NULL != opaque_context)
2232  "sent op request with context message\n");
2233  else
2235  "sent op request without context message\n");
2236 
2237  op->state = state;
2240  return state;
2241 }
2242 
2243 
2250 static struct OperationState *
2252 {
2253  struct OperationState *state;
2254  const struct StrataEstimator *se;
2255  struct GNUNET_MQ_Envelope *ev;
2256  struct StrataEstimatorMessage *strata_msg;
2257  char *buf;
2258  size_t len;
2259  uint16_t type;
2260 
2262  "accepting set union operation\n");
2264  "# of accepted union operations",
2265  1,
2266  GNUNET_NO);
2268  "# of total union operations",
2269  1,
2270  GNUNET_NO);
2271 
2272  state = GNUNET_new (struct OperationState);
2273  state->se = strata_estimator_dup (op->set->state->se);
2275  GNUNET_NO);
2276  state->salt_receive = state->salt_send = 42; // FIXME?????
2277  op->state = state;
2280 
2281  /* kick off the operation */
2282  se = state->se;
2283  buf = GNUNET_malloc (se->strata_count * IBF_BUCKET_SIZE * se->ibf_size);
2284  len = strata_estimator_write (se,
2285  buf);
2286  if (len < se->strata_count * IBF_BUCKET_SIZE * se->ibf_size)
2288  else
2290  ev = GNUNET_MQ_msg_extra (strata_msg,
2291  len,
2292  type);
2293  GNUNET_memcpy (&strata_msg[1],
2294  buf,
2295  len);
2296  GNUNET_free (buf);
2297  strata_msg->set_size
2299  GNUNET_MQ_send (op->mq,
2300  ev);
2301  state->phase = PHASE_EXPECT_IBF;
2302  return state;
2303 }
2304 
2305 
2314 static struct SetState *
2316 {
2317  struct SetState *set_state;
2318 
2320  "union set created\n");
2321  set_state = GNUNET_new (struct SetState);
2324  if (NULL == set_state->se)
2325  {
2327  "Failed to allocate strata estimator\n");
2328  GNUNET_free (set_state);
2329  return NULL;
2330  }
2331  return set_state;
2332 }
2333 
2334 
2341 static void
2342 union_add (struct SetState *set_state,
2343  struct ElementEntry *ee)
2344 {
2345  strata_estimator_insert (set_state->se,
2346  get_ibf_key (&ee->element_hash));
2347 }
2348 
2349 
2357 static void
2358 union_remove (struct SetState *set_state,
2359  struct ElementEntry *ee)
2360 {
2361  strata_estimator_remove (set_state->se,
2362  get_ibf_key (&ee->element_hash));
2363 }
2364 
2365 
2371 static void
2372 union_set_destroy (struct SetState *set_state)
2373 {
2374  if (NULL != set_state->se)
2375  {
2376  strata_estimator_destroy (set_state->se);
2377  set_state->se = NULL;
2378  }
2379  GNUNET_free (set_state);
2380 }
2381 
2382 
2389 static struct SetState *
2391 {
2392  struct SetState *new_state;
2393 
2394  GNUNET_assert ( (NULL != state) &&
2395  (NULL != state->se) );
2396  new_state = GNUNET_new (struct SetState);
2397  new_state->se = strata_estimator_dup (state->se);
2398 
2399  return new_state;
2400 }
2401 
2402 
2408 static void
2410 {
2411  send_client_done (op);
2413  GNUNET_YES);
2414 }
2415 
2416 
2423 const struct SetVT *
2425 {
2426  static const struct SetVT union_vt = {
2428  .add = &union_add,
2429  .remove = &union_remove,
2430  .destroy_set = &union_set_destroy,
2431  .evaluate = &union_evaluate,
2432  .accept = &union_accept,
2433  .cancel = &union_op_cancel,
2434  .copy_state = &union_copy_state,
2435  .channel_death = &union_channel_death
2436  };
2437 
2438  return &union_vt;
2439 }
Context for op_get_element_iterator.
We sent the strata estimator, and expect an IBF.
uint32_t offset
Offset of the strata in the rest of the message.
Client gets only elements that have been added to the set.
struct StrataEstimator * se
The strata estimator is only generated once for each set.
State of an evaluate operation with another peer.
static struct OperationState * union_accept(struct Operation *op)
Accept an union operation request from a remote peer.
static int send_full_element_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Send a set element.
struct GNUNET_CONTAINER_MultiHashMap32 * key_to_element
Maps unsalted IBF-Keys to elements.
The other peer is decoding the IBF we just sent.
#define LOG(kind,...)
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS
Actual set elements.
enum GNUNET_SET_ResultMode result_mode
When are elements sent to the client, and which elements are sent?
uint32_t received_fresh
Number of elements we received from the other peer that were not in the local set yet...
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
static unsigned int element_size
int received
Did we receive this element? Even if element->is_foreign is false, we might have received the element...
uint8_t reserved1
Padding, must be 0.
void handle_union_p2p_elements(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Handle an element message from a remote peer.
int _GSS_is_element_of_operation(struct ElementEntry *ee, struct Operation *op)
Is element ee part of the set used by op?
struct InvertibleBloomFilter * remote_ibf
The IBF we currently receive.
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 struct GNUNET_IDENTITY_EgoLookup * el
EgoLookup.
#define MAX_BUCKETS_PER_MESSAGE
Number of buckets that can be transmitted in one message.
#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_MESSAGE_TYPE_SET_UNION_P2P_OFFER
Tell the other peer which hashes match a given IBF key.
Element should be added to the result set of the remote peer, i.e.
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).
struct GNUNET_MQ_Handle * mq
MQ to talk to client.
We are decoding an IBF.
struct SetState * state
Implementation-specific state.
Message sent by the service to the client to indicate an element that is removed (set intersection) o...
Definition: set.h:246
uint32_t salt
Salt currently used for BF construction (by us or the other peer, depending on where we are in the co...
static int op_get_element_iterator(void *cls, uint32_t key, void *value)
Iterator over the mapping from IBF keys to element entries.
Element stored in a set.
struct GNUNET_HashCode element_hash
Hash of the element.
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.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MulitHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
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.
Message containing buckets of an invertible bloom filter.
Element should be added to the result set of the local peer, i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static int prepare_ibf(struct Operation *op, uint32_t size)
Create an ibf with the operation&#39;s elements of the specified size.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
struct GNUNET_CADET_Channel * channel
Channel to the peer.
int check_union_p2p_elements(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Check an element message from a remote peer.
Invertible bloom filter (IBF).
Definition: ibf.h:82
struct ElementEntry * element
The actual element associated with the key.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_ADD or GNUNET_MESSAGE_TYPE_SET_REMOVE.
Definition: set.h:288
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE(C)
#define GNUNET_MESSAGE_TYPE_SET_RESULT
Create an empty set.
uint32_t request_id
id the result belongs to
Definition: set.h:261
UnionOperationPhase
Current phase we are in for a union operation.
void handle_union_p2p_full_done(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a "full done" message.
int check_union_p2p_full_element(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Check a full element message from a remote peer.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
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...
The protocol is almost finished, but we still have to flush our message queue and/or expect some elem...
#define GNUNET_NO
Definition: gnunet_common.h:81
void _GSS_operation_destroy(struct Operation *op, int gc)
Destroy the given operation.
uint64_t initial_size
Initial size of our set, just before the operation started.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
void handle_union_p2p_full_element(void *cls, const struct GNUNET_SET_ElementMessage *emsg)
Handle an element message from a remote peer.
void strata_estimator_remove(struct StrataEstimator *se, struct IBF_Key key)
Remove a key from the strata estimator.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint64_t key_val
Definition: ibf.h:47
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MulitHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
static void send_client_done(void *cls)
Signal to the client that the operation has finished and destroy the operation.
int client_done_sent
Did we send the client that we are done?
void handle_union_p2p_ibf(void *cls, const struct IBFMessage *msg)
Handle an IBF message from a remote peer.
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:284
uint32_t salt_send
Salt that we&#39;re using for sending IBFs.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
int 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)...
static void union_set_destroy(struct SetState *set_state)
Destroy a set that supports the union operation.
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 void union_add(struct SetState *set_state, struct ElementEntry *ee)
Add the element from the given element message to the set.
static int ret
Final status code.
Definition: gnunet-arm.c:89
We sent the request message, and expect a strata estimator.
int 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.
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.
Success, all elements have been sent (and received).
const struct SetVT * _GSS_union_vt()
Get the table with implementing functions for set union.
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1242
uint16_t element_type
Type of the element to add or remove.
Definition: set.h:293
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
const void * data
Actual data of the element.
A handle to a strata estimator.
struct StrataEstimator * strata_estimator_dup(struct StrataEstimator *se)
Make a copy of a strata estimator.
void handle_union_p2p_done(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a done message from a remote peer.
static void salt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
FIXME.
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_STATISTICS_Handle * _GSS_statistics
Statistics handle.
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...
The key entry is used to associate an ibf key with an element.
uint64_t current_size
Current set size.
Definition: set.h:256
struct InvertibleBloomFilter * ibf_dup(const struct InvertibleBloomFilter *ibf)
Create a copy of an IBF, the copy has to be destroyed properly.
Definition: ibf.c:368
static int send_ibf(struct Operation *op, uint16_t ibf_order)
Send an ibf of appropriate size.
static int prepare_ibf_iterator(void *cls, uint32_t key, void *value)
Insert a key into an ibf.
uint32_t received_total
Total number of elements received from the other peer.
uint32_t size
How many cells does this IBF have?
Definition: ibf.h:87
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
static struct SetState * union_set_create(void)
Create a new set supporting the union operation.
uint32_t salt_receive
Salt for the IBF we&#39;ve received and that we&#39;re currently decoding.
In the penultimate phase, we wait until all our demands are satisfied.
struct StrataEstimator * se
Copy of the set&#39;s strata estimator at the time of creation of this operation.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
Request a set operation from a remote peer.
void handle_union_p2p_strata_estimator(void *cls, const struct StrataEstimatorMessage *msg)
Handle a strata estimator from a remote peer.
enum State state
current state of profiling
#define GNUNET_memcpy(dst, src, n)
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC
Compressed strata estimator.
static char * value
Value of the record to add/remove.
Information about an element element in the set.
The other peer refused to to the operation with us, or something went wrong.
int check_union_p2p_strata_estimator(void *cls, const struct StrataEstimatorMessage *msg)
Handle a strata estimator from a remote peer.
int check_union_p2p_offer(void *cls, const struct GNUNET_MessageHeader *mh)
Check offer (of struct GNUNET_HashCodes).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
void strata_estimator_destroy(struct StrataEstimator *se)
Destroy a strata estimator, free all of its resources.
Everything went ok, we are transmitting an element of the result (in set, or to be removed from set...
Dispatch table for a specific set operation.
int remote
GNUNET_YES if the element is a remote element, and does not belong to the operation&#39;s set...
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
static int decode_and_send(struct Operation *op)
Decode which elements are missing on each side, and send the appropriate offers and inquiries...
static void union_op_cancel(struct Operation *op)
Destroy the union operation.
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:222
uint8_t order
Order of the whole ibf, where num_buckets = 2^order.
struct IBF_Key ibf_key
IBF key for the entry, derived from the current salt.
struct KeyEntry * k
FIXME.
enum IntersectionOperationPhase phase
Current state of the operation.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE
Strata estimator.
uint16_t result_status
Was the evaluation successful? Contains an enum GNUNET_SET_Status in NBO.
Definition: set.h:267
#define IBF_BUCKET_SIZE
Size of one ibf bucket in bytes.
Definition: ibf.h:72
unsigned int GNUNET_CONTAINER_multihashmap32_size(const struct GNUNET_CONTAINER_MultiHashMap32 *map)
Get the number of key-value pairs in the map.
uint16_t status
See PRISM_STATUS_*-constants.
static char buf[2048]
int 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.
#define MAX_IBF_ORDER
The maximum size of an ibf we use is 2^(MAX_IBF_ORDER).
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE
Set operation is done.
void ibf_subtract(struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2)
Subtract ibf2 from ibf1, storing the result in ibf1.
Definition: ibf.c:346
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.
unsigned int strata_count
Size of the IBF array in strata.
void strata_estimator_insert(struct StrataEstimator *se, struct IBF_Key key)
Add a key to the strata estimator.
size_t strata_estimator_write(const struct StrataEstimator *se, void *buf)
Write the given strata estimator to the buffer.
Internal representation of the hash map.
A 512-bit hashcode.
Client gets notified of the required changes for both the local and the remote set.
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.
static int res
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
static void op_register_element(struct Operation *op, struct ElementEntry *ee, int received)
Insert an element into the union operation&#39;s key-to-element mapping.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
static int send_offers_iterator(void *cls, uint32_t key, void *value)
Iterator to send elements to a remote peer.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL
Demand the whole element from the other peer, given only the hash code.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:321
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
uint16_t element_type
Type of the element attachted to the message, if any.
Definition: set.h:272
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:315
unsigned int ibf_buckets_received
Number of ibf buckets already received into the remote_ibf.
struct GNUNET_HashCode key
The key used in the DHT.
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
invertible bloom filter
static unsigned int size
Size of the "table".
Definition: peer.c:67
static void union_channel_death(struct Operation *op)
Handle case where channel went down for an operation.
void handle_union_p2p_over(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a over message from a remote peer.
#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...
Definition: gnunet_mq_lib.h:88
int byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
void ibf_destroy(struct InvertibleBloomFilter *ibf)
Destroy all resources associated with the invertible bloom filter.
Definition: ibf.c:388
const char * name
char * getenv()
Strata estimator together with the peer&#39;s overall set size.
struct InvertibleBloomFilter * ibf_create(uint32_t size, uint8_t hash_num)
Create an invertible bloom filter.
Definition: ibf.c:76
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&#39;s element set.
unsigned int strata_estimator_difference(const struct StrataEstimator *se1, const struct StrataEstimator *se2)
Estimate set difference with two strata estimators, i.e.
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
int 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.
int check_union_p2p_ibf(void *cls, const struct IBFMessage *msg)
Check an IBF message from a remote peer.
void handle_union_p2p_request_full(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a request for full set transmission.
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.
Extra state required for efficient set intersection.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF
Invertible bloom filter.
uint16_t reserved2
Padding, must be 0.
struct InvertibleBloomFilter * local_ibf
The IBF with the local set&#39;s element.
Allow multiple values with the same key.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.
void ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
Insert a key into an IBF.
Definition: ibf.c:164
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
Definition: gnunet_mq_lib.h:76
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.
static void initialize_key_to_element(struct Operation *op)
Initialize the IBF key to element mapping local to this set operation.
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Send an ack on the channel to confirm the processing of a message.
Definition: cadet_api.c:973
static void unsalt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
FIXME.
uint16_t reserved
For alignment, always zero.
Definition: set.h:298
static void maybe_finish(struct Operation *op)
Tests if the operation is finished, and if so notify.
uint32_t salt
Salt used when hashing elements for this IBF.
struct GNUNET_MQ_Handle * mq
Message queue for the channel.
uint32_t client_request_id
ID used to identify an operation between service and client.
#define IBF_ALPHA
Number of buckets used in the ibf per estimated difference.
#define SE_IBF_SIZE
Size of the IBFs in the strata estimator.
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.
Definition: crypto_hash.c:278
#define SE_IBF_HASH_NUM
The hash num parameter for the difference digests and strata estimators.
uint16_t size
Number of bytes in the buffer pointed to by data.
common components for the implementation the different set operations
Continuation for multi part IBFs.
#define GNUNET_log(kind,...)
two-peer set operations
Message sent by client to the service to add or remove an element to/from the set.
Definition: set.h:282
struct GNUNET_SET_Element element
The actual element.
uint32_t operation
Operation to request, values from enum GNUNET_SET_OperationType
struct GNUNET_CONTAINER_MultiHashMap * elements
Maps struct GNUNET_HashCode * to struct ElementEntry *.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
#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 ...
struct Operation * op
Operation for which the elements should be sent.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
void _GSS_operation_destroy2(struct Operation *op)
This function probably should not exist and be replaced by inlining more specific logic in the variou...
Header for all communications.
#define GNUNET_YES
Definition: gnunet_common.h:80
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT
Send a set element, not as response to a demand but because we&#39;re sending the full set...
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:353
struct ClientState * cs
Client that owns the set.
static void send_full_set(struct Operation *op)
Switch to full set transmission for op.
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).
struct GNUNET_CONTAINER_MultiHashMap * demanded_hashes
Hashes for elements that we have demanded from the other peer.
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.
SetCreateImpl create
Callback for the set creation.
static struct IBF_Key get_ibf_key(const struct GNUNET_HashCode *src)
Derive the IBF key from a hash code and a salt.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
In the ultimate phase, we wait until our demands are satisfied and then quit (sending another DONE me...
Keys that can be inserted into and removed from an IBF.
Definition: ibf.h:45
uint32_t salt
Salt used when hashing elements for this inquiry.
#define SE_STRATA_COUNT
Number of IBFs in a strata estimator.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
Set union, return all elements that are in at least one of the sets.
static struct SetState * union_copy_state(struct SetState *state)
Copy union-specific set state.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY
Tell the other peer to send us a list of hashes that match an IBF key.
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).
int GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:91
static void union_remove(struct SetState *set_state, struct ElementEntry *ee)
Remove the element given in the element message from the set.
Used as a closure for sending elements with a specific IBF key.
Peer-to-Peer messages for gnunet set.
struct GNUNET_HashCode hash
FIXME.
After sending the full set, wait for responses with the elements that the local peer is missing...
struct IBF_Key ibf_key
The IBF key whose matching elements should be sent.
#define GNUNET_malloc(size)
Wrapper around malloc.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t element_type
Application-specific element type.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND
Demand the whole element from the other peer, given only the hash code.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
struct SetContent * content
Content, possibly shared by multiple sets, and thus reference counted.
int force_full
Always send full sets, even if delta operations would be more efficient.
unsigned int ibf_size
Size of each IBF stratum (in bytes)