GNUnet  0.10.x
gnunet-service-set.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 "gnunet-service-set.h"
31 
36 #define INCOMING_CHANNEL_TIMEOUT GNUNET_TIME_UNIT_MINUTES
37 
38 
47 
52 
56  struct Set *source_set;
57 
61  uint32_t cookie;
62 };
63 
64 
69 struct Listener {
73  struct Listener *next;
74 
78  struct Listener *prev;
79 
85  struct Operation *op_head;
86 
92  struct Operation *op_tail;
93 
98  struct ClientState *cs;
99 
104 
110 
114  enum GNUNET_SET_OperationType operation;
115 };
116 
117 
122 static struct GNUNET_CADET_Handle *cadet;
123 
128 
133 
137 static uint32_t lazy_copy_cookie;
138 
143 
147 static struct Listener *listener_head;
148 
152 static struct Listener *listener_tail;
153 
157 static unsigned int num_clients;
158 
163 static int in_shutdown;
164 
171 static uint32_t suggest_id;
172 
173 
182 static struct Operation *
183 get_incoming(uint32_t id)
184 {
185  for (struct Listener *listener = listener_head; NULL != listener;
187  {
188  for (struct Operation *op = listener->op_head; NULL != op; op = op->next)
189  if (op->suggest_id == id)
190  return op;
191  }
192  return NULL;
193 }
194 
195 
201 static void
203 {
204  struct Listener *listener;
205 
207  "Destroying incoming operation %p\n",
208  op);
209  if (NULL != (listener = op->listener))
210  {
211  GNUNET_CONTAINER_DLL_remove(listener->op_head, listener->op_tail, op);
212  op->listener = NULL;
213  }
214  if (NULL != op->timeout_task)
215  {
217  op->timeout_task = NULL;
218  }
220 }
221 
222 
231 
235  unsigned int min_op_generation;
236 
240  unsigned int max_op_generation;
241 };
242 
243 
253 static int
254 garbage_collect_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
255 {
256  //struct GarbageContext *gc = cls;
257  //struct ElementEntry *ee = value;
258 
259  //if (GNUNET_YES != ee->removed)
260  // return GNUNET_OK;
261  //if ( (gc->max_op_generation < ee->generation_added) ||
262  // (ee->generation_removed > gc->min_op_generation) )
263  //{
264  // GNUNET_assert (GNUNET_YES ==
265  // GNUNET_CONTAINER_multihashmap_remove (gc->map,
266  // key,
267  // ee));
268  // GNUNET_free (ee);
269  //}
270  return GNUNET_OK;
271 }
272 
273 
281 static void
283 {
284  struct GarbageContext gc;
285 
286  gc.min_op_generation = UINT_MAX;
287  gc.max_op_generation = 0;
288  for (struct Operation *op = set->ops_head; NULL != op; op = op->next)
289  {
290  gc.min_op_generation =
291  GNUNET_MIN(gc.min_op_generation, op->generation_created);
292  gc.max_op_generation =
293  GNUNET_MAX(gc.max_op_generation, op->generation_created);
294  }
295  gc.map = set->content->elements;
296  GNUNET_CONTAINER_multihashmap_iterate(set->content->elements,
298  &gc);
299 }
300 
301 
310 static int
311 is_excluded_generation(unsigned int generation,
312  struct GenerationRange *excluded,
313  unsigned int excluded_size)
314 {
315  for (unsigned int i = 0; i < excluded_size; i++)
316  if ((generation >= excluded[i].start) && (generation < excluded[i].end))
317  return GNUNET_YES;
318  return GNUNET_NO;
319 }
320 
321 
331 static int
333  unsigned int query_generation,
334  struct GenerationRange *excluded,
335  unsigned int excluded_size)
336 {
337  struct MutationEvent *mut;
338  int is_present;
339 
340  GNUNET_assert(NULL != ee->mutations);
341  if (GNUNET_YES ==
342  is_excluded_generation(query_generation, excluded, excluded_size))
343  {
344  GNUNET_break(0);
345  return GNUNET_NO;
346  }
347 
348  is_present = GNUNET_NO;
349 
350  /* Could be made faster with binary search, but lists
351  are small, so why bother. */
352  for (unsigned int i = 0; i < ee->mutations_size; i++)
353  {
354  mut = &ee->mutations[i];
355 
356  if (mut->generation > query_generation)
357  {
358  /* The mutation doesn't apply to our generation
359  anymore. We can'b break here, since mutations aren't
360  sorted by generation. */
361  continue;
362  }
363 
364  if (GNUNET_YES ==
365  is_excluded_generation(mut->generation, excluded, excluded_size))
366  {
367  /* The generation is excluded (because it belongs to another
368  fork via a lazy copy) and thus mutations aren't considered
369  for membership testing. */
370  continue;
371  }
372 
373  /* This would be an inconsistency in how we manage mutations. */
374  if ((GNUNET_YES == is_present) && (GNUNET_YES == mut->added))
375  GNUNET_assert(0);
376  /* Likewise. */
377  if ((GNUNET_NO == is_present) && (GNUNET_NO == mut->added))
378  GNUNET_assert(0);
379 
380  is_present = mut->added;
381  }
382 
383  return is_present;
384 }
385 
386 
394 int
396 {
397  return is_element_of_generation(ee,
398  op->generation_created,
401 }
402 
403 
417 void
419 {
420  struct Set *set = op->set;
421  struct GNUNET_CADET_Channel *channel;
422 
423  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Destroying operation %p\n", op);
424  GNUNET_assert(NULL == op->listener);
425  if (NULL != op->state)
426  {
427  set->vt->cancel(op);
428  op->state = NULL;
429  }
430  if (NULL != set)
431  {
432  GNUNET_CONTAINER_DLL_remove(set->ops_head, set->ops_tail, op);
433  op->set = NULL;
434  }
435  if (NULL != op->context_msg)
436  {
438  op->context_msg = NULL;
439  }
440  if (NULL != (channel = op->channel))
441  {
442  /* This will free op; called conditionally as this helper function
443  is also called from within the channel disconnect handler. */
444  op->channel = NULL;
446  }
447  if ((NULL != set) && (GNUNET_YES == gc))
449  /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
450  * there was a channel end handler that will free 'op' on the call stack. */
451 }
452 
453 
462 static void *
464  struct GNUNET_SERVICE_Client *c,
465  struct GNUNET_MQ_Handle *mq)
466 {
467  struct ClientState *cs;
468 
469  num_clients++;
470  cs = GNUNET_new(struct ClientState);
471  cs->client = c;
472  cs->mq = mq;
473  return cs;
474 }
475 
476 
485 static int
487  const struct GNUNET_HashCode *key,
488  void *value)
489 {
490  struct ElementEntry *ee = value;
491 
493  GNUNET_free(ee);
494  return GNUNET_YES;
495 }
496 
497 
505 static void
507  struct GNUNET_SERVICE_Client *client,
508  void *internal_cls)
509 {
510  struct ClientState *cs = internal_cls;
511  struct Operation *op;
512  struct Listener *listener;
513  struct Set *set;
514 
515  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, cleaning up\n");
516  if (NULL != (set = cs->set))
517  {
518  struct SetContent *content = set->content;
519  struct PendingMutation *pm;
520  struct PendingMutation *pm_current;
521  struct LazyCopyRequest *lcr;
522 
523  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Destroying client's set\n");
524  /* Destroy pending set operations */
525  while (NULL != set->ops_head)
526  _GSS_operation_destroy(set->ops_head, GNUNET_NO);
527 
528  /* Destroy operation-specific state */
529  GNUNET_assert(NULL != set->state);
530  set->vt->destroy_set(set->state);
531  set->state = NULL;
532 
533  /* Clean up ongoing iterations */
534  if (NULL != set->iter)
535  {
537  set->iter = NULL;
538  set->iteration_id++;
539  }
540 
541  /* discard any pending mutations that reference this set */
542  pm = content->pending_mutations_head;
543  while (NULL != pm)
544  {
545  pm_current = pm;
546  pm = pm->next;
547  if (pm_current->set == set)
548  {
550  content->pending_mutations_tail,
551  pm_current);
552  GNUNET_free(pm_current);
553  }
554  }
555 
556  /* free set content (or at least decrement RC) */
557  set->content = NULL;
558  GNUNET_assert(0 != content->refcount);
559  content->refcount--;
560  if (0 == content->refcount)
561  {
562  GNUNET_assert(NULL != content->elements);
565  NULL);
567  content->elements = NULL;
568  GNUNET_free(content);
569  }
570  GNUNET_free_non_null(set->excluded_generations);
571  set->excluded_generations = NULL;
572 
573  /* remove set from pending copy requests */
574  lcr = lazy_copy_head;
575  while (NULL != lcr)
576  {
577  struct LazyCopyRequest *lcr_current = lcr;
578 
579  lcr = lcr->next;
580  if (lcr_current->source_set == set)
581  {
582  GNUNET_CONTAINER_DLL_remove(lazy_copy_head,
583  lazy_copy_tail,
584  lcr_current);
585  GNUNET_free(lcr_current);
586  }
587  }
588  GNUNET_free(set);
589  }
590 
591  if (NULL != (listener = cs->listener))
592  {
593  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Destroying client's listener\n");
595  listener->open_port = NULL;
596  while (NULL != (op = listener->op_head))
597  {
599  "Destroying incoming operation `%u' from peer `%s'\n",
600  (unsigned int)op->client_request_id,
601  GNUNET_i2s(&op->peer));
602  incoming_destroy(op);
603  }
604  GNUNET_CONTAINER_DLL_remove(listener_head, listener_tail, listener);
605  GNUNET_free(listener);
606  }
607  GNUNET_free(cs);
608  num_clients--;
609  if ((GNUNET_YES == in_shutdown) && (0 == num_clients))
610  {
611  if (NULL != cadet)
612  {
614  cadet = NULL;
615  }
616  }
617 }
618 
619 
628 static int
630 {
631  struct Operation *op = cls;
632  struct Listener *listener = op->listener;
633  const struct GNUNET_MessageHeader *nested_context;
634 
635  /* double operation request */
636  if (0 != op->suggest_id)
637  {
638  GNUNET_break_op(0);
639  return GNUNET_SYSERR;
640  }
641  /* This should be equivalent to the previous condition, but can't hurt to check twice */
642  if (NULL == op->listener)
643  {
644  GNUNET_break(0);
645  return GNUNET_SYSERR;
646  }
647  if (listener->operation !=
648  (enum GNUNET_SET_OperationType)ntohl(msg->operation))
649  {
650  GNUNET_break_op(0);
651  return GNUNET_SYSERR;
652  }
653  nested_context = GNUNET_MQ_extract_nested_mh(msg);
654  if ((NULL != nested_context) &&
655  (ntohs(nested_context->size) > GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE))
656  {
657  GNUNET_break_op(0);
658  return GNUNET_SYSERR;
659  }
660  return GNUNET_OK;
661 }
662 
663 
681 static void
683 {
684  struct Operation *op = cls;
685  struct Listener *listener = op->listener;
686  const struct GNUNET_MessageHeader *nested_context;
687  struct GNUNET_MQ_Envelope *env;
688  struct GNUNET_SET_RequestMessage *cmsg;
689 
690  nested_context = GNUNET_MQ_extract_nested_mh(msg);
691  /* Make a copy of the nested_context (application-specific context
692  information that is opaque to set) so we can pass it to the
693  listener later on */
694  if (NULL != nested_context)
695  op->context_msg = GNUNET_copy_message(nested_context);
696  op->remote_element_count = ntohl(msg->element_count);
697  GNUNET_log(
699  "Received P2P operation request (op %u, port %s) for active listener\n",
700  (uint32_t)ntohl(msg->operation),
701  GNUNET_h2s(&op->listener->app_id));
702  GNUNET_assert(0 == op->suggest_id);
703  if (0 == suggest_id)
704  suggest_id++;
705  op->suggest_id = suggest_id++;
706  GNUNET_assert(NULL != op->timeout_task);
708  op->timeout_task = NULL;
709  env = GNUNET_MQ_msg_nested_mh(cmsg,
711  op->context_msg);
712  GNUNET_log(
714  "Suggesting incoming request with accept id %u to listener %p of client %p\n",
715  op->suggest_id,
716  listener,
717  listener->cs);
718  cmsg->accept_id = htonl(op->suggest_id);
719  cmsg->peer_id = op->peer;
720  GNUNET_MQ_send(listener->cs->mq, env);
721  /* NOTE: GNUNET_CADET_receive_done() will be called in
722  #handle_client_accept() */
723 }
724 
725 
732 static void
733 execute_add(struct Set *set, const struct GNUNET_SET_ElementMessage *msg)
734 {
735  struct GNUNET_SET_Element el;
736  struct ElementEntry *ee;
737  struct GNUNET_HashCode hash;
738 
740  el.size = ntohs(msg->header.size) - sizeof(*msg);
741  el.data = &msg[1];
742  el.element_type = ntohs(msg->element_type);
743  GNUNET_SET_element_hash(&el, &hash);
744  ee = GNUNET_CONTAINER_multihashmap_get(set->content->elements, &hash);
745  if (NULL == ee)
746  {
748  "Client inserts element %s of size %u\n",
749  GNUNET_h2s(&hash),
750  el.size);
751  ee = GNUNET_malloc(el.size + sizeof(*ee));
752  ee->element.size = el.size;
753  GNUNET_memcpy(&ee[1], el.data, el.size);
754  ee->element.data = &ee[1];
756  ee->remote = GNUNET_NO;
757  ee->mutations = NULL;
758  ee->mutations_size = 0;
759  ee->element_hash = hash;
762  set->content->elements,
763  &ee->element_hash,
764  ee,
766  }
767  else if (GNUNET_YES ==
769  set->current_generation,
770  set->excluded_generations,
771  set->excluded_generations_size))
772  {
774  "Client inserted element %s of size %u twice (ignored)\n",
775  GNUNET_h2s(&hash),
776  el.size);
777 
778  /* same element inserted twice */
779  return;
780  }
781 
782  {
783  struct MutationEvent mut = { .generation = set->current_generation,
784  .added = GNUNET_YES };
786  }
787  set->vt->add(set->state, ee);
788 }
789 
790 
797 static void
798 execute_remove(struct Set *set, const struct GNUNET_SET_ElementMessage *msg)
799 {
800  struct GNUNET_SET_Element el;
801  struct ElementEntry *ee;
802  struct GNUNET_HashCode hash;
803 
805  el.size = ntohs(msg->header.size) - sizeof(*msg);
806  el.data = &msg[1];
807  el.element_type = ntohs(msg->element_type);
808  GNUNET_SET_element_hash(&el, &hash);
809  ee = GNUNET_CONTAINER_multihashmap_get(set->content->elements, &hash);
810  if (NULL == ee)
811  {
812  /* Client tried to remove non-existing element. */
814  "Client removes non-existing element of size %u\n",
815  el.size);
816  return;
817  }
819  set->current_generation,
820  set->excluded_generations,
821  set->excluded_generations_size))
822  {
823  /* Client tried to remove element twice */
825  "Client removed element of size %u twice (ignored)\n",
826  el.size);
827  return;
828  }
829  else
830  {
831  struct MutationEvent mut = { .generation = set->current_generation,
832  .added = GNUNET_NO };
833 
835  "Client removes element of size %u\n",
836  el.size);
837 
839  }
840  set->vt->remove(set->state, ee);
841 }
842 
843 
850 static void
852 {
853  switch (ntohs(msg->header.type))
854  {
856  execute_add(set, msg);
857  break;
858 
860  execute_remove(set, msg);
861  break;
862 
863  default:
864  GNUNET_break(0);
865  }
866 }
867 
868 
875 static void
877 {
878  struct PendingMutation *pm;
879 
880  if (0 != set->content->iterator_count)
881  return; /* still cannot do this */
882  while (NULL != (pm = set->content->pending_mutations_head))
883  {
886  pm);
888  "Executing pending mutation on %p.\n",
889  pm->set);
890  execute_mutation(pm->set, pm->msg);
891  GNUNET_free(pm->msg);
892  GNUNET_free(pm);
893  }
894 }
895 
896 
910 static void
912 {
913  int ret;
914  struct ElementEntry *ee;
915  struct GNUNET_MQ_Envelope *ev;
917 
918  GNUNET_assert(NULL != set->iter);
919  do
920  {
922  NULL,
923  (const void **)&ee);
924  if (GNUNET_NO == ret)
925  {
926  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Iteration on %p done.\n", set);
929  set->iter = NULL;
930  set->iteration_id++;
931  GNUNET_assert(set->content->iterator_count > 0);
932  set->content->iterator_count--;
934  GNUNET_MQ_send(set->cs->mq, ev);
935  return;
936  }
937  GNUNET_assert(NULL != ee);
938  }
939  while (GNUNET_NO ==
941  set->iter_generation,
942  set->excluded_generations,
943  set->excluded_generations_size));
945  "Sending iteration element on %p.\n",
946  set);
947  ev = GNUNET_MQ_msg_extra(msg,
948  ee->element.size,
950  GNUNET_memcpy(&msg[1], ee->element.data, ee->element.size);
951  msg->element_type = htons(ee->element.element_type);
952  msg->iteration_id = htons(set->iteration_id);
953  GNUNET_MQ_send(set->cs->mq, ev);
954 }
955 
956 
966 static void
968 {
969  struct ClientState *cs = cls;
970  struct Set *set;
971 
972  if (NULL == (set = cs->set))
973  {
974  /* attempt to iterate over a non existing set */
975  GNUNET_break(0);
977  return;
978  }
979  if (NULL != set->iter)
980  {
981  /* Only one concurrent iterate-action allowed per set */
982  GNUNET_break(0);
984  return;
985  }
987  "Iterating set %p in gen %u with %u content elements\n",
988  (void *)set,
989  set->current_generation,
990  GNUNET_CONTAINER_multihashmap_size(set->content->elements));
992  set->content->iterator_count++;
993  set->iter =
994  GNUNET_CONTAINER_multihashmap_iterator_create(set->content->elements);
995  set->iter_generation = set->current_generation;
996  send_client_element(set);
997 }
998 
999 
1008 static void
1010 {
1011  struct ClientState *cs = cls;
1012  struct Set *set;
1013 
1015  "Client created new set (operation %u)\n",
1016  (uint32_t)ntohl(msg->operation));
1017  if (NULL != cs->set)
1018  {
1019  /* There can only be one set per client */
1020  GNUNET_break(0);
1022  return;
1023  }
1024  set = GNUNET_new(struct Set);
1025  switch (ntohl(msg->operation))
1026  {
1028  set->vt = _GSS_intersection_vt();
1029  break;
1030 
1032  set->vt = _GSS_union_vt();
1033  break;
1034 
1035  default:
1036  GNUNET_free(set);
1037  GNUNET_break(0);
1039  return;
1040  }
1041  set->operation = (enum GNUNET_SET_OperationType)ntohl(msg->operation);
1042  set->state = set->vt->create();
1043  if (NULL == set->state)
1044  {
1045  /* initialization failed (i.e. out of memory) */
1046  GNUNET_free(set);
1048  return;
1049  }
1050  set->content = GNUNET_new(struct SetContent);
1051  set->content->refcount = 1;
1052  set->content->elements = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES);
1053  set->cs = cs;
1054  cs->set = set;
1056 }
1057 
1058 
1068 static void
1070 {
1071  struct Operation *op = cls;
1072 
1073  op->timeout_task = NULL;
1075  "Remote peer's incoming request timed out\n");
1076  incoming_destroy(op);
1077 }
1078 
1079 
1096 static void *
1097 channel_new_cb(void *cls,
1098  struct GNUNET_CADET_Channel *channel,
1099  const struct GNUNET_PeerIdentity *source)
1100 {
1101  struct Listener *listener = cls;
1102  struct Operation *op;
1103 
1104  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New incoming channel\n");
1105  op = GNUNET_new(struct Operation);
1106  op->listener = listener;
1107  op->peer = *source;
1108  op->channel = channel;
1109  op->mq = GNUNET_CADET_get_mq(op->channel);
1113  op);
1114  GNUNET_CONTAINER_DLL_insert(listener->op_head, listener->op_tail, op);
1115  return op;
1116 }
1117 
1118 
1135 static void
1136 channel_end_cb(void *channel_ctx, const struct GNUNET_CADET_Channel *channel)
1137 {
1138  struct Operation *op = channel_ctx;
1139 
1140  op->channel = NULL;
1142 }
1143 
1144 
1150 void
1152 {
1153  struct GNUNET_CADET_Channel *channel;
1154 
1155  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "channel_end_cb called\n");
1156  if (NULL != (channel = op->channel))
1157  {
1158  /* This will free op; called conditionally as this helper function
1159  is also called from within the channel disconnect handler. */
1160  op->channel = NULL;
1162  }
1163  if (NULL != op->listener)
1164  {
1165  incoming_destroy(op);
1166  return;
1167  }
1168  if (NULL != op->set)
1169  op->set->vt->channel_death(op);
1170  else
1172  GNUNET_free(op);
1173 }
1174 
1175 
1190 static void
1192  const struct GNUNET_CADET_Channel *channel,
1193  int window_size)
1194 {
1195  /* FIXME: not implemented, we could do flow control here... */
1196 }
1197 
1198 
1205 static void
1207 {
1208  struct ClientState *cs = cls;
1209  struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1210  { GNUNET_MQ_hd_var_size(incoming_msg,
1212  struct OperationRequestMessage,
1213  NULL),
1214  GNUNET_MQ_hd_var_size(union_p2p_ibf,
1216  struct IBFMessage,
1217  NULL),
1218  GNUNET_MQ_hd_var_size(union_p2p_elements,
1221  NULL),
1222  GNUNET_MQ_hd_var_size(union_p2p_offer,
1224  struct GNUNET_MessageHeader,
1225  NULL),
1226  GNUNET_MQ_hd_var_size(union_p2p_inquiry,
1228  struct InquiryMessage,
1229  NULL),
1230  GNUNET_MQ_hd_var_size(union_p2p_demand,
1232  struct GNUNET_MessageHeader,
1233  NULL),
1234  GNUNET_MQ_hd_fixed_size(union_p2p_done,
1236  struct GNUNET_MessageHeader,
1237  NULL),
1238  GNUNET_MQ_hd_fixed_size(union_p2p_over,
1240  struct GNUNET_MessageHeader,
1241  NULL),
1242  GNUNET_MQ_hd_fixed_size(union_p2p_full_done,
1244  struct GNUNET_MessageHeader,
1245  NULL),
1246  GNUNET_MQ_hd_fixed_size(union_p2p_request_full,
1248  struct GNUNET_MessageHeader,
1249  NULL),
1250  GNUNET_MQ_hd_var_size(union_p2p_strata_estimator,
1252  struct StrataEstimatorMessage,
1253  NULL),
1254  GNUNET_MQ_hd_var_size(union_p2p_strata_estimator,
1256  struct StrataEstimatorMessage,
1257  NULL),
1258  GNUNET_MQ_hd_var_size(union_p2p_full_element,
1261  NULL),
1262  GNUNET_MQ_hd_fixed_size(intersection_p2p_element_info,
1265  NULL),
1266  GNUNET_MQ_hd_var_size(intersection_p2p_bf,
1268  struct BFMessage,
1269  NULL),
1270  GNUNET_MQ_hd_fixed_size(intersection_p2p_done,
1272  struct IntersectionDoneMessage,
1273  NULL),
1275  struct Listener *listener;
1276 
1277  if (NULL != cs->listener)
1278  {
1279  /* max. one active listener per client! */
1280  GNUNET_break(0);
1282  return;
1283  }
1284  listener = GNUNET_new(struct Listener);
1285  listener->cs = cs;
1286  cs->listener = listener;
1287  listener->app_id = msg->app_id;
1288  listener->operation = (enum GNUNET_SET_OperationType)ntohl(msg->operation);
1289  GNUNET_CONTAINER_DLL_insert(listener_head, listener_tail, listener);
1291  "New listener created (op %u, port %s)\n",
1292  listener->operation,
1293  GNUNET_h2s(&listener->app_id));
1294  listener->open_port = GNUNET_CADET_open_port(cadet,
1295  &msg->app_id,
1296  &channel_new_cb,
1297  listener,
1299  &channel_end_cb,
1300  cadet_handlers);
1302 }
1303 
1304 
1312 static void
1314 {
1315  struct ClientState *cs = cls;
1316  struct Operation *op;
1317 
1318  op = get_incoming(ntohl(msg->accept_reject_id));
1319  if (NULL == op)
1320  {
1321  /* no matching incoming operation for this reject;
1322  could be that the other peer already disconnected... */
1324  "Client rejected unknown operation %u\n",
1325  (unsigned int)ntohl(msg->accept_reject_id));
1327  return;
1328  }
1330  "Peer request (op %u, app %s) rejected by client\n",
1331  op->listener->operation,
1332  GNUNET_h2s(&cs->listener->app_id));
1335 }
1336 
1337 
1344 static int
1346 {
1347  /* NOTE: Technically, we should probably check with the
1348  block library whether the element we are given is well-formed */
1349  return GNUNET_OK;
1350 }
1351 
1352 
1359 static void
1361 {
1362  struct ClientState *cs = cls;
1363  struct Set *set;
1364 
1365  if (NULL == (set = cs->set))
1366  {
1367  /* client without a set requested an operation */
1368  GNUNET_break(0);
1370  return;
1371  }
1373 
1374  if (0 != set->content->iterator_count)
1375  {
1376  struct PendingMutation *pm;
1377 
1378  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Scheduling mutation on set\n");
1379  pm = GNUNET_new(struct PendingMutation);
1380  pm->msg =
1382  pm->set = set;
1383  GNUNET_CONTAINER_DLL_insert_tail(set->content->pending_mutations_head,
1384  set->content->pending_mutations_tail,
1385  pm);
1386  return;
1387  }
1388  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Executing mutation on set\n");
1389  execute_mutation(set, msg);
1390 }
1391 
1392 
1399 static void
1401 {
1402  struct GenerationRange r;
1403 
1404  if (set->current_generation == set->content->latest_generation)
1405  {
1406  set->content->latest_generation++;
1407  set->current_generation++;
1408  return;
1409  }
1410 
1411  GNUNET_assert(set->current_generation < set->content->latest_generation);
1412 
1413  r.start = set->current_generation + 1;
1414  r.end = set->content->latest_generation + 1;
1415  set->content->latest_generation = r.end;
1416  set->current_generation = r.end;
1417  GNUNET_array_append(set->excluded_generations,
1418  set->excluded_generations_size,
1419  r);
1420 }
1421 
1422 
1432 static int
1434 {
1435  /* FIXME: suboptimal, even if the context below could be NULL,
1436  there are malformed messages this does not check for... */
1437  return GNUNET_OK;
1438 }
1439 
1440 
1449 static void
1451 {
1452  struct ClientState *cs = cls;
1453  struct Operation *op = GNUNET_new(struct Operation);
1454  const struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1455  { GNUNET_MQ_hd_var_size(incoming_msg,
1457  struct OperationRequestMessage,
1458  op),
1459  GNUNET_MQ_hd_var_size(union_p2p_ibf,
1461  struct IBFMessage,
1462  op),
1463  GNUNET_MQ_hd_var_size(union_p2p_elements,
1466  op),
1467  GNUNET_MQ_hd_var_size(union_p2p_offer,
1469  struct GNUNET_MessageHeader,
1470  op),
1471  GNUNET_MQ_hd_var_size(union_p2p_inquiry,
1473  struct InquiryMessage,
1474  op),
1475  GNUNET_MQ_hd_var_size(union_p2p_demand,
1477  struct GNUNET_MessageHeader,
1478  op),
1479  GNUNET_MQ_hd_fixed_size(union_p2p_done,
1481  struct GNUNET_MessageHeader,
1482  op),
1483  GNUNET_MQ_hd_fixed_size(union_p2p_over,
1485  struct GNUNET_MessageHeader,
1486  op),
1487  GNUNET_MQ_hd_fixed_size(union_p2p_full_done,
1489  struct GNUNET_MessageHeader,
1490  op),
1491  GNUNET_MQ_hd_fixed_size(union_p2p_request_full,
1493  struct GNUNET_MessageHeader,
1494  op),
1495  GNUNET_MQ_hd_var_size(union_p2p_strata_estimator,
1497  struct StrataEstimatorMessage,
1498  op),
1499  GNUNET_MQ_hd_var_size(union_p2p_strata_estimator,
1501  struct StrataEstimatorMessage,
1502  op),
1503  GNUNET_MQ_hd_var_size(union_p2p_full_element,
1506  op),
1507  GNUNET_MQ_hd_fixed_size(intersection_p2p_element_info,
1510  op),
1511  GNUNET_MQ_hd_var_size(intersection_p2p_bf,
1513  struct BFMessage,
1514  op),
1515  GNUNET_MQ_hd_fixed_size(intersection_p2p_done,
1517  struct IntersectionDoneMessage,
1518  op),
1520  struct Set *set;
1521  const struct GNUNET_MessageHeader *context;
1522 
1523  if (NULL == (set = cs->set))
1524  {
1525  GNUNET_break(0);
1526  GNUNET_free(op);
1528  return;
1529  }
1531  op->peer = msg->target_peer;
1532  op->result_mode = ntohl(msg->result_mode);
1533  op->client_request_id = ntohl(msg->request_id);
1534  op->byzantine = msg->byzantine;
1536  op->force_full = msg->force_full;
1537  op->force_delta = msg->force_delta;
1538  context = GNUNET_MQ_extract_nested_mh(msg);
1539 
1540  /* Advance generation values, so that
1541  mutations won't interfer with the running operation. */
1542  op->set = set;
1543  op->generation_created = set->current_generation;
1544  advance_generation(set);
1545  GNUNET_CONTAINER_DLL_insert(set->ops_head, set->ops_tail, op);
1547  "Creating new CADET channel to port %s for set operation type %u\n",
1548  GNUNET_h2s(&msg->app_id),
1549  set->operation);
1551  op,
1552  &msg->target_peer,
1553  &msg->app_id,
1555  &channel_end_cb,
1556  cadet_handlers);
1557  op->mq = GNUNET_CADET_get_mq(op->channel);
1558  op->state = set->vt->evaluate(op, context);
1559  if (NULL == op->state)
1560  {
1561  GNUNET_break(0);
1563  return;
1564  }
1566 }
1567 
1568 
1577 static void
1579 {
1580  struct ClientState *cs = cls;
1581  struct Set *set;
1582 
1583  if (NULL == (set = cs->set))
1584  {
1585  /* client without a set acknowledged receiving a value */
1586  GNUNET_break(0);
1588  return;
1589  }
1590  if (NULL == set->iter)
1591  {
1592  /* client sent an ack, but we were not expecting one (as
1593  set iteration has finished) */
1594  GNUNET_break(0);
1596  return;
1597  }
1599  if (ntohl(ack->send_more))
1600  {
1601  send_client_element(set);
1602  }
1603  else
1604  {
1606  set->iter = NULL;
1607  set->iteration_id++;
1608  }
1609 }
1610 
1611 
1618 static void
1620  const struct GNUNET_MessageHeader *mh)
1621 {
1622  struct ClientState *cs = cls;
1623  struct Set *set;
1624  struct LazyCopyRequest *cr;
1625  struct GNUNET_MQ_Envelope *ev;
1626  struct GNUNET_SET_CopyLazyResponseMessage *resp_msg;
1627 
1628  if (NULL == (set = cs->set))
1629  {
1630  /* client without a set requested an operation */
1631  GNUNET_break(0);
1633  return;
1634  }
1636  "Client requested creation of lazy copy\n");
1637  cr = GNUNET_new(struct LazyCopyRequest);
1638  cr->cookie = ++lazy_copy_cookie;
1639  cr->source_set = set;
1640  GNUNET_CONTAINER_DLL_insert(lazy_copy_head, lazy_copy_tail, cr);
1642  resp_msg->cookie = cr->cookie;
1643  GNUNET_MQ_send(set->cs->mq, ev);
1645 }
1646 
1647 
1654 static void
1656  void *cls,
1657  const struct GNUNET_SET_CopyLazyConnectMessage *msg)
1658 {
1659  struct ClientState *cs = cls;
1660  struct LazyCopyRequest *cr;
1661  struct Set *set;
1662  int found;
1663 
1664  if (NULL != cs->set)
1665  {
1666  /* There can only be one set per client */
1667  GNUNET_break(0);
1669  return;
1670  }
1671  found = GNUNET_NO;
1672  for (cr = lazy_copy_head; NULL != cr; cr = cr->next)
1673  {
1674  if (cr->cookie == msg->cookie)
1675  {
1676  found = GNUNET_YES;
1677  break;
1678  }
1679  }
1680  if (GNUNET_NO == found)
1681  {
1682  /* client asked for copy with cookie we don't know */
1683  GNUNET_break(0);
1685  return;
1686  }
1687  GNUNET_CONTAINER_DLL_remove(lazy_copy_head, lazy_copy_tail, cr);
1689  "Client %p requested use of lazy copy\n",
1690  cs);
1691  set = GNUNET_new(struct Set);
1692  switch (cr->source_set->operation)
1693  {
1695  set->vt = _GSS_intersection_vt();
1696  break;
1697 
1699  set->vt = _GSS_union_vt();
1700  break;
1701 
1702  default:
1703  GNUNET_assert(0);
1704  return;
1705  }
1706 
1707  if (NULL == set->vt->copy_state)
1708  {
1709  /* Lazy copy not supported for this set operation */
1710  GNUNET_break(0);
1711  GNUNET_free(set);
1712  GNUNET_free(cr);
1714  return;
1715  }
1716 
1717  set->operation = cr->source_set->operation;
1718  set->state = set->vt->copy_state(cr->source_set->state);
1719  set->content = cr->source_set->content;
1720  set->content->refcount++;
1721 
1722  set->current_generation = cr->source_set->current_generation;
1723  set->excluded_generations_size = cr->source_set->excluded_generations_size;
1724  set->excluded_generations =
1726  set->excluded_generations_size *
1727  sizeof(struct GenerationRange));
1728 
1729  /* Advance the generation of the new set, so that mutations to the
1730  of the cloned set and the source set are independent. */
1731  advance_generation(set);
1732  set->cs = cs;
1733  cs->set = set;
1734  GNUNET_free(cr);
1736 }
1737 
1738 
1745 static void
1747 {
1748  struct ClientState *cs = cls;
1749  struct Set *set;
1750  struct Operation *op;
1751  int found;
1752 
1753  if (NULL == (set = cs->set))
1754  {
1755  /* client without a set requested an operation */
1756  GNUNET_break(0);
1758  return;
1759  }
1760  found = GNUNET_NO;
1761  for (op = set->ops_head; NULL != op; op = op->next)
1762  {
1763  if (op->client_request_id == ntohl(msg->request_id))
1764  {
1765  found = GNUNET_YES;
1766  break;
1767  }
1768  }
1769  if (GNUNET_NO == found)
1770  {
1771  /* It may happen that the operation was already destroyed due to
1772  * the other peer disconnecting. The client may not know about this
1773  * yet and try to cancel the (just barely non-existent) operation.
1774  * So this is not a hard error.
1775  */
1777  "Client canceled non-existent op %u\n",
1778  (uint32_t)ntohl(msg->request_id));
1779  }
1780  else
1781  {
1783  "Client requested cancel for op %u\n",
1784  (uint32_t)ntohl(msg->request_id));
1786  }
1788 }
1789 
1790 
1799 static void
1801 {
1802  struct ClientState *cs = cls;
1803  struct Set *set;
1804  struct Operation *op;
1805  struct GNUNET_SET_ResultMessage *result_message;
1806  struct GNUNET_MQ_Envelope *ev;
1807  struct Listener *listener;
1808 
1809  if (NULL == (set = cs->set))
1810  {
1811  /* client without a set requested to accept */
1812  GNUNET_break(0);
1814  return;
1815  }
1816  op = get_incoming(ntohl(msg->accept_reject_id));
1817  if (NULL == op)
1818  {
1819  /* It is not an error if the set op does not exist -- it may
1820  * have been destroyed when the partner peer disconnected. */
1821  GNUNET_log(
1823  "Client %p accepted request %u of listener %p that is no longer active\n",
1824  cs,
1825  ntohl(msg->accept_reject_id),
1826  cs->listener);
1827  ev = GNUNET_MQ_msg(result_message, GNUNET_MESSAGE_TYPE_SET_RESULT);
1828  result_message->request_id = msg->request_id;
1829  result_message->result_status = htons(GNUNET_SET_STATUS_FAILURE);
1830  GNUNET_MQ_send(set->cs->mq, ev);
1832  return;
1833  }
1835  "Client accepting request %u\n",
1836  (uint32_t)ntohl(msg->accept_reject_id));
1837  listener = op->listener;
1838  op->listener = NULL;
1839  GNUNET_CONTAINER_DLL_remove(listener->op_head, listener->op_tail, op);
1840  op->set = set;
1841  GNUNET_CONTAINER_DLL_insert(set->ops_head, set->ops_tail, op);
1842  op->client_request_id = ntohl(msg->request_id);
1843  op->result_mode = ntohl(msg->result_mode);
1844  op->byzantine = msg->byzantine;
1846  op->force_full = msg->force_full;
1847  op->force_delta = msg->force_delta;
1848 
1849  /* Advance generation values, so that future mutations do not
1850  interfer with the running operation. */
1851  op->generation_created = set->current_generation;
1852  advance_generation(set);
1853  GNUNET_assert(NULL == op->state);
1854  op->state = set->vt->accept(op);
1855  if (NULL == op->state)
1856  {
1857  GNUNET_break(0);
1859  return;
1860  }
1861  /* Now allow CADET to continue, as we did not do this in
1862  #handle_incoming_msg (as we wanted to first see if the
1863  local client would accept the request). */
1866 }
1867 
1868 
1874 static void
1875 shutdown_task(void *cls)
1876 {
1877  /* Delay actual shutdown to allow service to disconnect clients */
1879  if (0 == num_clients)
1880  {
1881  if (NULL != cadet)
1882  {
1883  GNUNET_CADET_disconnect(cadet);
1884  cadet = NULL;
1885  }
1886  }
1887  GNUNET_STATISTICS_destroy(_GSS_statistics, GNUNET_YES);
1888  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "handled shutdown request\n");
1889 }
1890 
1891 
1900 static void
1901 run(void *cls,
1902  const struct GNUNET_CONFIGURATION_Handle *cfg,
1904 {
1905  /* FIXME: need to modify SERVICE (!) API to allow
1906  us to run a shutdown task *after* clients were
1907  forcefully disconnected! */
1909  _GSS_statistics = GNUNET_STATISTICS_create("set", cfg);
1910  cadet = GNUNET_CADET_connect(cfg);
1911  if (NULL == cadet)
1912  {
1914  _("Could not connect to CADET service\n"));
1916  return;
1917  }
1918 }
1919 
1920 
1925  "set",
1927  &run,
1930  NULL,
1931  GNUNET_MQ_hd_fixed_size(client_accept,
1933  struct GNUNET_SET_AcceptMessage,
1934  NULL),
1935  GNUNET_MQ_hd_fixed_size(client_iter_ack,
1938  NULL),
1939  GNUNET_MQ_hd_var_size(client_mutation,
1942  NULL),
1943  GNUNET_MQ_hd_fixed_size(client_create_set,
1945  struct GNUNET_SET_CreateMessage,
1946  NULL),
1947  GNUNET_MQ_hd_fixed_size(client_iterate,
1949  struct GNUNET_MessageHeader,
1950  NULL),
1951  GNUNET_MQ_hd_var_size(client_evaluate,
1954  NULL),
1955  GNUNET_MQ_hd_fixed_size(client_listen,
1957  struct GNUNET_SET_ListenMessage,
1958  NULL),
1959  GNUNET_MQ_hd_fixed_size(client_reject,
1961  struct GNUNET_SET_RejectMessage,
1962  NULL),
1963  GNUNET_MQ_hd_var_size(client_mutation,
1966  NULL),
1967  GNUNET_MQ_hd_fixed_size(client_cancel,
1969  struct GNUNET_SET_CancelMessage,
1970  NULL),
1971  GNUNET_MQ_hd_fixed_size(client_copy_lazy_prepare,
1973  struct GNUNET_MessageHeader,
1974  NULL),
1975  GNUNET_MQ_hd_fixed_size(client_copy_lazy_connect,
1978  NULL),
1980 
1981 
1982 /* end of gnunet-service-set.c */
static void handle_client_create_set(void *cls, const struct GNUNET_SET_CreateMessage *msg)
Called when a client wants to create a new set.
struct GNUNET_PeerIdentity target_peer
Peer to evaluate the operation with.
Definition: set.h:190
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
#define GNUNET_MESSAGE_TYPE_SET_CANCEL
Cancel a set operation.
static uint32_t suggest_id
Counter for allocating unique IDs for clients, used to identify incoming operation requests from remo...
struct Set * set
Set, if associated with the client, otherwise NULL.
struct GNUNET_ARM_Operation * next
This is a doubly-linked list.
Definition: arm_api.c:44
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:838
const struct SetVT * _GSS_intersection_vt(void)
Get the table with implementing functions for set intersection.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
static struct Listener * listener_tail
Listeners are held in a doubly linked list.
static void handle_client_listen(void *cls, const struct GNUNET_SET_ListenMessage *msg)
Called when a client wants to create a new listener.
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?
State we keep per client.
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.
struct GenerationRange * excluded_generations
List of generations we have to exclude, due to lazy copies.
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
uint32_t suggest_id
Unique request id for the request from a remote peer, sent to the client, which will accept or reject...
int _GSS_is_element_of_operation(struct ElementEntry *ee, struct Operation *op)
Is element ee part of the set used by op?
#define GNUNET_MESSAGE_TYPE_SET_ADD
Add element to set.
static void handle_client_mutation(void *cls, const struct GNUNET_SET_ElementMessage *msg)
Called when a client wants to add or remove an element to a set it inhabits.
uint32_t element_count
For Intersection: my element count.
struct MutationEvent * mutations
If mutations is not NULL, it contains a list of mutations, ordered by increasing generation.
Opaque handle to the service.
Definition: cadet_api.c:38
Handle to a service.
Definition: service.c:114
#define GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT
Element result for the iterating client.
#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.
int byzantine_lower_bound
Lower bound for the set size, used only when byzantine mode is enabled.
struct GNUNET_MQ_Handle * mq
MQ to talk to client.
struct PendingMutation * pending_mutations_head
Mutations requested by the client that we&#39;re unable to execute right now because we&#39;re iterating over...
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
struct SetState * state
Implementation-specific state.
#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_RESPONSE
Give the client an ID for connecting to the set&#39;s copy.
#define GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF
Bloom filter message for intersection exchange started by Bob.
Message sent by the service to the client to indicate an element that is removed (set intersection) o...
Definition: set.h:238
uint32_t request_id
Request ID to identify responses.
Definition: set.h:94
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
static int check_client_evaluate(void *cls, const struct GNUNET_SET_EvaluateMessage *msg)
Called when a client wants to initiate a set operation with another peer.
Element stored in a set.
struct GNUNET_HashCode element_hash
Hash of the element.
unsigned int refcount
Number of references to the content.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
uint8_t force_full
Always send full sets, even if delta operations would be more efficient.
Definition: set.h:112
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *internal_cls)
Clean up after a client has disconnected.
static int check_incoming_msg(void *cls, const struct OperationRequestMessage *msg)
Check a request for a set operation from another peer.
Message containing buckets of an invertible bloom filter.
#define GNUNET_MQ_extract_nested_mh(var)
Return a pointer to the message at the end of the given message.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
int added
If added is GNUNET_YES, then this is a remove event, otherwise it is an add event.
static uint32_t lazy_copy_cookie
Generator for unique cookie we set per lazy copy request.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
uint32_t cookie
Cookie identifying the request.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
uint8_t force_delta
Always use delta operation instead of sending full sets, even it it&#39;s less efficient.
Definition: set.h:106
static void execute_delayed_mutations(struct Set *set)
Execute mutations that were delayed on a set because of pending operations.
struct GNUNET_CADET_Channel * channel
Channel to the peer.
#define GNUNET_MESSAGE_TYPE_SET_EVALUATE
Evaluate a set operation.
#define INCOMING_CHANNEL_TIMEOUT
How long do we hold on to an incoming channel if there is no local listener before giving up...
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_ADD or GNUNET_MESSAGE_TYPE_SET_REMOVE.
Definition: set.h:278
#define GNUNET_MESSAGE_TYPE_SET_RESULT
Create an empty set.
A request for an operation with another client.
Definition: set.h:148
#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_PREPARE
Ask the set service to prepare a copy of a set.
unsigned int excluded_generations_size
Number of elements in array excluded_generations.
uint32_t request_id
id the result belongs to
Definition: set.h:252
#define GNUNET_MESSAGE_TYPE_SET_ACCEPT
Accept a set request.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static void shutdown_task(void *cls)
Called to clean up, after a shutdown has been requested.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
#define GNUNET_NO
Definition: gnunet_common.h:78
void _GSS_operation_destroy(struct Operation *op, int gc)
Destroy the given operation.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
Opaque handle to a channel.
Definition: cadet_api.c:79
static int is_excluded_generation(unsigned int generation, struct GenerationRange *excluded, unsigned int excluded_size)
Is generation in the range of exclusions?
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:75
struct Operation * ops_head
Evaluate operations are held in a linked list.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
Set element transmitted by service to client in response to a set iteration request.
Definition: set.h:315
static struct GNUNET_HashCode app_id
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void handle_client_evaluate(void *cls, const struct GNUNET_SET_EvaluateMessage *msg)
Called when a client wants to initiate a set operation with another peer.
A listener is inhabited by a client, and waits for evaluation requests from remote peers...
static void execute_mutation(struct Set *set, const struct GNUNET_SET_ElementMessage *msg)
Perform a mutation on a set as specified by the msg.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static int garbage_collect_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
Function invoked to check if an element can be removed from the set&#39;s history because it is no longer...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
Information about a mutation to apply to a set.
uint32_t result_mode
How should results be sent to us? See enum GNUNET_SET_ResultMode.
Definition: set.h:185
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
enum GNUNET_SET_OperationType operation
The type of the operation.
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
static void send_client_element(struct Set *set)
Send the next element of a set to the set&#39;s client.
uint8_t byzantine_lower_bound
Lower bound for the set size, used only when byzantine mode is enabled.
Definition: set.h:124
static int check_client_mutation(void *cls, const struct GNUNET_SET_ElementMessage *msg)
Called when a client wants to add or remove an element to a set it inhabits.
uint8_t force_full
Always send full sets, even if delta operations would be more efficient.
Definition: set.h:213
struct LazyCopyRequest * prev
Kept in a DLL.
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...
#define GNUNET_MESSAGE_TYPE_SET_CREATE
Create a new local set.
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1241
#define GNUNET_MESSAGE_TYPE_SET_REJECT
Reject a set request.
unsigned int generation_created
Generation in which the operation handle was created.
uint16_t element_type
Type of the element to add or remove.
Definition: set.h:283
static pa_context * context
Pulseaudio context.
const void * data
Actual data of the element.
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:973
static void channel_window_cb(void *cls, const struct GNUNET_CADET_Channel *channel, int window_size)
Function called whenever an MQ-channel&#39;s transmission window size changes.
uint32_t operation
Operation type, values of enum GNUNET_SET_OperationType
Definition: set.h:67
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.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct PendingMutation * next
Mutations are kept in a DLL.
struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
Handle to a client that is connected to a service.
Definition: service.c:246
struct GNUNET_PeerIdentity peer
The identity of the requesting peer.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
GNUNET_SERVICE_MAIN("set", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_accept, GNUNET_MESSAGE_TYPE_SET_ACCEPT, struct GNUNET_SET_AcceptMessage, NULL), GNUNET_MQ_hd_fixed_size(client_iter_ack, GNUNET_MESSAGE_TYPE_SET_ITER_ACK, struct GNUNET_SET_IterAckMessage, NULL), GNUNET_MQ_hd_var_size(client_mutation, GNUNET_MESSAGE_TYPE_SET_ADD, struct GNUNET_SET_ElementMessage, NULL), GNUNET_MQ_hd_fixed_size(client_create_set, GNUNET_MESSAGE_TYPE_SET_CREATE, struct GNUNET_SET_CreateMessage, NULL), GNUNET_MQ_hd_fixed_size(client_iterate, GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_var_size(client_evaluate, GNUNET_MESSAGE_TYPE_SET_EVALUATE, struct GNUNET_SET_EvaluateMessage, NULL), GNUNET_MQ_hd_fixed_size(client_listen, GNUNET_MESSAGE_TYPE_SET_LISTEN, struct GNUNET_SET_ListenMessage, NULL), GNUNET_MQ_hd_fixed_size(client_reject, GNUNET_MESSAGE_TYPE_SET_REJECT, struct GNUNET_SET_RejectMessage, NULL), GNUNET_MQ_hd_var_size(client_mutation, GNUNET_MESSAGE_TYPE_SET_REMOVE, struct GNUNET_SET_ElementMessage, NULL), GNUNET_MQ_hd_fixed_size(client_cancel, GNUNET_MESSAGE_TYPE_SET_CANCEL, struct GNUNET_SET_CancelMessage, NULL), GNUNET_MQ_hd_fixed_size(client_copy_lazy_prepare, GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_PREPARE, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_fixed_size(client_copy_lazy_connect, GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_CONNECT, struct GNUNET_SET_CopyLazyConnectMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
#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
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_CONNECT
Sent by the client to the server to connect to an existing, lazily copied set.
#define GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
Request a set operation from a remote peer.
struct GNUNET_CADET_Port * GNUNET_CADET_open_port(struct GNUNET_CADET_Handle *h, const struct GNUNET_HashCode *port, GNUNET_CADET_ConnectEventHandler connects, void *connects_cls, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Open a port to receive incomming MQ-based channels.
Definition: cadet_api.c:1007
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC
Compressed strata estimator.
Message sent by the client to the service to ask starting a new set to perform operations with...
Definition: set.h:40
static unsigned int num_clients
Number of active clients.
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.
unsigned int current_generation
Current generation, that is, number of previously executed operations and lazy copies on the underlyi...
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
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.
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:82
Message sent by the client to the service to start listening for incoming requests to perform a certa...
Definition: set.h:58
unsigned int max_op_generation
Largest generation for which an operation is still pending.
struct Listener * listener
Port this operation runs on.
uint8_t force_delta
Always use delta operation instead of sending full sets, even it it&#39;s less efficient.
Definition: set.h:207
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
#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:258
A set that supports a specific operation with other peers.
static void handle_client_copy_lazy_prepare(void *cls, const struct GNUNET_MessageHeader *mh)
Handle a request from the client to copy a set.
static int is_element_of_generation(struct ElementEntry *ee, unsigned int query_generation, struct GenerationRange *excluded, unsigned int excluded_size)
Is element ee part of the set during query_generation?
Randomness for IVs etc.
OpChannelDeathImpl channel_death
Callback called in case the CADET channel died.
static void handle_client_cancel(void *cls, const struct GNUNET_SET_CancelMessage *msg)
Handle a request from the client to cancel a running set operation.
static int in_shutdown
Are we in shutdown? if GNUNET_YES and the number of clients drops to zero, disconnect from CADET...
uint32_t request_id
Id of our set to evaluate, chosen implicitly by the client when it calls GNUNET_SET_commit().
Definition: set.h:201
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE
Set operation is done.
struct Listener * prev
Listeners are held in a doubly linked list.
struct Operation * op_tail
Tail of DLL of operations this listener is responsible for.
#define GNUNET_MESSAGE_TYPE_SET_LISTEN
Listen for operation requests.
uint32_t operation
Operation type, values of enum GNUNET_SET_OperationType
Definition: set.h:49
static void handle_client_iterate(void *cls, const struct GNUNET_MessageHeader *m)
Called when a client wants to iterate the elements of a set.
struct PendingMutation * pending_mutations_tail
Mutations requested by the client that we&#39;re unable to execute right now because we&#39;re iterating over...
static struct GNUNET_CADET_Handle * cadet
Handle to the cadet service, used to listen for and connect to remote peers.
#define GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST
Start iteration over set elements.
A 512-bit hashcode.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2315
struct Operation * op_head
Head of DLL of operations this listener is responsible for.
Message handler for a specific message type.
struct GNUNET_CADET_Port * open_port
The port we are listening on with CADET.
Client connects to a lazily copied set.
Definition: set.h:372
static void incoming_timeout_cb(void *cls)
Timeout happens iff:
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL
Demand the whole element from the other peer, given only the hash code.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
Bloom filter messages exchanged for set intersection calculation.
static GstElement * source
Appsrc instance into which we write data for the pipeline.
int force_delta
Always use delta operation instead of sending full sets, even it it&#39;s less efficient.
struct Listener * listener
Listener, if associated with the client, otherwise NULL.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
static void * channel_new_cb(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *source)
Method called whenever another peer has added us to a channel the other peer initiated.
uint8_t byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
Definition: set.h:219
MutationEvent gives information about changes to an element (removal / addition) in a set content...
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
uint32_t result_mode
How should results be sent to us? See enum GNUNET_SET_ResultMode.
Definition: set.h:100
int byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
uint8_t byzantine_lower_bound
Lower bound for the set size, used only when byzantine mode is enabled.
Definition: set.h:225
#define GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO
Information about the element count for intersection.
static void handle_incoming_msg(void *cls, const struct OperationRequestMessage *msg)
Handle a request for a set operation from another peer.
Sent to the service by the client in order to cancel a set operation.
Definition: set.h:298
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
Strata estimator together with the peer&#39;s overall set size.
Message sent by client to service to initiate a set operation as a client (not as listener)...
Definition: set.h:175
Client acknowledges receiving element in iteration.
Definition: set.h:340
GNUNET_SET_OperationType
The operation that a set set supports.
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.
static void handle_client_reject(void *cls, const struct GNUNET_SET_RejectMessage *msg)
Called when the listening client rejects an operation request by another peer.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF
Invertible bloom filter.
SetContent stores the actual set elements, which may be shared by multiple generations derived from o...
static void channel_end_cb(void *channel_ctx, const struct GNUNET_CADET_Channel *channel)
Function called whenever a channel is destroyed.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
Function called by the service&#39;s run method to run service-specific setup code.
uint32_t accept_reject_id
ID of the incoming request we want to accept.
Definition: set.h:89
struct Listener * next
Listeners are held in a doubly linked list.
#define GNUNET_MESSAGE_TYPE_SET_ITER_ACK
Acknowledge result from iteration.
unsigned int generation
First generation affected by this mutation event.
uint32_t cookie
Temporary name for the copied set.
Definition: set.h:381
struct Set * source_set
Which set are we supposed to copy?
Handle to a message queue.
Definition: mq.c:84
static void handle_client_copy_lazy_connect(void *cls, const struct GNUNET_SET_CopyLazyConnectMessage *msg)
Handle a request from the client to connect to a copy of a set.
static struct LazyCopyRequest * lazy_copy_tail
DLL of lazy copy requests by this client.
static void incoming_destroy(struct Operation *op)
Destroy an incoming request from a remote peer.
struct Operation * next
Kept in a DLL of the listener, if listener is non-NULL.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task, if the incoming peer has not been accepted after the timeout, it will be disconnected...
During intersection, the first (and possibly second) message send it the number of elements in the se...
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
#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
The identity of the host (wraps the signing key of the peer).
uint32_t accept_reject_id
ID of the incoming request we want to reject.
Definition: set.h:141
struct LazyCopyRequest * next
Kept in a DLL.
two-peer set operations
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:951
struct GNUNET_CADET_Channel * GNUNET_CADET_channel_create(struct GNUNET_CADET_Handle *h, void *channel_cls, const struct GNUNET_PeerIdentity *destination, const struct GNUNET_HashCode *port, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Create a new channel towards a remote peer.
Definition: cadet_api.c:1065
struct GNUNET_HashCode app_id
application id
Definition: set.h:72
struct Set * set
Set this mutation is about.
struct GNUNET_MQ_Handle * mq
Message queue for the channel.
#define GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE
Maximum size of a context message for set operation requests.
configuration data
Definition: configuration.c:83
struct GNUNET_HashCode app_id
Application id.
Definition: set.h:195
uint32_t salt
Salt to use for the operation.
struct GNUNET_SERVICE_Client * client
Client this is about.
static void handle_client_accept(void *cls, const struct GNUNET_SET_AcceptMessage *msg)
Handle a request from the client to accept a set operation that came from a remote peer...
uint32_t client_request_id
ID used to identify an operation between service and client.
uint32_t accept_id
ID of the to identify the request when accepting or rejecting it.
Definition: set.h:158
#define GNUNET_MESSAGE_TYPE_SET_REMOVE
Remove element from set.
#define GNUNET_MESSAGE_TYPE_SET_REQUEST
Notify the client of a request from a remote peer.
#define GNUNET_MESSAGE_TYPE_SET_ITER_DONE
Iteration end marker for the client.
struct GNUNET_MessageHeader * context_msg
Context message, may be NULL.
Server responds to a lazy copy request.
Definition: set.h:356
const struct SetVT * _GSS_union_vt(void)
Get the table with implementing functions for set union.
unsigned int end
Generation after the last excluded generation.
static void execute_add(struct Set *set, const struct GNUNET_SET_ElementMessage *msg)
Add an element to set as specified by msg.
uint16_t size
Number of bytes in the buffer pointed to by data.
common components for the implementation the different set operations
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
#define GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE
Intersection operation is done.
two-peer set operations
static struct Operation * get_incoming(uint32_t id)
Get the incoming socket associated with the given id.
Message sent by client to the service to add or remove an element to/from the set.
Definition: set.h:273
int iterator_count
Number of concurrently active iterators.
struct GNUNET_SET_Element element
The actual element.
Opaque handle to a port.
Definition: cadet_api.c:143
uint32_t operation
Operation to request, values from enum GNUNET_SET_OperationType
struct GNUNET_PeerIdentity peer_id
Identity of the requesting peer.
Definition: set.h:163
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 ...
uint8_t byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
Definition: set.h:118
uint32_t cookie
Temporary name for the copied set.
Definition: set.h:365
void _GSS_operation_destroy2(struct Operation *op)
This function probably should not exist and be replaced by inlining more specific logic in the variou...
struct GNUNET_HashCode app_id
Application ID for the operation, used to distinguish multiple operations of the same type with the s...
Header for all communications.
static void handle_client_iter_ack(void *cls, const struct GNUNET_SET_IterAckMessage *ack)
Handle an ack from a client, and send the next element.
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port().
Definition: cadet_api.c:871
#define GNUNET_YES
Definition: gnunet_common.h:77
#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...
Last message, send to confirm the final 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:351
const struct SetVT * vt
Virtual table for this set.
struct ClientState * cs
Client that owns the set.
struct GNUNET_CONTAINER_MultiHashMap * map
Map for which we are garbage collecting removed elements.
Set intersection, only return elements that are in both sets.
static void execute_remove(struct Set *set, const struct GNUNET_SET_ElementMessage *msg)
Remove an element from set as specified by msg.
uint32_t request_id
ID of the request we want to cancel.
Definition: set.h:307
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OVER
Request all missing elements from the other peer, based on their sets and the elements we previously ...
uint32_t remote_element_count
Remote peers element count.
static void collect_generation_garbage(struct Set *set)
Collect and destroy elements that are not needed anymore, because their lifetime (as determined by th...
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
unsigned int start
First generation that is excluded.
static void advance_generation(struct Set *set)
Advance the current generation of a set, adding exclusion ranges if necessary.
struct ClientState * cs
Client that owns the listener.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
unsigned int mutations_size
Number of elements in the array mutations.
Set union, return all elements that are in at least one of the sets.
static struct LazyCopyRequest * lazy_copy_head
DLL of lazy copy requests by this client.
Message sent by a listening client to the service to reject performing the operation with the other p...
Definition: set.h:132
Lazy copy requests made by a client.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY
Tell the other peer to send us a list of hashes that match an IBF key.
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:900
static int destroy_elements_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over hash map entries to free element entries.
struct GNUNET_SET_ElementMessage * msg
Message that describes the desired mutation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
Message sent by a listening client to the service to accept performing the operation with the other p...
Definition: set.h:80
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
Peer-to-Peer messages for gnunet set.
#define GNUNET_malloc(size)
Wrapper around malloc.
Context for the garbage_collect_cb().
uint16_t element_type
Type of the element attachted to the message, if any.
Definition: set.h:331
uint16_t iteration_id
To which set iteration does this reponse belong to? First iteration (per client) has counter zero...
Definition: set.h:325
static struct Listener * listener_head
Listeners are held in a doubly linked list.
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t element_type
Application-specific element type.
uint32_t send_more
Non-zero if the service should continue sending elements.
Definition: set.h:349
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND
Demand the whole element from the other peer, given only the hash code.
struct GNUNET_MessageHeader * GNUNET_copy_message(const struct GNUNET_MessageHeader *msg)
Create a copy of the given message.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
struct SetContent * content
Content, possibly shared by multiple sets, and thus reference counted.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected peer.
Definition: cadet_api.c:1116
int force_full
Always send full sets, even if delta operations would be more efficient.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
unsigned int min_op_generation
Lowest generation for which an operation is still pending.