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 
37 
39 
40  void *cls;
41 
43 };
44 
53 
58 
63 
69 
73  void *iterator_cls;
74 
81 
85  int invalid;
86 
91  uint16_t iteration_id;
92 
97 
102 
107 };
108 
109 
118  uint32_t accept_id;
119 
124  int accepted;
125 };
126 
127 
138 
142  void *result_cls;
143 
148  struct GNUNET_SET_Handle *set;
149 
155 
160  uint32_t *request_id_addr;
161 
166 
171 
175  uint32_t request_id;
176 };
177 
178 
187 
194 
200 
204  void *listen_cls;
205 
210 
214  struct GNUNET_TIME_Relative reconnect_backoff;
215 
220 
224  enum GNUNET_SET_OperationType operation;
225 };
226 
227 
228 /* mutual recursion with handle_copy_lazy */
229 static struct GNUNET_SET_Handle *
232  const uint32_t *cookie);
233 
234 
242 static void
245 {
246  struct GNUNET_SET_Handle *set = cls;
247  struct SetCopyRequest *req;
248  struct GNUNET_SET_Handle *new_set;
249 
250  req = set->copy_req_head;
251  if (NULL == req)
252  {
253  /* Service sent us unsolicited lazy copy response */
254  GNUNET_break(0);
255  return;
256  }
257 
259  "Handling response to lazy copy\n");
260  GNUNET_CONTAINER_DLL_remove(set->copy_req_head,
261  set->copy_req_tail,
262  req);
263  // We pass none as operation here, since it doesn't matter when
264  // cloning.
265  new_set = create_internal(set->cfg,
267  &msg->cookie);
268  req->cb(req->cls, new_set);
269  GNUNET_free(req);
270 }
271 
272 
280 static int
282  const struct GNUNET_SET_IterResponseMessage *msg)
283 {
284  /* minimum size was already checked, everything else is OK! */
285  return GNUNET_OK;
286 }
287 
288 
296 static void
298  const struct GNUNET_SET_IterResponseMessage *msg)
299 {
300  struct GNUNET_SET_Handle *set = cls;
301  GNUNET_SET_ElementIterator iter = set->iterator;
302  struct GNUNET_SET_Element element;
303  struct GNUNET_SET_IterAckMessage *ack_msg;
304  struct GNUNET_MQ_Envelope *ev;
305  uint16_t msize;
306 
308  "Received element in set iteration\n");
309  msize = ntohs(msg->header.size);
310  if (set->iteration_id != ntohs(msg->iteration_id))
311  {
312  /* element from a previous iteration, skip! */
313  iter = NULL;
314  }
315  if (NULL != iter)
316  {
317  element.size = msize - sizeof(struct GNUNET_SET_IterResponseMessage);
318  element.element_type = ntohs(msg->element_type);
319  element.data = &msg[1];
320  iter(set->iterator_cls,
321  &element);
322  }
323  ev = GNUNET_MQ_msg(ack_msg,
325  ack_msg->send_more = htonl((NULL != iter));
326  GNUNET_MQ_send(set->mq, ev);
327 }
328 
329 
337 static void
339  const struct GNUNET_MessageHeader *mh)
340 {
341  struct GNUNET_SET_Handle *set = cls;
342  GNUNET_SET_ElementIterator iter = set->iterator;
343 
344  if (NULL == iter)
345  {
346  /* FIXME: if this is true, could cancel+start a fresh one
347  cause elements to go to the wrong iteration? */
349  "Service completed set iteration that was already cancelled\n");
350  return;
351  }
353  "Set iteration completed\n");
354  set->destroy_requested = GNUNET_SYSERR;
355  set->iterator = NULL;
356  set->iteration_id++;
357  iter(set->iterator_cls,
358  NULL);
359  if (GNUNET_SYSERR == set->destroy_requested)
360  set->destroy_requested = GNUNET_NO;
361  if (GNUNET_YES == set->destroy_requested)
362  GNUNET_SET_destroy(set);
363 }
364 
365 
373 static int
375  const struct GNUNET_SET_ResultMessage *msg)
376 {
377  /* minimum size was already checked, everything else is OK! */
378  return GNUNET_OK;
379 }
380 
381 
388 static void
390  const struct GNUNET_SET_ResultMessage *msg)
391 {
392  struct GNUNET_SET_Handle *set = cls;
394  struct GNUNET_SET_Element e;
395  enum GNUNET_SET_Status result_status;
396  int destroy_set;
397 
398  GNUNET_assert(NULL != set->mq);
399  result_status = (enum GNUNET_SET_Status)ntohs(msg->result_status);
401  "Got result message with status %d\n",
402  result_status);
403 
404  oh = GNUNET_MQ_assoc_get(set->mq,
405  ntohl(msg->request_id));
406  if (NULL == oh)
407  {
408  /* 'oh' can be NULL if we canceled the operation, but the service
409  did not get the cancel message yet. */
411  "Ignoring result from canceled operation\n");
412  return;
413  }
414 
415  switch (result_status)
416  {
420  goto do_element;
421 
424  goto do_final;
425 
427  /* not used anymore */
428  GNUNET_assert(0);
429  }
430 
431 do_final:
433  "Treating result as final status\n");
434  GNUNET_MQ_assoc_remove(set->mq,
435  ntohl(msg->request_id));
436  GNUNET_CONTAINER_DLL_remove(set->ops_head,
437  set->ops_tail,
438  oh);
439  /* Need to do this calculation _before_ the result callback,
440  as IF the application still has a valid set handle, it
441  may trigger destruction of the set during the callback. */
442  destroy_set = (GNUNET_YES == set->destroy_requested) &&
443  (NULL == set->ops_head);
444  if (NULL != oh->result_cb)
445  {
446  oh->result_cb(oh->result_cls,
447  NULL,
449  result_status);
450  }
451  else
452  {
454  "No callback for final status\n");
455  }
456  if (destroy_set)
457  GNUNET_SET_destroy(set);
458  GNUNET_free(oh);
459  return;
460 
461 do_element:
463  "Treating result as element\n");
464  e.data = &msg[1];
465  e.size = ntohs(msg->header.size) - sizeof(struct GNUNET_SET_ResultMessage);
466  e.element_type = ntohs(msg->element_type);
467  if (NULL != oh->result_cb)
468  oh->result_cb(oh->result_cls,
469  &e,
471  result_status);
472 }
473 
474 
480 static void
482 {
483  struct GNUNET_SET_Handle *set = oh->set;
484  struct GNUNET_SET_OperationHandle *h_assoc;
485 
486  if (NULL != oh->conclude_mqm)
488  /* is the operation already commited? */
489  if (NULL != set)
490  {
492  set->ops_tail,
493  oh);
494  h_assoc = GNUNET_MQ_assoc_remove(set->mq,
495  oh->request_id);
496  GNUNET_assert((NULL == h_assoc) ||
497  (h_assoc == oh));
498  }
499  GNUNET_free(oh);
500 }
501 
502 
510 void
512 {
513  struct GNUNET_SET_Handle *set = oh->set;
514  struct GNUNET_SET_CancelMessage *m;
515  struct GNUNET_MQ_Envelope *mqm;
516 
518  "Cancelling SET operation\n");
519  if (NULL != set)
520  {
522  m->request_id = htonl(oh->request_id);
523  GNUNET_MQ_send(set->mq, mqm);
524  }
526  if ((NULL != set) &&
527  (GNUNET_YES == set->destroy_requested) &&
528  (NULL == set->ops_head))
529  {
531  "Destroying set after operation cancel\n");
532  GNUNET_SET_destroy(set);
533  }
534 }
535 
536 
544 static void
546  enum GNUNET_MQ_Error error)
547 {
548  struct GNUNET_SET_Handle *set = cls;
549  GNUNET_SET_ElementIterator iter = set->iterator;
550 
552  "Handling client set error %d\n",
553  error);
554  while (NULL != set->ops_head)
555  {
556  if ((NULL != set->ops_head->result_cb) &&
557  (GNUNET_NO == set->destroy_requested))
558  set->ops_head->result_cb(set->ops_head->result_cls,
559  NULL,
560  0,
562  set_operation_destroy(set->ops_head);
563  }
564  set->iterator = NULL;
565  set->iteration_id++;
566  set->invalid = GNUNET_YES;
567  if (NULL != iter)
568  iter(set->iterator_cls,
569  NULL);
570 }
571 
572 
576 static struct GNUNET_SET_Handle *
579  const uint32_t *cookie)
580 {
581  struct GNUNET_SET_Handle *set = GNUNET_new(struct GNUNET_SET_Handle);
582  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
586  set),
587  GNUNET_MQ_hd_var_size(iter_element,
590  set),
591  GNUNET_MQ_hd_fixed_size(iter_done,
593  struct GNUNET_MessageHeader,
594  set),
595  GNUNET_MQ_hd_fixed_size(copy_lazy,
598  set),
600  };
601  struct GNUNET_MQ_Envelope *mqm;
602  struct GNUNET_SET_CreateMessage *create_msg;
603  struct GNUNET_SET_CopyLazyConnectMessage *copy_msg;
604 
605  set->cfg = cfg;
606  set->mq = GNUNET_CLIENT_connect(cfg,
607  "set",
608  mq_handlers,
610  set);
611  if (NULL == set->mq)
612  {
613  GNUNET_free(set);
614  return NULL;
615  }
616  if (NULL == cookie)
617  {
619  "Creating new set (operation %u)\n",
620  op);
621  mqm = GNUNET_MQ_msg(create_msg,
623  create_msg->operation = htonl(op);
624  }
625  else
626  {
628  "Creating new set (lazy copy)\n",
629  op);
630  mqm = GNUNET_MQ_msg(copy_msg,
632  copy_msg->cookie = *cookie;
633  }
634  GNUNET_MQ_send(set->mq,
635  mqm);
636  return set;
637 }
638 
639 
651 struct GNUNET_SET_Handle *
654 {
655  struct GNUNET_SET_Handle *set;
656 
657  set = create_internal(cfg,
658  op,
659  NULL);
661  "Creating set %p for operation %d\n",
662  set,
663  op);
664  return set;
665 }
666 
667 
681 int
683  const struct GNUNET_SET_Element *element,
685  void *cont_cls)
686 {
687  struct GNUNET_MQ_Envelope *mqm;
689 
691  "adding element of type %u to set %p\n",
692  (unsigned int)element->element_type,
693  set);
694  GNUNET_assert(NULL != set);
695  if (GNUNET_YES == set->invalid)
696  {
697  if (NULL != cont)
698  cont(cont_cls);
699  return GNUNET_SYSERR;
700  }
701  mqm = GNUNET_MQ_msg_extra(msg,
702  element->size,
704  msg->element_type = htons(element->element_type);
705  GNUNET_memcpy(&msg[1],
706  element->data,
707  element->size);
709  cont, cont_cls);
710  GNUNET_MQ_send(set->mq, mqm);
711  return GNUNET_OK;
712 }
713 
714 
728 int
730  const struct GNUNET_SET_Element *element,
732  void *cont_cls)
733 {
734  struct GNUNET_MQ_Envelope *mqm;
736 
738  "Removing element from set %p\n",
739  set);
740  if (GNUNET_YES == set->invalid)
741  {
742  if (NULL != cont)
743  cont(cont_cls);
744  return GNUNET_SYSERR;
745  }
746  mqm = GNUNET_MQ_msg_extra(msg,
747  element->size,
749  msg->element_type = htons(element->element_type);
750  GNUNET_memcpy(&msg[1],
751  element->data,
752  element->size);
754  cont, cont_cls);
755  GNUNET_MQ_send(set->mq, mqm);
756  return GNUNET_OK;
757 }
758 
759 
766 void
768 {
769  /* destroying set while iterator is active is currently
770  not supported; we should expand the API to allow
771  clients to explicitly cancel the iteration! */
772  GNUNET_assert(NULL != set);
773  if ((NULL != set->ops_head) ||
774  (NULL != set->iterator) ||
775  (GNUNET_SYSERR == set->destroy_requested))
776  {
778  "Set operations are pending, delaying set destruction\n");
779  set->destroy_requested = GNUNET_YES;
780  return;
781  }
783  "Really destroying set\n");
784  if (NULL != set->mq)
785  {
786  GNUNET_MQ_destroy(set->mq);
787  set->mq = NULL;
788  }
789  GNUNET_free(set);
790 }
791 
792 
808 GNUNET_SET_prepare(const struct GNUNET_PeerIdentity *other_peer,
809  const struct GNUNET_HashCode *app_id,
810  const struct GNUNET_MessageHeader *context_msg,
811  enum GNUNET_SET_ResultMode result_mode,
812  struct GNUNET_SET_Option options[],
814  void *result_cls)
815 {
816  struct GNUNET_MQ_Envelope *mqm;
819  struct GNUNET_SET_Option *opt;
820 
822  "Client prepares set operation (%d)\n",
823  result_mode);
825  oh->result_cb = result_cb;
826  oh->result_cls = result_cls;
827  mqm = GNUNET_MQ_msg_nested_mh(msg,
829  context_msg);
830  msg->app_id = *app_id;
831  msg->result_mode = htonl(result_mode);
832  msg->target_peer = *other_peer;
833  for (opt = options; opt->type != 0; opt++)
834  {
835  switch (opt->type)
836  {
838  msg->byzantine = GNUNET_YES;
839  msg->byzantine_lower_bound = opt->v.num;
840  break;
841 
843  msg->force_full = GNUNET_YES;
844  break;
845 
847  msg->force_delta = GNUNET_YES;
848  break;
849 
850  default:
852  "Option with type %d not recognized\n", (int)opt->type);
853  }
854  }
855  oh->conclude_mqm = mqm;
856  oh->request_id_addr = &msg->request_id;
857 
858  return oh;
859 }
860 
861 
867 static void
868 listen_connect(void *cls);
869 
870 
878 static int
880  const struct GNUNET_SET_RequestMessage *msg)
881 {
882  const struct GNUNET_MessageHeader *context_msg;
883 
884  if (ntohs(msg->header.size) == sizeof(*msg))
885  return GNUNET_OK; /* no context message is OK */
886  context_msg = GNUNET_MQ_extract_nested_mh(msg);
887  if (NULL == context_msg)
888  {
889  /* malformed context message is NOT ok */
890  GNUNET_break_op(0);
891  return GNUNET_SYSERR;
892  }
893  return GNUNET_OK;
894 }
895 
896 
903 static void
905  const struct GNUNET_SET_RequestMessage *msg)
906 {
907  struct GNUNET_SET_ListenHandle *lh = cls;
908  struct GNUNET_SET_Request req;
909  const struct GNUNET_MessageHeader *context_msg;
910  struct GNUNET_MQ_Envelope *mqm;
911  struct GNUNET_SET_RejectMessage *rmsg;
912 
914  "Processing incoming operation request with id %u\n",
915  ntohl(msg->accept_id));
916  /* we got another valid request => reset the backoff */
918  req.accept_id = ntohl(msg->accept_id);
919  req.accepted = GNUNET_NO;
920  context_msg = GNUNET_MQ_extract_nested_mh(msg);
921  /* calling #GNUNET_SET_accept() in the listen cb will set req->accepted */
922  lh->listen_cb(lh->listen_cls,
923  &msg->peer_id,
924  context_msg,
925  &req);
926  if (GNUNET_YES == req.accepted)
927  return; /* the accept-case is handled in #GNUNET_SET_accept() */
929  "Rejected request %u\n",
930  ntohl(msg->accept_id));
931  mqm = GNUNET_MQ_msg(rmsg,
933  rmsg->accept_reject_id = msg->accept_id;
934  GNUNET_MQ_send(lh->mq, mqm);
935 }
936 
937 
945 static void
947  enum GNUNET_MQ_Error error)
948 {
949  struct GNUNET_SET_ListenHandle *lh = cls;
950 
952  "Listener broke down (%d), re-connecting\n",
953  (int)error);
954  GNUNET_MQ_destroy(lh->mq);
955  lh->mq = NULL;
958  lh);
960 }
961 
962 
968 static void
970 {
971  struct GNUNET_SET_ListenHandle *lh = cls;
972  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
976  lh),
978  };
979  struct GNUNET_MQ_Envelope *mqm;
981 
982  lh->reconnect_task = NULL;
983  GNUNET_assert(NULL == lh->mq);
984  lh->mq = GNUNET_CLIENT_connect(lh->cfg,
985  "set",
986  mq_handlers,
988  lh);
989  if (NULL == lh->mq)
990  return;
992  msg->operation = htonl(lh->operation);
993  msg->app_id = lh->app_id;
994  GNUNET_MQ_send(lh->mq,
995  mqm);
996 }
997 
998 
1011 struct GNUNET_SET_ListenHandle *
1014  const struct GNUNET_HashCode *app_id,
1016  void *listen_cls)
1017 {
1018  struct GNUNET_SET_ListenHandle *lh;
1019 
1021  "Starting listener for app %s\n",
1022  GNUNET_h2s(app_id));
1023  lh = GNUNET_new(struct GNUNET_SET_ListenHandle);
1024  lh->listen_cb = listen_cb;
1025  lh->listen_cls = listen_cls;
1026  lh->cfg = cfg;
1027  lh->operation = operation;
1028  lh->app_id = *app_id;
1030  listen_connect(lh);
1031  if (NULL == lh->mq)
1032  {
1033  GNUNET_free(lh);
1034  return NULL;
1035  }
1036  return lh;
1037 }
1038 
1039 
1045 void
1047 {
1049  "Canceling listener %s\n",
1050  GNUNET_h2s(&lh->app_id));
1051  if (NULL != lh->mq)
1052  {
1053  GNUNET_MQ_destroy(lh->mq);
1054  lh->mq = NULL;
1055  }
1056  if (NULL != lh->reconnect_task)
1057  {
1059  lh->reconnect_task = NULL;
1060  }
1061  GNUNET_free(lh);
1062 }
1063 
1064 
1081  enum GNUNET_SET_ResultMode result_mode,
1082  struct GNUNET_SET_Option options[],
1084  void *result_cls)
1085 {
1086  struct GNUNET_MQ_Envelope *mqm;
1088  struct GNUNET_SET_AcceptMessage *msg;
1089 
1090  GNUNET_assert(GNUNET_NO == request->accepted);
1092  "Client accepts set operation (%d) with id %u\n",
1093  result_mode,
1094  request->accept_id);
1095  request->accepted = GNUNET_YES;
1096  mqm = GNUNET_MQ_msg(msg,
1098  msg->accept_reject_id = htonl(request->accept_id);
1099  msg->result_mode = htonl(result_mode);
1101  oh->result_cb = result_cb;
1102  oh->result_cls = result_cls;
1103  oh->conclude_mqm = mqm;
1104  oh->request_id_addr = &msg->request_id;
1105  return oh;
1106 }
1107 
1108 
1122 int
1124  struct GNUNET_SET_Handle *set)
1125 {
1126  if (NULL != oh->set)
1127  {
1128  /* Some other set was already committed for this
1129  * operation, there is a logic bug in the client of this API */
1130  GNUNET_break(0);
1131  return GNUNET_OK;
1132  }
1133  GNUNET_assert(NULL != set);
1134  if (GNUNET_YES == set->invalid)
1135  return GNUNET_SYSERR;
1137  "Client commits to SET\n");
1138  GNUNET_assert(NULL != oh->conclude_mqm);
1139  oh->set = set;
1140  GNUNET_CONTAINER_DLL_insert(set->ops_head,
1141  set->ops_tail,
1142  oh);
1143  oh->request_id = GNUNET_MQ_assoc_add(set->mq,
1144  oh);
1145  *oh->request_id_addr = htonl(oh->request_id);
1146  GNUNET_MQ_send(set->mq,
1147  oh->conclude_mqm);
1148  oh->conclude_mqm = NULL;
1149  oh->request_id_addr = NULL;
1150  return GNUNET_OK;
1151 }
1152 
1153 
1166 int
1169  void *iter_cls)
1170 {
1171  struct GNUNET_MQ_Envelope *ev;
1172 
1173  GNUNET_assert(NULL != iter);
1174  if (GNUNET_YES == set->invalid)
1175  return GNUNET_SYSERR;
1176  if (NULL != set->iterator)
1177  return GNUNET_NO;
1179  "Iterating over set\n");
1180  set->iterator = iter;
1181  set->iterator_cls = iter_cls;
1183  GNUNET_MQ_send(set->mq, ev);
1184  return GNUNET_YES;
1185 }
1186 
1187 
1188 void
1191  void *cls)
1192 {
1193  struct GNUNET_MQ_Envelope *ev;
1194  struct SetCopyRequest *req;
1195 
1197  "Creating lazy copy of set\n");
1199  GNUNET_MQ_send(set->mq, ev);
1200 
1201  req = GNUNET_new(struct SetCopyRequest);
1202  req->cb = cb;
1203  req->cls = cls;
1204  GNUNET_CONTAINER_DLL_insert(set->copy_req_head,
1205  set->copy_req_tail,
1206  req);
1207 }
1208 
1209 
1217 struct GNUNET_SET_Element *
1219 {
1220  struct GNUNET_SET_Element *copy;
1221 
1222  copy = GNUNET_malloc(element->size + sizeof(struct GNUNET_SET_Element));
1223  copy->size = element->size;
1224  copy->element_type = element->element_type;
1225  copy->data = &copy[1];
1226  GNUNET_memcpy(&copy[1],
1227  element->data,
1228  copy->size);
1229  return copy;
1230 }
1231 
1232 
1240 void
1242  struct GNUNET_HashCode *ret_hash)
1243 {
1245 
1246  /* It's not guaranteed that the element data is always after the element header,
1247  so we need to hash the chunks separately. */
1248  GNUNET_CRYPTO_hash_context_read(ctx, &element->size, sizeof(uint16_t));
1249  GNUNET_CRYPTO_hash_context_read(ctx, &element->element_type, sizeof(uint16_t));
1250  GNUNET_CRYPTO_hash_context_read(ctx, element->data, element->size);
1251  GNUNET_CRYPTO_hash_context_finish(ctx, ret_hash);
1252 }
1253 
1254 /* end of set_api.c */
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.
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:148
struct SetCopyRequest * next
Definition: set_api.c:36
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:1012
void * result_cls
Closure for result_cb.
Definition: set_api.c:142
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:729
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
static void handle_iter_element(void *cls, const struct GNUNET_SET_IterResponseMessage *msg)
Handle element for iteration over the set.
Definition: set_api.c:297
#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:682
#define GNUNET_MESSAGE_TYPE_SET_ADD
Add element to set.
Handle for a set operation request from another peer.
Definition: set_api.c:113
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:900
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:186
void * iterator_cls
Closure for iterator.
Definition: set_api.c:73
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:706
#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:238
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:94
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:879
static void handle_request(void *cls, const struct GNUNET_SET_RequestMessage *msg)
Handle request message for a listen operation.
Definition: set_api.c:904
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:652
#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:204
struct GNUNET_SET_OperationHandle * ops_tail
Linked list of operations on the set.
Definition: set_api.c:62
#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:148
#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:38
uint32_t request_id
id the result belongs to
Definition: set.h:252
#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:101
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#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
GNUNET_SET_ListenCallback listen_cb
Function to call on a new incoming request, or on error.
Definition: set_api.c:199
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 GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:445
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.
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:808
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:389
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:185
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:91
void * cls
Definition: set_api.c:40
uint32_t request_id
Request ID to identify the operation within the set.
Definition: set_api.c:175
void GNUNET_SET_copy_lazy(struct GNUNET_SET_Handle *set, GNUNET_SET_CopyReadyCallback cb, void *cls)
Definition: set_api.c:1189
uint8_t force_full
Always send full sets, even if delta operations would be more efficient.
Definition: set.h:213
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:243
#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.
uint16_t element_type
Type of the element to add or remove.
Definition: set.h:283
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:67
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:767
uint64_t current_size
Current set size.
Definition: set.h:247
#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:124
struct GNUNET_MQ_Handle * mq
Message queue for client.
Definition: set_api.c:52
#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:85
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
#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:137
Only use optimized set operations, even though for this particular set operation they might be much s...
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:338
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:772
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:58
struct GNUNET_TIME_Relative reconnect_backoff
Time to wait until we try to reconnect on failure.
Definition: set_api.c:214
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:207
uint16_t result_status
Was the evaluation successful? Contains an enum GNUNET_SET_Status in NBO.
Definition: set.h:258
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:201
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:969
#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
GNUNET_SET_CopyReadyCallback cb
Definition: set_api.c:42
int destroy_requested
Should the set be destroyed once all operations are gone? GNUNET_SYSERR if GNUNET_SET_destroy() must ...
Definition: set_api.c:80
#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:372
Opaque handle to a set.
Definition: set_api.c:48
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:160
uint32_t accept_id
Id of the request, used to identify the request when accepting/rejecting it.
Definition: set_api.c:118
struct GNUNET_HashCode app_id
Application ID we listen for.
Definition: set_api.c:209
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:319
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:281
uint16_t element_type
Type of the element attachted to the message, if any.
Definition: set.h:263
uint8_t byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
Definition: set.h:219
#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
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:471
uint8_t byzantine_lower_bound
Lower bound for the set size, used only when byzantine mode is enabled.
Definition: set.h:225
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_REQUEST.
Definition: set.h:152
Sent to the service by the client in order to cancel a set operation.
Definition: set.h:298
void GNUNET_SET_listen_cancel(struct GNUNET_SET_ListenHandle *lh)
Cancel the given listen operation.
Definition: set_api.c:1046
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_ElementIterator iterator
Callback for the current iteration over the set, NULL if no iterator is active.
Definition: set_api.c:68
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:165
static int check_result(void *cls, const struct GNUNET_SET_ResultMessage *msg)
Check that the given msg is well-formed.
Definition: set_api.c:374
uint32_t accept_reject_id
ID of the incoming request we want to accept.
Definition: set.h:89
struct SetCopyRequest * copy_req_tail
Doubly linked list of copy requests.
Definition: set_api.c:106
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_RESULT.
Definition: set.h:242
#define GNUNET_MESSAGE_TYPE_SET_ITER_ACK
Acknowledge result from iteration.
uint32_t cookie
Temporary name for the copied set.
Definition: set.h:381
Handle to an operation.
Definition: set_api.c:132
Handle to a message queue.
Definition: mq.c:84
struct GNUNET_SET_OperationHandle * ops_head
Linked list of operations on the set.
Definition: set_api.c:57
#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:1123
uint32_t accept_reject_id
ID of the incoming request we want to reject.
Definition: set.h:141
static void set_operation_destroy(struct GNUNET_SET_OperationHandle *oh)
Destroy the given set operation.
Definition: set_api.c:481
struct GNUNET_HashCode app_id
application id
Definition: set.h:72
enum GNUNET_SET_OperationType operation
Operation we listen for.
Definition: set_api.c:224
struct GNUNET_MQ_Envelope * conclude_mqm
Message sent to the server on calling conclude, NULL if conclude has been called. ...
Definition: set_api.c:154
configuration data
Definition: configuration.c:83
struct GNUNET_HashCode app_id
Application id.
Definition: set.h:195
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.
void * GNUNET_MQ_assoc_remove(struct GNUNET_MQ_Handle *mq, uint32_t request_id)
Remove the association for a request_id.
Definition: mq.c:750
#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:356
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:131
Message sent by client to the service to add or remove an element to/from the set.
Definition: set.h:273
struct GNUNET_SET_OperationHandle * next
Handles are kept in a linked list.
Definition: set_api.c:170
Opaque handle to a listen operation.
Definition: set_api.c:182
struct GNUNET_PeerIdentity peer_id
Identity of the requesting peer.
Definition: set.h:163
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:511
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1218
uint32_t cookie
Temporary name for the copied set.
Definition: set.h:365
Header for all communications.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:821
#define GNUNET_YES
Definition: gnunet_common.h:77
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
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:577
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT.
Definition: set.h:319
uint32_t request_id
ID of the request we want to cancel.
Definition: set.h:307
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:1167
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:946
Message sent by a listening client to the service to reject performing the operation with the other p...
Definition: set.h:132
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:545
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.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration, needed when creating (lazy) copies.
Definition: set_api.c:96
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:488
#define GNUNET_malloc(size)
Wrapper around malloc.
uint16_t element_type
Type of the element attachted to the message, if any.
Definition: set.h:331
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:325
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:219
#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:349
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:1080
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:734
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
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:193
union GNUNET_SET_Option::@57 v
Value for the option, only used with some options.