GNUnet  0.10.x
set_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012-2016 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"
28 #include "gnunet_protocols.h"
29 #include "gnunet_set_service.h"
30 #include "set.h"
31 
32 
33 #define LOG(kind,...) GNUNET_log_from (kind, "set-api",__VA_ARGS__)
34 
36 {
38 
40 
41  void *cls;
42 
44 };
45 
50 {
55 
60 
65 
71 
75  void *iterator_cls;
76 
83 
87  int invalid;
88 
93  uint16_t iteration_id;
94 
99 
104 
109 };
110 
111 
116 {
121  uint32_t accept_id;
122 
127  int accepted;
128 };
129 
130 
136 {
142 
146  void *result_cls;
147 
152  struct GNUNET_SET_Handle *set;
153 
159 
164  uint32_t *request_id_addr;
165 
170 
175 
179  uint32_t request_id;
180 };
181 
182 
187 {
188 
193 
200 
206 
210  void *listen_cls;
211 
216 
220  struct GNUNET_TIME_Relative reconnect_backoff;
221 
226 
230  enum GNUNET_SET_OperationType operation;
231 };
232 
233 
234 /* mutual recursion with handle_copy_lazy */
235 static struct GNUNET_SET_Handle *
238  const uint32_t *cookie);
239 
240 
248 static void
251 {
252  struct GNUNET_SET_Handle *set = cls;
253  struct SetCopyRequest *req;
254  struct GNUNET_SET_Handle *new_set;
255 
256  req = set->copy_req_head;
257  if (NULL == req)
258  {
259  /* Service sent us unsolicited lazy copy response */
260  GNUNET_break (0);
261  return;
262  }
263 
265  "Handling response to lazy copy\n");
266  GNUNET_CONTAINER_DLL_remove (set->copy_req_head,
267  set->copy_req_tail,
268  req);
269  // We pass none as operation here, since it doesn't matter when
270  // cloning.
271  new_set = create_internal (set->cfg,
273  &msg->cookie);
274  req->cb (req->cls, new_set);
275  GNUNET_free (req);
276 }
277 
278 
286 static int
288  const struct GNUNET_SET_IterResponseMessage *msg)
289 {
290  /* minimum size was already checked, everything else is OK! */
291  return GNUNET_OK;
292 }
293 
294 
302 static void
304  const struct GNUNET_SET_IterResponseMessage *msg)
305 {
306  struct GNUNET_SET_Handle *set = cls;
307  GNUNET_SET_ElementIterator iter = set->iterator;
308  struct GNUNET_SET_Element element;
309  struct GNUNET_SET_IterAckMessage *ack_msg;
310  struct GNUNET_MQ_Envelope *ev;
311  uint16_t msize;
312 
314  "Received element in set iteration\n");
315  msize = ntohs (msg->header.size);
316  if (set->iteration_id != ntohs (msg->iteration_id))
317  {
318  /* element from a previous iteration, skip! */
319  iter = NULL;
320  }
321  if (NULL != iter)
322  {
323  element.size = msize - sizeof (struct GNUNET_SET_IterResponseMessage);
324  element.element_type = ntohs (msg->element_type);
325  element.data = &msg[1];
326  iter (set->iterator_cls,
327  &element);
328  }
329  ev = GNUNET_MQ_msg (ack_msg,
331  ack_msg->send_more = htonl ((NULL != iter));
332  GNUNET_MQ_send (set->mq, ev);
333 }
334 
335 
343 static void
345  const struct GNUNET_MessageHeader *mh)
346 {
347  struct GNUNET_SET_Handle *set = cls;
348  GNUNET_SET_ElementIterator iter = set->iterator;
349 
350  if (NULL == iter)
351  {
352  /* FIXME: if this is true, could cancel+start a fresh one
353  cause elements to go to the wrong iteration? */
355  "Service completed set iteration that was already cancelled\n");
356  return;
357  }
359  "Set iteration completed\n");
360  set->destroy_requested = GNUNET_SYSERR;
361  set->iterator = NULL;
362  set->iteration_id++;
363  iter (set->iterator_cls,
364  NULL);
365  if (GNUNET_SYSERR == set->destroy_requested)
366  set->destroy_requested = GNUNET_NO;
367  if (GNUNET_YES == set->destroy_requested)
368  GNUNET_SET_destroy (set);
369 }
370 
371 
379 static int
381  const struct GNUNET_SET_ResultMessage *msg)
382 {
383  /* minimum size was already checked, everything else is OK! */
384  return GNUNET_OK;
385 }
386 
387 
394 static void
396  const struct GNUNET_SET_ResultMessage *msg)
397 {
398  struct GNUNET_SET_Handle *set = cls;
400  struct GNUNET_SET_Element e;
401  enum GNUNET_SET_Status result_status;
402  int destroy_set;
403 
404  GNUNET_assert (NULL != set->mq);
405  result_status = (enum GNUNET_SET_Status) ntohs (msg->result_status);
407  "Got result message with status %d\n",
408  result_status);
409 
410  oh = GNUNET_MQ_assoc_get (set->mq,
411  ntohl (msg->request_id));
412  if (NULL == oh)
413  {
414  /* 'oh' can be NULL if we canceled the operation, but the service
415  did not get the cancel message yet. */
417  "Ignoring result from canceled operation\n");
418  return;
419  }
420 
421  switch (result_status)
422  {
426  goto do_element;
429  goto do_final;
431  /* not used anymore */
432  GNUNET_assert (0);
433  }
434 
435 do_final:
437  "Treating result as final status\n");
438  GNUNET_MQ_assoc_remove (set->mq,
439  ntohl (msg->request_id));
440  GNUNET_CONTAINER_DLL_remove (set->ops_head,
441  set->ops_tail,
442  oh);
443  /* Need to do this calculation _before_ the result callback,
444  as IF the application still has a valid set handle, it
445  may trigger destruction of the set during the callback. */
446  destroy_set = (GNUNET_YES == set->destroy_requested) &&
447  (NULL == set->ops_head);
448  if (NULL != oh->result_cb)
449  {
450  oh->result_cb (oh->result_cls,
451  NULL,
453  result_status);
454  }
455  else
456  {
458  "No callback for final status\n");
459  }
460  if (destroy_set)
461  GNUNET_SET_destroy (set);
462  GNUNET_free (oh);
463  return;
464 
465 do_element:
467  "Treating result as element\n");
468  e.data = &msg[1];
469  e.size = ntohs (msg->header.size) - sizeof (struct GNUNET_SET_ResultMessage);
470  e.element_type = ntohs (msg->element_type);
471  if (NULL != oh->result_cb)
472  oh->result_cb (oh->result_cls,
473  &e,
475  result_status);
476 }
477 
478 
484 static void
486 {
487  struct GNUNET_SET_Handle *set = oh->set;
488  struct GNUNET_SET_OperationHandle *h_assoc;
489 
490  if (NULL != oh->conclude_mqm)
492  /* is the operation already commited? */
493  if (NULL != set)
494  {
496  set->ops_tail,
497  oh);
498  h_assoc = GNUNET_MQ_assoc_remove (set->mq,
499  oh->request_id);
500  GNUNET_assert ( (NULL == h_assoc) ||
501  (h_assoc == oh) );
502  }
503  GNUNET_free (oh);
504 }
505 
506 
514 void
516 {
517  struct GNUNET_SET_Handle *set = oh->set;
518  struct GNUNET_SET_CancelMessage *m;
519  struct GNUNET_MQ_Envelope *mqm;
520 
522  "Cancelling SET operation\n");
523  if (NULL != set)
524  {
526  m->request_id = htonl (oh->request_id);
527  GNUNET_MQ_send (set->mq, mqm);
528  }
530  if ( (NULL != set) &&
531  (GNUNET_YES == set->destroy_requested) &&
532  (NULL == set->ops_head) )
533  {
535  "Destroying set after operation cancel\n");
536  GNUNET_SET_destroy (set);
537  }
538 }
539 
540 
548 static void
550  enum GNUNET_MQ_Error error)
551 {
552  struct GNUNET_SET_Handle *set = cls;
553  GNUNET_SET_ElementIterator iter = set->iterator;
554 
556  "Handling client set error %d\n",
557  error);
558  while (NULL != set->ops_head)
559  {
560  if ( (NULL != set->ops_head->result_cb) &&
561  (GNUNET_NO == set->destroy_requested) )
562  set->ops_head->result_cb (set->ops_head->result_cls,
563  NULL,
564  0,
566  set_operation_destroy (set->ops_head);
567  }
568  set->iterator = NULL;
569  set->iteration_id++;
570  set->invalid = GNUNET_YES;
571  if (NULL != iter)
572  iter (set->iterator_cls,
573  NULL);
574 }
575 
576 
580 static struct GNUNET_SET_Handle *
583  const uint32_t *cookie)
584 {
585  struct GNUNET_SET_Handle *set = GNUNET_new (struct GNUNET_SET_Handle);
586  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
590  set),
591  GNUNET_MQ_hd_var_size (iter_element,
594  set),
595  GNUNET_MQ_hd_fixed_size (iter_done,
597  struct GNUNET_MessageHeader,
598  set),
599  GNUNET_MQ_hd_fixed_size (copy_lazy,
602  set),
604  };
605  struct GNUNET_MQ_Envelope *mqm;
606  struct GNUNET_SET_CreateMessage *create_msg;
607  struct GNUNET_SET_CopyLazyConnectMessage *copy_msg;
608 
609  set->cfg = cfg;
610  set->mq = GNUNET_CLIENT_connect (cfg,
611  "set",
612  mq_handlers,
614  set);
615  if (NULL == set->mq)
616  {
617  GNUNET_free (set);
618  return NULL;
619  }
620  if (NULL == cookie)
621  {
623  "Creating new set (operation %u)\n",
624  op);
625  mqm = GNUNET_MQ_msg (create_msg,
627  create_msg->operation = htonl (op);
628  }
629  else
630  {
632  "Creating new set (lazy copy)\n",
633  op);
634  mqm = GNUNET_MQ_msg (copy_msg,
636  copy_msg->cookie = *cookie;
637  }
638  GNUNET_MQ_send (set->mq,
639  mqm);
640  return set;
641 }
642 
643 
655 struct GNUNET_SET_Handle *
658 {
659  struct GNUNET_SET_Handle *set;
660 
661  set = create_internal (cfg,
662  op,
663  NULL);
665  "Creating set %p for operation %d\n",
666  set,
667  op);
668  return set;
669 }
670 
671 
685 int
687  const struct GNUNET_SET_Element *element,
689  void *cont_cls)
690 {
691  struct GNUNET_MQ_Envelope *mqm;
693 
695  "adding element of type %u to set %p\n",
696  (unsigned int) element->element_type,
697  set);
698  GNUNET_assert (NULL != set);
699  if (GNUNET_YES == set->invalid)
700  {
701  if (NULL != cont)
702  cont (cont_cls);
703  return GNUNET_SYSERR;
704  }
705  mqm = GNUNET_MQ_msg_extra (msg,
706  element->size,
708  msg->element_type = htons (element->element_type);
709  GNUNET_memcpy (&msg[1],
710  element->data,
711  element->size);
713  cont, cont_cls);
714  GNUNET_MQ_send (set->mq, mqm);
715  return GNUNET_OK;
716 }
717 
718 
732 int
734  const struct GNUNET_SET_Element *element,
736  void *cont_cls)
737 {
738  struct GNUNET_MQ_Envelope *mqm;
740 
742  "Removing element from set %p\n",
743  set);
744  if (GNUNET_YES == set->invalid)
745  {
746  if (NULL != cont)
747  cont (cont_cls);
748  return GNUNET_SYSERR;
749  }
750  mqm = GNUNET_MQ_msg_extra (msg,
751  element->size,
753  msg->element_type = htons (element->element_type);
754  GNUNET_memcpy (&msg[1],
755  element->data,
756  element->size);
758  cont, cont_cls);
759  GNUNET_MQ_send (set->mq, mqm);
760  return GNUNET_OK;
761 }
762 
763 
770 void
772 {
773  /* destroying set while iterator is active is currently
774  not supported; we should expand the API to allow
775  clients to explicitly cancel the iteration! */
776  GNUNET_assert (NULL != set);
777  if ( (NULL != set->ops_head) ||
778  (NULL != set->iterator) ||
779  (GNUNET_SYSERR == set->destroy_requested) )
780  {
782  "Set operations are pending, delaying set destruction\n");
783  set->destroy_requested = GNUNET_YES;
784  return;
785  }
787  "Really destroying set\n");
788  if (NULL != set->mq)
789  {
790  GNUNET_MQ_destroy (set->mq);
791  set->mq = NULL;
792  }
793  GNUNET_free (set);
794 }
795 
796 
812 GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
813  const struct GNUNET_HashCode *app_id,
814  const struct GNUNET_MessageHeader *context_msg,
815  enum GNUNET_SET_ResultMode result_mode,
816  struct GNUNET_SET_Option options[],
818  void *result_cls)
819 {
820  struct GNUNET_MQ_Envelope *mqm;
823  struct GNUNET_SET_Option *opt;
824 
826  "Client prepares set operation (%d)\n",
827  result_mode);
829  oh->result_cb = result_cb;
830  oh->result_cls = result_cls;
831  mqm = GNUNET_MQ_msg_nested_mh (msg,
833  context_msg);
834  msg->app_id = *app_id;
835  msg->result_mode = htonl (result_mode);
836  msg->target_peer = *other_peer;
837  for (opt = options; opt->type != 0; opt++)
838  {
839  switch (opt->type)
840  {
842  msg->byzantine = GNUNET_YES;
843  msg->byzantine_lower_bound = opt->v.num;
844  break;
846  msg->force_full = GNUNET_YES;
847  break;
849  msg->force_delta = GNUNET_YES;
850  break;
851  default:
853  "Option with type %d not recognized\n", (int) opt->type);
854  }
855  }
856  oh->conclude_mqm = mqm;
857  oh->request_id_addr = &msg->request_id;
858 
859  return oh;
860 }
861 
862 
868 static void
869 listen_connect (void *cls);
870 
871 
879 static int
881  const struct GNUNET_SET_RequestMessage *msg)
882 {
883  const struct GNUNET_MessageHeader *context_msg;
884 
885  if (ntohs (msg->header.size) == sizeof (*msg))
886  return GNUNET_OK; /* no context message is OK */
887  context_msg = GNUNET_MQ_extract_nested_mh (msg);
888  if (NULL == context_msg)
889  {
890  /* malformed context message is NOT ok */
891  GNUNET_break_op (0);
892  return GNUNET_SYSERR;
893  }
894  return GNUNET_OK;
895 }
896 
897 
904 static void
906  const struct GNUNET_SET_RequestMessage *msg)
907 {
908  struct GNUNET_SET_ListenHandle *lh = cls;
909  struct GNUNET_SET_Request req;
910  const struct GNUNET_MessageHeader *context_msg;
911  struct GNUNET_MQ_Envelope *mqm;
912  struct GNUNET_SET_RejectMessage *rmsg;
913 
915  "Processing incoming operation request with id %u\n",
916  ntohl (msg->accept_id));
917  /* we got another valid request => reset the backoff */
919  req.accept_id = ntohl (msg->accept_id);
920  req.accepted = GNUNET_NO;
921  context_msg = GNUNET_MQ_extract_nested_mh (msg);
922  /* calling #GNUNET_SET_accept() in the listen cb will set req->accepted */
923  lh->listen_cb (lh->listen_cls,
924  &msg->peer_id,
925  context_msg,
926  &req);
927  if (GNUNET_YES == req.accepted)
928  return; /* the accept-case is handled in #GNUNET_SET_accept() */
930  "Rejected request %u\n",
931  ntohl (msg->accept_id));
932  mqm = GNUNET_MQ_msg (rmsg,
934  rmsg->accept_reject_id = msg->accept_id;
935  GNUNET_MQ_send (lh->mq, mqm);
936 }
937 
938 
946 static void
948  enum GNUNET_MQ_Error error)
949 {
950  struct GNUNET_SET_ListenHandle *lh = cls;
951 
953  "Listener broke down (%d), re-connecting\n",
954  (int) error);
955  GNUNET_MQ_destroy (lh->mq);
956  lh->mq = NULL;
959  lh);
961 }
962 
963 
969 static void
971 {
972  struct GNUNET_SET_ListenHandle *lh = cls;
973  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
977  lh),
979  };
980  struct GNUNET_MQ_Envelope *mqm;
982 
983  lh->reconnect_task = NULL;
984  GNUNET_assert (NULL == lh->mq);
985  lh->mq = GNUNET_CLIENT_connect (lh->cfg,
986  "set",
987  mq_handlers,
989  lh);
990  if (NULL == lh->mq)
991  return;
993  msg->operation = htonl (lh->operation);
994  msg->app_id = lh->app_id;
995  GNUNET_MQ_send (lh->mq,
996  mqm);
997 }
998 
999 
1012 struct GNUNET_SET_ListenHandle *
1015  const struct GNUNET_HashCode *app_id,
1017  void *listen_cls)
1018 {
1019  struct GNUNET_SET_ListenHandle *lh;
1020 
1022  "Starting listener for app %s\n",
1023  GNUNET_h2s (app_id));
1024  lh = GNUNET_new (struct GNUNET_SET_ListenHandle);
1025  lh->listen_cb = listen_cb;
1026  lh->listen_cls = listen_cls;
1027  lh->cfg = cfg;
1028  lh->operation = operation;
1029  lh->app_id = *app_id;
1031  listen_connect (lh);
1032  if (NULL == lh->mq)
1033  {
1034  GNUNET_free (lh);
1035  return NULL;
1036  }
1037  return lh;
1038 }
1039 
1040 
1046 void
1048 {
1050  "Canceling listener %s\n",
1051  GNUNET_h2s (&lh->app_id));
1052  if (NULL != lh->mq)
1053  {
1054  GNUNET_MQ_destroy (lh->mq);
1055  lh->mq = NULL;
1056  }
1057  if (NULL != lh->reconnect_task)
1058  {
1060  lh->reconnect_task = NULL;
1061  }
1062  GNUNET_free (lh);
1063 }
1064 
1065 
1082  enum GNUNET_SET_ResultMode result_mode,
1083  struct GNUNET_SET_Option options[],
1085  void *result_cls)
1086 {
1087  struct GNUNET_MQ_Envelope *mqm;
1089  struct GNUNET_SET_AcceptMessage *msg;
1090 
1091  GNUNET_assert (GNUNET_NO == request->accepted);
1093  "Client accepts set operation (%d) with id %u\n",
1094  result_mode,
1095  request->accept_id);
1096  request->accepted = GNUNET_YES;
1097  mqm = GNUNET_MQ_msg (msg,
1099  msg->accept_reject_id = htonl (request->accept_id);
1100  msg->result_mode = htonl (result_mode);
1101  oh = GNUNET_new (struct GNUNET_SET_OperationHandle);
1102  oh->result_cb = result_cb;
1103  oh->result_cls = result_cls;
1104  oh->conclude_mqm = mqm;
1105  oh->request_id_addr = &msg->request_id;
1106  return oh;
1107 }
1108 
1109 
1123 int
1125  struct GNUNET_SET_Handle *set)
1126 {
1127  if (NULL != oh->set)
1128  {
1129  /* Some other set was already committed for this
1130  * operation, there is a logic bug in the client of this API */
1131  GNUNET_break (0);
1132  return GNUNET_OK;
1133  }
1134  GNUNET_assert (NULL != set);
1135  if (GNUNET_YES == set->invalid)
1136  return GNUNET_SYSERR;
1138  "Client commits to SET\n");
1139  GNUNET_assert (NULL != oh->conclude_mqm);
1140  oh->set = set;
1141  GNUNET_CONTAINER_DLL_insert (set->ops_head,
1142  set->ops_tail,
1143  oh);
1144  oh->request_id = GNUNET_MQ_assoc_add (set->mq,
1145  oh);
1146  *oh->request_id_addr = htonl (oh->request_id);
1147  GNUNET_MQ_send (set->mq,
1148  oh->conclude_mqm);
1149  oh->conclude_mqm = NULL;
1150  oh->request_id_addr = NULL;
1151  return GNUNET_OK;
1152 }
1153 
1154 
1167 int
1170  void *iter_cls)
1171 {
1172  struct GNUNET_MQ_Envelope *ev;
1173 
1174  GNUNET_assert (NULL != iter);
1175  if (GNUNET_YES == set->invalid)
1176  return GNUNET_SYSERR;
1177  if (NULL != set->iterator)
1178  return GNUNET_NO;
1180  "Iterating over set\n");
1181  set->iterator = iter;
1182  set->iterator_cls = iter_cls;
1184  GNUNET_MQ_send (set->mq, ev);
1185  return GNUNET_YES;
1186 }
1187 
1188 
1189 void
1192  void *cls)
1193 {
1194  struct GNUNET_MQ_Envelope *ev;
1195  struct SetCopyRequest *req;
1196 
1198  "Creating lazy copy of set\n");
1200  GNUNET_MQ_send (set->mq, ev);
1201 
1202  req = GNUNET_new (struct SetCopyRequest);
1203  req->cb = cb;
1204  req->cls = cls;
1205  GNUNET_CONTAINER_DLL_insert (set->copy_req_head,
1206  set->copy_req_tail,
1207  req);
1208 }
1209 
1210 
1218 struct GNUNET_SET_Element *
1220 {
1221  struct GNUNET_SET_Element *copy;
1222 
1223  copy = GNUNET_malloc (element->size + sizeof (struct GNUNET_SET_Element));
1224  copy->size = element->size;
1225  copy->element_type = element->element_type;
1226  copy->data = &copy[1];
1227  GNUNET_memcpy (&copy[1],
1228  element->data,
1229  copy->size);
1230  return copy;
1231 }
1232 
1233 
1241 void
1243  struct GNUNET_HashCode *ret_hash)
1244 {
1246 
1247  /* It's not guaranteed that the element data is always after the element header,
1248  so we need to hash the chunks separately. */
1249  GNUNET_CRYPTO_hash_context_read (ctx, &element->size, sizeof (uint16_t));
1250  GNUNET_CRYPTO_hash_context_read (ctx, &element->element_type, sizeof (uint16_t));
1251  GNUNET_CRYPTO_hash_context_read (ctx, element->data, element->size);
1252  GNUNET_CRYPTO_hash_context_finish (ctx, ret_hash);
1253 }
1254 
1255 /* end of set_api.c */
struct GNUNET_PeerIdentity target_peer
Peer to evaluate the operation with.
Definition: set.h:198
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static void listen_cb(void *cls)
We have been notified that our listen socket has something to read.
#define GNUNET_MESSAGE_TYPE_SET_CANCEL
Cancel a set operation.
struct GNUNET_SET_Handle * set
Local set used for the operation, NULL if no set has been provided by conclude yet.
Definition: set_api.c:152
struct SetCopyRequest * next
Definition: set_api.c:37
A purely local set that does not support any operation.
struct GNUNET_SET_ListenHandle * GNUNET_SET_listen(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType operation, const struct GNUNET_HashCode *app_id, GNUNET_SET_ListenCallback listen_cb, void *listen_cls)
Wait for set operation requests for the given application id.
Definition: set_api.c:1013
void * result_cls
Closure for result_cb.
Definition: set_api.c:146
int GNUNET_SET_remove_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Remove an element to the given set.
Definition: set_api.c:733
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void handle_iter_element(void *cls, const struct GNUNET_SET_IterResponseMessage *msg)
Handle element for iteration over the set.
Definition: set_api.c:303
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:686
#define GNUNET_MESSAGE_TYPE_SET_ADD
Add element to set.
Handle for a set operation request from another peer.
Definition: set_api.c:115
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:901
void(* GNUNET_SET_ResultIterator)(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
Callback for set operation results.
#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...
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: set_api.c:192
void * iterator_cls
Closure for iterator.
Definition: set_api.c:75
Element should be added to the result set of the remote peer, i.e.
uint32_t GNUNET_MQ_assoc_add(struct GNUNET_MQ_Handle *mq, void *assoc_data)
Associate the assoc_data in mq with a unique request id.
Definition: mq.c:708
#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_RESPONSE
Give the client an ID for connecting to the set&#39;s copy.
Message sent by the service to the client to indicate an element that is removed (set intersection) o...
Definition: set.h:246
messages used for the set api
GNUNET_MQ_Error
Error codes for the queue.
uint32_t request_id
Request ID to identify responses.
Definition: set.h:98
Element stored in a set.
static int check_request(void *cls, const struct GNUNET_SET_RequestMessage *msg)
Check validity of request message for a listen operation.
Definition: set_api.c:880
static void handle_request(void *cls, const struct GNUNET_SET_RequestMessage *msg)
Handle request message for a listen operation.
Definition: set_api.c:905
struct GNUNET_SET_Handle * GNUNET_SET_create(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op)
Create an empty set, supporting the specified operation.
Definition: set_api.c:656
#define GNUNET_MQ_extract_nested_mh(var)
Return a pointer to the message at the end of the given message.
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 struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
Do not use the optimized set operation, but send full sets.
void * listen_cls
Closure for listen_cb.
Definition: set_api.c:210
struct GNUNET_SET_OperationHandle * ops_tail
Linked list of operations on the set.
Definition: set_api.c:64
#define GNUNET_MESSAGE_TYPE_SET_EVALUATE
Evaluate a set operation.
void(* GNUNET_SET_CopyReadyCallback)(void *cls, struct GNUNET_SET_Handle *copy)
#define GNUNET_MESSAGE_TYPE_SET_RESULT
Create an empty set.
A request for an operation with another client.
Definition: set.h:154
#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_PREPARE
Ask the set service to prepare a copy of a set.
struct SetCopyRequest * prev
Definition: set_api.c:39
uint32_t request_id
id the result belongs to
Definition: set.h:261
#define GNUNET_MESSAGE_TYPE_SET_ACCEPT
Accept a set request.
struct SetCopyRequest * copy_req_head
Doubly linked list of copy requests.
Definition: set_api.c:103
#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:81
GNUNET_SET_ListenCallback listen_cb
Function to call on a new incoming request, or on error.
Definition: set_api.c:205
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
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:446
Set element transmitted by service to client in response to a set iteration request.
Definition: set.h:326
static struct GNUNET_HashCode app_id
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_SET_OperationHandle * GNUNET_SET_prepare(const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Prepare a set operation to be evaluated with another peer.
Definition: set_api.c:812
Context for cummulative hashing.
Definition: crypto_hash.c:431
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static void handle_result(void *cls, const struct GNUNET_SET_ResultMessage *msg)
Handle result message for a set operation.
Definition: set_api.c:395
void(* GNUNET_SET_Continuation)(void *cls)
Continuation used for some of the set operations.
uint32_t result_mode
How should results be sent to us? See enum GNUNET_SET_ResultMode.
Definition: set.h:193
uint16_t iteration_id
Both client and service count the number of iterators created so far to match replies with iterators...
Definition: set_api.c:93
void * cls
Definition: set_api.c:41
uint32_t request_id
Request ID to identify the operation within the set.
Definition: set_api.c:179
void GNUNET_SET_copy_lazy(struct GNUNET_SET_Handle *set, GNUNET_SET_CopyReadyCallback cb, void *cls)
Definition: set_api.c:1190
uint8_t force_full
Always send full sets, even if delta operations would be more efficient.
Definition: set.h:221
Success, all elements have been sent (and received).
int(* GNUNET_SET_ElementIterator)(void *cls, const struct GNUNET_SET_Element *element)
Iterator for set elements.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static void handle_copy_lazy(void *cls, const struct GNUNET_SET_CopyLazyResponseMessage *msg)
Handle element for iteration over the set.
Definition: set_api.c:249
#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:1242
#define GNUNET_MESSAGE_TYPE_SET_REJECT
Reject a set request.
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.
enum GNUNET_SET_OptionType type
Type of the option.
uint32_t operation
Operation type, values of enum GNUNET_SET_OperationType
Definition: set.h:69
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle if no operations are left, mark the set for destruction otherwise.
Definition: set_api.c:771
uint64_t current_size
Current set size.
Definition: set.h:256
#define LOG(kind,...)
Definition: set_api.c:33
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
int accepted
Has the request been accepted already? GNUNET_YES/GNUNET_NO.
Definition: set_api.c:127
struct GNUNET_MQ_Handle * mq
Message queue for client.
Definition: set_api.c:54
#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
int invalid
Has the set become invalid (e.g.
Definition: set_api.c:87
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:1246
#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_CONNECT
Sent by the client to the server to connect to an existing, lazily copied set.
GNUNET_SET_ResultIterator result_cb
Function to be called when we have a result, or an error.
Definition: set_api.c:141
Only use optimized set operations, even though for this particular set operation they might be much s...
#define GNUNET_memcpy(dst, src, n)
Message sent by the client to the service to ask starting a new set to perform operations with...
Definition: set.h:40
static void handle_iter_done(void *cls, const struct GNUNET_MessageHeader *mh)
Handle message signalling conclusion of iteration over the set.
Definition: set_api.c:344
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore...
Definition: mq.c:774
The other peer refused to to the operation with us, or something went wrong.
Success, all elements have been returned (but the other peer might still be receiving some from us...
static struct GNUNET_TRANSPORT_OfferHelloHandle * oh
Active HELLO offering to transport service.
#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.
Everything went ok, we are transmitting an element of the result (in set, or to be removed from set...
Message sent by the client to the service to start listening for incoming requests to perform a certa...
Definition: set.h:59
struct GNUNET_TIME_Relative reconnect_backoff
Time to wait until we try to reconnect on failure.
Definition: set_api.c:220
GNUNET_SET_Status
Status for the result callback.
uint8_t force_delta
Always use delta operation instead of sending full sets, even it it&#39;s less efficient.
Definition: set.h:215
uint16_t result_status
Was the evaluation successful? Contains an enum GNUNET_SET_Status in NBO.
Definition: set.h:267
GNUNET_SET_ResultMode
The way results are given to the client.
uint32_t request_id
Id of our set to evaluate, chosen implicitly by the client when it calls GNUNET_SET_commit().
Definition: set.h:209
static int result
Global testing status.
static void listen_connect(void *cls)
Connect to the set service in order to listen for requests.
Definition: set_api.c:970
#define GNUNET_MESSAGE_TYPE_SET_LISTEN
Listen for operation requests.
uint32_t operation
Operation type, values of enum GNUNET_SET_OperationType
Definition: set.h:50
GNUNET_SET_CopyReadyCallback cb
Definition: set_api.c:43
int destroy_requested
Should the set be destroyed once all operations are gone? GNUNET_SYSERR if GNUNET_SET_destroy() must ...
Definition: set_api.c:82
#define GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST
Start iteration over set elements.
A 512-bit hashcode.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
Message handler for a specific message type.
Client connects to a lazily copied set.
Definition: set.h:386
Opaque handle to a set.
Definition: set_api.c:49
uint32_t * request_id_addr
Address of the request if in the conclude message, used to patch the request id into the message when...
Definition: set_api.c:164
uint32_t accept_id
Id of the request, used to identify the request when accepting/rejecting it.
Definition: set_api.c:121
struct GNUNET_HashCode app_id
Application ID we listen for.
Definition: set_api.c:215
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:321
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
static int check_iter_element(void *cls, const struct GNUNET_SET_IterResponseMessage *msg)
Check that the given msg is well-formed.
Definition: set_api.c:287
uint16_t element_type
Type of the element attachted to the message, if any.
Definition: set.h:272
uint8_t byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
Definition: set.h:227
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
uint32_t result_mode
How should results be sent to us? See enum GNUNET_SET_ResultMode.
Definition: set.h:104
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
Definition: crypto_hash.c:472
uint8_t byzantine_lower_bound
Lower bound for the set size, used only when byzantine mode is enabled.
Definition: set.h:233
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_REQUEST.
Definition: set.h:159
Sent to the service by the client in order to cancel a set operation.
Definition: set.h:308
void GNUNET_SET_listen_cancel(struct GNUNET_SET_ListenHandle *lh)
Cancel the given listen operation.
Definition: set_api.c:1047
Message sent by client to service to initiate a set operation as a client (not as listener)...
Definition: set.h:182
Client acknowledges receiving element in iteration.
Definition: set.h:352
GNUNET_SET_ElementIterator iterator
Callback for the current iteration over the set, NULL if no iterator is active.
Definition: set_api.c:70
GNUNET_SET_OperationType
The operation that a set set supports.
Option for set operations.
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
struct GNUNET_SET_OperationHandle * prev
Handles are kept in a linked list.
Definition: set_api.c:169
static int check_result(void *cls, const struct GNUNET_SET_ResultMessage *msg)
Check that the given msg is well-formed.
Definition: set_api.c:380
uint32_t accept_reject_id
ID of the incoming request we want to accept.
Definition: set.h:93
struct SetCopyRequest * copy_req_tail
Doubly linked list of copy requests.
Definition: set_api.c:108
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_RESULT.
Definition: set.h:251
#define GNUNET_MESSAGE_TYPE_SET_ITER_ACK
Acknowledge result from iteration.
uint32_t cookie
Temporary name for the copied set.
Definition: set.h:396
Handle to an operation.
Definition: set_api.c:135
Handle to a message queue.
Definition: mq.c:85
struct GNUNET_SET_OperationHandle * ops_head
Linked list of operations on the set.
Definition: set_api.c:59
#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).
int GNUNET_SET_commit(struct GNUNET_SET_OperationHandle *oh, struct GNUNET_SET_Handle *set)
Commit a set to be used with a set operation.
Definition: set_api.c:1124
uint32_t accept_reject_id
ID of the incoming request we want to reject.
Definition: set.h:146
static void set_operation_destroy(struct GNUNET_SET_OperationHandle *oh)
Destroy the given set operation.
Definition: set_api.c:485
struct GNUNET_HashCode app_id
application id
Definition: set.h:74
enum GNUNET_SET_OperationType operation
Operation we listen for.
Definition: set_api.c:230
struct GNUNET_MQ_Envelope * conclude_mqm
Message sent to the server on calling conclude, NULL if conclude has been called. ...
Definition: set_api.c:158
configuration data
Definition: configuration.c:85
struct GNUNET_HashCode app_id
Application id.
Definition: set.h:203
uint32_t accept_id
ID of the to identify the request when accepting or rejecting it.
Definition: set.h:165
#define GNUNET_MESSAGE_TYPE_SET_REMOVE
Remove element from set.
void * GNUNET_MQ_assoc_remove(struct GNUNET_MQ_Handle *mq, uint32_t request_id)
Remove the association for a request_id.
Definition: mq.c:752
#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.
Server responds to a lazy copy request.
Definition: set.h:369
uint16_t size
Number of bytes in the buffer pointed to by data.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
Message sent by client to the service to add or remove an element to/from the set.
Definition: set.h:282
struct GNUNET_SET_OperationHandle * next
Handles are kept in a linked list.
Definition: set_api.c:174
Opaque handle to a listen operation.
Definition: set_api.c:186
struct GNUNET_PeerIdentity peer_id
Identity of the requesting peer.
Definition: set.h:170
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:515
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1219
uint32_t cookie
Temporary name for the copied set.
Definition: set.h:379
Header for all communications.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
#define GNUNET_YES
Definition: gnunet_common.h:80
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
static struct GNUNET_SET_Handle * create_internal(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op, const uint32_t *cookie)
FIXME.
Definition: set_api.c:581
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT.
Definition: set.h:331
uint32_t request_id
ID of the request we want to cancel.
Definition: set.h:318
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
int GNUNET_SET_iterate(struct GNUNET_SET_Handle *set, GNUNET_SET_ElementIterator iter, void *iter_cls)
Iterate over all elements in the given set.
Definition: set_api.c:1168
static void handle_client_listener_error(void *cls, enum GNUNET_MQ_Error error)
Our connection with the set service encountered an error, re-initialize with exponential back-off...
Definition: set_api.c:947
Message sent by a listening client to the service to reject performing the operation with the other p...
Definition: set.h:136
static void handle_client_set_error(void *cls, enum GNUNET_MQ_Error error)
We encountered an error communicating with the set service while performing a set operation...
Definition: set_api.c:549
Message sent by a listening client to the service to accept performing the operation with the other p...
Definition: set.h:83
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration, needed when creating (lazy) copies.
Definition: set_api.c:98
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:489
#define GNUNET_malloc(size)
Wrapper around malloc.
uint16_t element_type
Type of the element attachted to the message, if any.
Definition: set.h:343
void(* GNUNET_SET_ListenCallback)(void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request)
Called when another peer wants to do a set operation with the local peer.
uint16_t iteration_id
To which set iteration does this reponse belong to? First iteration (per client) has counter zero...
Definition: set.h:337
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
struct GNUNET_SCHEDULER_Task * reconnect_task
Task for reconnecting when the listener fails.
Definition: set_api.c:225
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint16_t element_type
Application-specific element type.
uint32_t send_more
Non-zero if the service should continue sending elements.
Definition: set.h:362
struct GNUNET_SET_OperationHandle * GNUNET_SET_accept(struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SET_listen.
Definition: set_api.c:1081
void * GNUNET_MQ_assoc_get(struct GNUNET_MQ_Handle *mq, uint32_t request_id)
Get the data associated with a request_id in a queue.
Definition: mq.c:736
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault...
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration handle for the listener, stored here to be able to reconnect transparently on connectio...
Definition: set_api.c:199
union GNUNET_SET_Option::@57 v
Value for the option, only used with some options.