GNUnet  0.11.x
gnunet-service-cadet_peer.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2001-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  */
20 
33 #include "platform.h"
34 #include "gnunet_util_lib.h"
35 #include "gnunet_hello_lib.h"
36 #include "gnunet_signatures.h"
38 #include "gnunet_ats_service.h"
39 #include "gnunet_core_service.h"
41 #include "cadet_protocol.h"
47 
48 
49 #define LOG(level, ...) GNUNET_log_from (level, "cadet-per", __VA_ARGS__)
50 
51 
55 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply ( \
56  GNUNET_TIME_UNIT_MINUTES, 5)
57 
61 #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply ( \
62  GNUNET_TIME_UNIT_MINUTES, 2)
63 
67 #define MAX_OOO_QUEUE_SIZE 100
68 
69 
75 {
80 
85 
90 
94  void *cb_cls;
95 
99  struct CadetPeer *cp;
100 
105 };
106 
107 
111 struct CadetPeer
112 {
117 
121  struct GNUNET_TIME_Absolute last_contactXXX;
122 
128 
134 
139 
144 
149 
155 
160 
165 
170 
174  struct CadetTunnel *t;
175 
180 
185 
190 
195 
201 
205  unsigned int queue_n;
206 
210  unsigned int num_paths;
211 
216  unsigned int off_sum;
217 
225  unsigned int mqm_ready_counter;
226 
231  unsigned int path_dll_length;
232 };
233 
234 
241 const char *
242 GCP_2s (const struct CadetPeer *cp)
243 {
244  static char buf[5];
245  char *ret;
246 
247  if ((NULL == cp) ||
248  (0 == GNUNET_is_zero (&cp->pid.public_key)))
249  return "NULL";
250 
252  if (NULL == ret)
253  return "NULL";
254 
255  GNUNET_strlcpy (buf,
256  ret,
257  sizeof(buf));
258  GNUNET_free (ret);
259  return buf;
260 }
261 
262 
278 double
280  unsigned int off)
281 {
282  unsigned int num_alts = cp->num_paths;
283  unsigned int off_sum;
284  double avg_sum;
285  double path_delta;
286  double weight_alts;
287 
288  GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
289  GNUNET_assert (0 != cp->path_dll_length);
290 
291  /* We maintain 'off_sum' in 'peer' and thereby
292  avoid the SLOW recalculation each time. Kept here
293  just to document what is going on. */
294 #if SLOW
295  off_sum = 0;
296  for (unsigned int j = 0; j < cp->path_dll_length; j++)
297  for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
298  NULL != pe;
299  pe = pe->next)
300  off_sum += j;
301  GNUNET_assert (off_sum == cp->off_sum);
302 #else
303  off_sum = cp->off_sum;
304 #endif
305  avg_sum = off_sum * 1.0 / cp->path_dll_length;
306  path_delta = off - avg_sum;
307  /* path_delta positiv: path off of peer above average (bad path for peer),
308  path_delta negativ: path off of peer below average (good path for peer) */
309  if (path_delta <= -1.0)
310  weight_alts = -num_alts / path_delta; /* discount alternative paths */
311  else if (path_delta >= 1.0)
312  weight_alts = num_alts * path_delta; /* overcount alternative paths */
313  else
314  weight_alts = num_alts; /* count alternative paths normally */
315 
316 
317  /* off+1: long paths are generally harder to find and thus count
318  a bit more as they get longer. However, above-average paths
319  still need to count less, hence the squaring of that factor. */
320  return (off + 1.0) / (weight_alts * weight_alts);
321 }
322 
323 
329 static void
330 destroy_peer (void *cls)
331 {
332  struct CadetPeer *cp = cls;
333 
335  "Destroying state about peer %s\n",
336  GCP_2s (cp));
337  cp->destroy_task = NULL;
338  GNUNET_assert (NULL == cp->t);
339  GNUNET_assert (NULL == cp->core_mq);
340  GNUNET_assert (0 == cp->num_paths);
341  for (unsigned int i = 0; i < cp->path_dll_length; i++)
342  GNUNET_assert (NULL == cp->path_heads[i]);
346  &cp->pid,
347  cp));
350  cp->path_dll_length = 0;
351  if (NULL != cp->search_h)
352  {
354  cp->search_h = NULL;
355  }
356  /* FIXME: clean up search_delayedXXX! */
357 
358  if (NULL != cp->hello_offer)
359  {
361  cp->hello_offer = NULL;
362  }
363  if (NULL != cp->connectivity_suggestion)
364  {
366  cp->connectivity_suggestion = NULL;
367  }
369  if (NULL != cp->path_heap)
370  {
372  cp->path_heap = NULL;
373  }
374  if (NULL != cp->heap_cleanup_task)
375  {
377  cp->heap_cleanup_task = NULL;
378  }
380  /* Peer should not be freed if paths exist; if there are no paths,
381  there ought to be no connections, and without connections, no
382  notifications. Thus we can assert that mqm_head is empty at this
383  point. */
384  GNUNET_assert (NULL == cp->mqm_head);
385  GNUNET_assert (NULL == cp->mqm_ready_ptr);
386  GNUNET_free (cp);
387 }
388 
389 
395 static void
397 {
398  uint32_t strength;
399 
401  "Updating peer %s activation state (%u connections)%s%s\n",
402  GCP_2s (cp),
404  (NULL == cp->t) ? "" : " with tunnel",
405  (NULL == cp->core_mq) ? "" : " with CORE link");
406  if (NULL != cp->destroy_task)
407  {
408  /* It's active, do not destory! */
410  cp->destroy_task = NULL;
411  }
413  (NULL == cp->t))
414  {
415  /* We're just on a path or directly connected; don't bother too much */
416  if (NULL != cp->connectivity_suggestion)
417  {
419  cp->connectivity_suggestion = NULL;
420  }
421  if (NULL != cp->search_h)
422  {
424  cp->search_h = NULL;
425  }
426  return;
427  }
428  if (NULL == cp->core_mq)
429  {
430  /* Lacks direct connection, try to create one by querying the DHT */
431  if ((NULL == cp->search_h) &&
433  cp->search_h
434  = GCD_search (&cp->pid);
435  }
436  else
437  {
438  /* Have direct connection, stop DHT search if active */
439  if (NULL != cp->search_h)
440  {
442  cp->search_h = NULL;
443  }
444  }
445 
446  /* If we have a tunnel, our urge for connections is much bigger */
447  strength = (NULL != cp->t) ? 32 : 1;
448  if (NULL != cp->connectivity_suggestion)
452  &cp->pid,
453  strength);
454 }
455 
456 
462 static void
464 
465 
472 static void
473 drop_paths (void *cls)
474 {
475  struct CadetPeer *cp = cls;
476  struct CadetPeerPath *path;
477 
478  cp->destroy_task = NULL;
479  while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
480  GCPP_release (path);
482 }
483 
484 
490 static void
492 {
493  struct GNUNET_TIME_Relative exp;
494 
495  if (NULL != cp->destroy_task)
496  {
498  cp->destroy_task = NULL;
499  }
500  if (NULL != cp->t)
501  return; /* still relevant! */
502  if (NULL != cp->core_mq)
503  return; /* still relevant! */
505  return; /* still relevant! */
506  if ((NULL != cp->path_heap) &&
508  {
510  &drop_paths,
511  cp);
512  return;
513  }
514  if (0 != cp->num_paths)
515  return; /* still relevant! */
516  if (NULL != cp->hello)
517  {
518  /* relevant only until HELLO expires */
520  cp->hello));
522  &destroy_peer,
523  cp);
524  return;
525  }
527  &destroy_peer,
528  cp);
529 }
530 
531 
538 void
539 GCP_set_mq (struct CadetPeer *cp,
540  struct GNUNET_MQ_Handle *mq)
541 {
543  "Message queue for peer %s is now %p\n",
544  GCP_2s (cp),
545  mq);
546  cp->core_mq = mq;
547  for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
548  NULL != mqm;
549  mqm = next)
550  {
551  /* Save next pointer in case mqm gets freed by the callback */
552  next = mqm->next;
553  if (NULL == mq)
554  {
555  if (NULL != mqm->env)
556  {
557  GNUNET_MQ_discard (mqm->env);
558  mqm->env = NULL;
559  mqm->cb (mqm->cb_cls,
560  GNUNET_SYSERR);
561  }
562  else
563  {
564  mqm->cb (mqm->cb_cls,
565  GNUNET_NO);
566  }
567  }
568  else
569  {
570  GNUNET_assert (NULL == mqm->env);
571  mqm->cb (mqm->cb_cls,
572  GNUNET_YES);
573  }
574  }
575  if ((NULL != mq) ||
576  (NULL != cp->t))
578  else
580 
581  if ((NULL != mq) &&
582  (NULL != cp->t))
583  {
584  /* have a new, direct path to the target, notify tunnel */
585  struct CadetPeerPath *path;
586 
587  path = GCPP_get_path_from_route (1,
588  &cp->pid);
589  GCT_consider_path (cp->t,
590  path,
591  0);
592  }
593 }
594 
595 
602 static int
604 {
605  if (0 == drop_percent)
606  return GNUNET_NO;
608  101) < drop_percent)
609  return GNUNET_YES;
610  return GNUNET_NO;
611 }
612 
613 
620 static void
621 mqm_send_done (void *cls);
622 
623 
629 static void
631 {
632  struct CadetPeer *cp = mqm->cp;
633 
634  /* Move ready pointer to the next entry that might be ready. */
635  if ((mqm == cp->mqm_ready_ptr) &&
636  (NULL != mqm->next))
637  cp->mqm_ready_ptr = mqm->next;
638  /* Move entry to the end of the DLL, to be fair. */
639  if (mqm != cp->mqm_tail)
640  {
642  cp->mqm_tail,
643  mqm);
645  cp->mqm_tail,
646  mqm);
647  }
648  cp->mqm_ready_counter--;
649  if (GNUNET_YES == should_I_drop ())
650  {
652  "DROPPING message to peer %s from MQM %p\n",
653  GCP_2s (cp),
654  mqm);
655  GNUNET_MQ_discard (mqm->env);
656  mqm->env = NULL;
657  mqm_send_done (cp);
658  }
659  else
660  {
661  {
662  const struct GNUNET_MessageHeader *mh;
663 
664  mh = GNUNET_MQ_env_get_msg (mqm->env);
665  switch (ntohs (mh->type))
666  {
668  {
670  = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh;
672  "P2P forwarding KX with ephemeral %s to %s on CID %s\n",
673  GNUNET_e2s (&msg->ephemeral_key),
674  GCP_2s (cp),
676  }
677  break;
678 
679  default:
680  break;
681  }
682  }
684  "Sending to peer %s from MQM %p\n",
685  GCP_2s (cp),
686  mqm);
687  GNUNET_MQ_send (cp->core_mq,
688  mqm->env);
689  mqm->env = NULL;
690  }
691  mqm->cb (mqm->cb_cls,
692  GNUNET_YES);
693 }
694 
695 
703 static void
705 {
706  struct GCP_MessageQueueManager *mqm;
707 
708  if (0 == cp->mqm_ready_counter)
709  return;
710  while ((NULL != (mqm = cp->mqm_ready_ptr)) &&
711  (NULL == mqm->env))
712  cp->mqm_ready_ptr = mqm->next;
713  if (NULL == mqm)
714  return; /* nothing to do */
715  mqm_execute (mqm);
716 }
717 
718 
725 static void
726 mqm_send_done (void *cls)
727 {
728  struct CadetPeer *cp = cls;
729 
731  "Sending to peer %s completed\n",
732  GCP_2s (cp));
733  send_next_ready (cp);
734 }
735 
736 
744 void
746  struct GNUNET_MQ_Envelope *env)
747 {
748  struct CadetPeer *cp = mqm->cp;
749 
750  GNUNET_assert (NULL != env);
752  "Queueing message to peer %s in MQM %p\n",
753  GCP_2s (cp),
754  mqm);
755  GNUNET_assert (NULL != cp->core_mq);
756  GNUNET_assert (NULL == mqm->env);
758  &mqm_send_done,
759  cp);
760  mqm->env = env;
761  cp->mqm_ready_counter++;
762  if (mqm != cp->mqm_ready_ptr)
763  cp->mqm_ready_ptr = cp->mqm_head;
764  if (1 == cp->mqm_ready_counter)
765  cp->mqm_ready_ptr = mqm;
766  if (0 != GNUNET_MQ_get_length (cp->core_mq))
767  return;
768  send_next_ready (cp);
769 }
770 
771 
780 static int
782  const struct GNUNET_PeerIdentity *pid,
783  void *value)
784 {
785  struct CadetPeer *cp = value;
786 
787  if (NULL != cp->destroy_task)
788  {
790  cp->destroy_task = NULL;
791  }
792  destroy_peer (cp);
793  return GNUNET_OK;
794 }
795 
796 
802 void
804 {
806  "Destroying all peers now\n");
809  NULL);
810 }
811 
812 
819 void
821 {
822  struct CadetPeerPath *path;
823 
825  "Destroying all paths to %s\n",
826  GCP_2s (cp));
827  while (NULL != (path =
829  GCPP_release (path);
831  cp->path_heap = NULL;
832 }
833 
834 
842 void
844  struct CadetPeerPathEntry *entry,
845  unsigned int off)
846 {
848  off));
850  "Discovered that peer %s is on path %s at offset %u\n",
851  GCP_2s (cp),
852  GCPP_2s (entry->path),
853  off);
854  if (off >= cp->path_dll_length)
855  {
856  unsigned int len = cp->path_dll_length;
857 
859  len,
860  off + 4);
862  cp->path_dll_length,
863  off + 4);
864  }
866  cp->path_tails[off],
867  entry);
868  cp->off_sum += off;
869  cp->num_paths++;
870 
871  /* If we have a tunnel to this peer, tell the tunnel that there is a
872  new path available. */
873  if (NULL != cp->t)
874  GCT_consider_path (cp->t,
875  entry->path,
876  off);
877 
878  if ((NULL != cp->search_h) &&
879  (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths))
880  {
881  /* Now I have enough paths, stop search */
883  cp->search_h = NULL;
884  }
885  if (NULL != cp->destroy_task)
886  {
887  /* paths changed, this resets the destroy timeout counter
888  and aborts a destroy task that may no longer be valid
889  to have (as we now have more paths via this peer). */
891  }
892 }
893 
894 
902 void
904  struct CadetPeerPathEntry *entry,
905  unsigned int off)
906 {
908  "Removing knowledge about peer %s beging on path %s at offset %u\n",
909  GCP_2s (cp),
910  GCPP_2s (entry->path),
911  off);
913  cp->path_tails[off],
914  entry);
915  GNUNET_assert (0 < cp->num_paths);
916  cp->off_sum -= off;
917  cp->num_paths--;
918  if ((NULL == cp->core_mq) &&
919  (NULL != cp->t) &&
920  (NULL == cp->search_h) &&
922  cp->search_h
923  = GCD_search (&cp->pid);
924  if (NULL == cp->destroy_task)
925  {
926  /* paths changed, we might now be ready for destruction, check again */
928  }
929 }
930 
931 
938 static void
939 path_heap_cleanup (void *cls)
940 {
941  struct CadetPeer *cp = cls;
942  struct CadetPeerPath *root;
943 
944  cp->heap_cleanup_task = NULL;
947  {
948  /* Now we have way too many, drop least desirable UNLESS it is in use!
949  (Note that this intentionally keeps highly desireable, but currently
950  unused paths around in the hope that we might be able to switch, even
951  if the number of paths exceeds the threshold.) */
953  GNUNET_assert (NULL != root);
954  if (NULL !=
955  GCPP_get_connection (root,
956  cp,
957  GCPP_get_length (root) - 1))
958  break; /* can't fix */
959  /* Got plenty of paths to this destination, and this is a low-quality
960  one that we don't care about. Allow it to die. */
961  GNUNET_assert (root ==
963  GCPP_release (root);
964  }
965 }
966 
967 
981  struct CadetPeerPath *path,
982  unsigned int off,
983  int force)
984 {
985  GNUNET_CONTAINER_HeapCostType desirability;
986  struct CadetPeerPath *root;
987  GNUNET_CONTAINER_HeapCostType root_desirability;
988  struct GNUNET_CONTAINER_HeapNode *hn;
989 
990  GNUNET_assert (off == GCPP_get_length (path) - 1);
992  off));
993  if (NULL == cp->path_heap)
994  {
995  /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
996  GNUNET_assert (GNUNET_NO == force);
997  return NULL;
998  }
999  desirability = GCPP_get_desirability (path);
1000  if (GNUNET_NO == force)
1001  {
1002  /* FIXME: desirability is not yet initialized; tricky! */
1003  if (GNUNET_NO ==
1005  (void **) &root,
1006  &root_desirability))
1007  {
1008  root = NULL;
1009  root_desirability = 0;
1010  }
1011 
1013  (desirability < root_desirability))
1014  {
1016  "Decided to not attach path %s to peer %s due to undesirability\n",
1017  GCPP_2s (path),
1018  GCP_2s (cp));
1019  return NULL;
1020  }
1021  }
1022 
1024  "Attaching path %s to peer %s (%s)\n",
1025  GCPP_2s (path),
1026  GCP_2s (cp),
1027  (GNUNET_NO == force) ? "desirable" : "forced");
1028 
1029  /* Yes, we'd like to add this path, add to our heap */
1031  path,
1032  desirability);
1033 
1034  /* Consider maybe dropping other paths because of the new one */
1037  (NULL != cp->heap_cleanup_task))
1039  cp);
1040  return hn;
1041 }
1042 
1043 
1053 void
1055  struct CadetPeerPath *path,
1056  struct GNUNET_CONTAINER_HeapNode *hn)
1057 {
1059  "Detatching path %s from peer %s\n",
1060  GCPP_2s (path),
1061  GCP_2s (cp));
1062  GNUNET_assert (path ==
1064 }
1065 
1066 
1073 void
1075  struct CadetConnection *cc)
1076 {
1078  "Adding %s to peer %s\n",
1079  GCC_2s (cc),
1080  GCP_2s (cp));
1083  &GCC_get_id (
1084  cc)->connection_of_tunnel,
1085  cc,
1087  if (NULL != cp->destroy_task)
1088  {
1090  cp->destroy_task = NULL;
1091  }
1092 }
1093 
1094 
1101 void
1103  struct CadetConnection *cc)
1104 {
1106  "Removing connection %s from peer %s\n",
1107  GCC_2s (cc),
1108  GCP_2s (cp));
1111  &GCC_get_id (
1112  cc)->
1113  connection_of_tunnel,
1114  cc));
1115  consider_peer_destroy (cp);
1116 }
1117 
1118 
1130 struct CadetPeer *
1132  int create)
1133 {
1134  struct CadetPeer *cp;
1135 
1137  peer_id);
1138  if (NULL != cp)
1139  return cp;
1140  if (GNUNET_NO == create)
1141  return NULL;
1142  cp = GNUNET_new (struct CadetPeer);
1143  cp->pid = *peer_id;
1145  GNUNET_YES);
1150  &cp->pid,
1151  cp,
1154  "Creating peer %s\n",
1155  GCP_2s (cp));
1156  return cp;
1157 }
1158 
1159 
1166 const struct GNUNET_PeerIdentity *
1167 GCP_get_id (struct CadetPeer *cp)
1168 {
1169  return &cp->pid;
1170 }
1171 
1172 
1179 void
1181  void *cls)
1182 {
1184  iter,
1185  cls);
1186 }
1187 
1188 
1195 unsigned int
1196 GCP_count_paths (const struct CadetPeer *cp)
1197 {
1198  return cp->num_paths;
1199 }
1200 
1201 
1210 unsigned int
1212  GCP_PathIterator callback,
1213  void *callback_cls)
1214 {
1215  unsigned int ret = 0;
1216 
1218  "Iterating over paths to peer %s%s\n",
1219  GCP_2s (cp),
1220  (NULL == cp->core_mq) ? "" : " including direct link");
1221  if (NULL != cp->core_mq)
1222  {
1223  /* FIXME: this branch seems to duplicate the
1224  i=0 case below (direct link). Leave out!??? -CG */
1225  struct CadetPeerPath *path;
1226 
1227  path = GCPP_get_path_from_route (1,
1228  &cp->pid);
1229  ret++;
1230  if (GNUNET_NO ==
1231  callback (callback_cls,
1232  path,
1233  0))
1234  return ret;
1235  }
1236  for (unsigned int i = 0; i < cp->path_dll_length; i++)
1237  {
1238  for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1239  NULL != pe;
1240  pe = pe->next)
1241  {
1242  ret++;
1243  if (GNUNET_NO ==
1244  callback (callback_cls,
1245  pe->path,
1246  i))
1247  return ret;
1248  }
1249  }
1250  return ret;
1251 }
1252 
1253 
1262 unsigned int
1264  GCP_PathIterator callback,
1265  void *callback_cls)
1266 {
1267  unsigned int ret = 0;
1268 
1270  "Iterating over paths to peer %s without direct link\n",
1271  GCP_2s (cp));
1272  for (unsigned int i = 1; i < cp->path_dll_length; i++)
1273  {
1274  for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1275  NULL != pe;
1276  pe = pe->next)
1277  {
1278  ret++;
1279  if (GNUNET_NO ==
1280  callback (callback_cls,
1281  pe->path,
1282  i))
1283  return ret;
1284  }
1285  }
1286  return ret;
1287 }
1288 
1289 
1300 unsigned int
1302  unsigned int dist,
1303  GCP_PathIterator callback,
1304  void *callback_cls)
1305 {
1306  unsigned int ret = 0;
1307 
1308  if (dist >= cp->path_dll_length)
1309  {
1311  "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1312  dist,
1313  cp->path_dll_length);
1314  return 0;
1315  }
1316  for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1317  NULL != pe;
1318  pe = pe->next)
1319  {
1320  if (GNUNET_NO ==
1321  callback (callback_cls,
1322  pe->path,
1323  dist))
1324  return ret;
1325  ret++;
1326  }
1327  return ret;
1328 }
1329 
1330 
1338 struct CadetTunnel *
1340  int create)
1341 {
1342  if (NULL == cp)
1343  return NULL;
1344  if ((NULL != cp->t) ||
1345  (GNUNET_NO == create))
1346  return cp->t;
1347  cp->t = GCT_create_tunnel (cp);
1349  return cp->t;
1350 }
1351 
1352 
1359 static void
1360 hello_offer_done (void *cls)
1361 {
1362  struct CadetPeer *cp = cls;
1363 
1364  cp->hello_offer = NULL;
1365 }
1366 
1367 
1375 void
1377  const struct GNUNET_HELLO_Message *hello)
1378 {
1379  struct GNUNET_HELLO_Message *mrg;
1380 
1382  "Got %u byte HELLO for peer %s\n",
1383  (unsigned int) GNUNET_HELLO_size (hello),
1384  GCP_2s (cp));
1385  if (NULL != cp->hello_offer)
1386  {
1388  cp->hello_offer = NULL;
1389  }
1390  if (NULL != cp->hello)
1391  {
1392  mrg = GNUNET_HELLO_merge (hello,
1393  cp->hello);
1394  GNUNET_free (cp->hello);
1395  cp->hello = mrg;
1396  }
1397  else
1398  {
1399  cp->hello = GNUNET_memdup (hello,
1400  GNUNET_HELLO_size (hello));
1401  }
1402  cp->hello_offer
1406  cp);
1407  /* New HELLO means cp's destruction time may change... */
1408  consider_peer_destroy (cp);
1409 }
1410 
1411 
1419 void
1421  struct CadetTunnel *t)
1422 {
1424  "Dropping tunnel %s to peer %s\n",
1425  GCT_2s (t),
1426  GCP_2s (cp));
1427  GNUNET_assert (cp->t == t);
1428  cp->t = NULL;
1429  consider_peer_destroy (cp);
1430 }
1431 
1432 
1439 int
1441 {
1442  return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1443 }
1444 
1445 
1454 struct GCP_MessageQueueManager *
1457  void *cb_cls)
1458 {
1459  struct GCP_MessageQueueManager *mqm;
1460 
1461  mqm = GNUNET_new (struct GCP_MessageQueueManager);
1462  mqm->cb = cb;
1463  mqm->cb_cls = cb_cls;
1464  mqm->cp = cp;
1466  cp->mqm_tail,
1467  mqm);
1469  "Creating MQM %p for peer %s\n",
1470  mqm,
1471  GCP_2s (cp));
1472  if (NULL != cp->core_mq)
1473  cb (cb_cls,
1474  GNUNET_YES);
1475  return mqm;
1476 }
1477 
1478 
1485 void
1487  struct GNUNET_MQ_Envelope *last_env)
1488 {
1489  struct CadetPeer *cp = mqm->cp;
1490 
1492  "Destroying MQM %p for peer %s%s\n",
1493  mqm,
1494  GCP_2s (cp),
1495  (NULL == last_env) ? "" : " with last ditch transmission");
1496  if (NULL != mqm->env)
1497  GNUNET_MQ_discard (mqm->env);
1498  if (NULL != last_env)
1499  {
1500  if (NULL != cp->core_mq)
1501  {
1502  GNUNET_MQ_notify_sent (last_env,
1503  &mqm_send_done,
1504  cp);
1505  GNUNET_MQ_send (cp->core_mq,
1506  last_env);
1507  }
1508  else
1509  {
1510  GNUNET_MQ_discard (last_env);
1511  }
1512  }
1513  if (cp->mqm_ready_ptr == mqm)
1514  cp->mqm_ready_ptr = mqm->next;
1516  cp->mqm_tail,
1517  mqm);
1518  GNUNET_free (mqm);
1519 }
1520 
1521 
1531 void
1533  struct GNUNET_MQ_Envelope *env)
1534 {
1536  "Sending message to %s out of management\n",
1537  GCP_2s (cp));
1538  if (NULL == cp->core_mq)
1539  {
1540  GNUNET_MQ_discard (env);
1541  return;
1542  }
1544  {
1545  GNUNET_MQ_discard (env);
1546  return;
1547  }
1548  GNUNET_MQ_notify_sent (env,
1549  &mqm_send_done,
1550  cp);
1551  GNUNET_MQ_send (cp->core_mq,
1552  env);
1553 }
1554 
1555 
1556 /* end of gnunet-service-cadet-new_peer.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
unsigned int off_sum
Sum over all of the offsets of all of the paths in the path_heads DLLs.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
Peer description.
A HELLO message is used to exchange information about transports with other peers.
Entry in linked list for all offer-HELLO requests.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
void(* GCP_MessageQueueNotificationCallback)(void *cls, int available)
Function to call with updated message queue object.
struct GNUNET_CONTAINER_MultiShortmap * connections
Connections that go through this peer; indexed by tid.
Low-level connection to a destination.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition: mq.c:1080
#define MAX_OOO_QUEUE_SIZE
Queue size when we start dropping OOO messages.
void GCP_drop_owned_paths(struct CadetPeer *cp)
Drop all paths owned by this peer, and do not allow new ones to be added: We are shutting down...
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct CadetTunnel * GCP_get_tunnel(struct CadetPeer *cp, int create)
Get the tunnel towards a peer.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
struct GNUNET_HELLO_Message * GNUNET_HELLO_merge(const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2)
Construct a HELLO message by merging the addresses in two existing HELLOs (which must be for the same...
Definition: hello.c:524
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GCP_MessageQueueManager * prev
Kept in a DLL.
A connection is a live end-to-end messaging mechanism where the peers are identified by a path and kn...
Handle for DHT searches.
void GCD_search_stop(struct GCD_search_handle *h)
Stop DHT search started with GCD_search().
const char * GCT_2s(const struct CadetTunnel *t)
Get the static string for the peer this tunnel is directed.
static void consider_peer_destroy(struct CadetPeer *cp)
This peer may no longer be needed, consider cleaning it up.
#define DESIRED_CONNECTIONS_PER_TUNNEL
How many connections would we like to have per tunnel?
void GCP_set_hello(struct CadetPeer *cp, const struct GNUNET_HELLO_Message *hello)
We got a HELLO for a peer, remember it, and possibly trigger adequate actions (like trying to connect...
struct GCP_MessageQueueManager * mqm_head
Notifications to call when core_mq changes.
const char * GCC_2s(const struct CadetConnection *cc)
Get a (static) string for a connection.
struct GNUNET_MQ_Handle * core_mq
Handle for core transmissions.
Data structure used to track whom we have to notify about changes to our message queue.
static void send_next_ready(struct CadetPeer *cp)
Find the next ready message in the queue (starting the search from the cp->mqm_ready_ptr) and if poss...
struct CadetTunnel * GCT_create_tunnel(struct CadetPeer *destination)
Create a tunnel to destionation.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
Entry in a peer path.
#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
static void destroy_peer(void *cls)
This peer is no longer be needed, clean it up now.
const struct GNUNET_CADET_ConnectionTunnelIdentifier * GCC_get_id(struct CadetConnection *cc)
Obtain unique ID for the connection.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
int(* GNUNET_CONTAINER_PeerMapIterator)(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
struct GNUNET_TRANSPORT_OfferHelloHandle * hello_offer
Handle to us offering the HELLO to the transport.
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_CONTAINER_HeapNode * GCP_attach_path(struct CadetPeer *cp, struct CadetPeerPath *path, unsigned int off, int force)
Try adding a path to this peer.
int GNUNET_CONTAINER_heap_peek2(const struct GNUNET_CONTAINER_Heap *heap, void **element, GNUNET_CONTAINER_HeapCostType *cost)
Get element and cost stored at the root of heap.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
void GCP_set_mq(struct CadetPeer *cp, struct GNUNET_MQ_Handle *mq)
Set the message queue to mq for peer cp and notify watchers.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
Information we track per tunnel.
struct CadetPeerPathEntry ** path_heads
Array of DLLs of paths traversing the peer, organized by the offset of the peer on the larger path...
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
struct GNUNET_HELLO_Message * hello
Hello message of the peer.
void GCP_send(struct GCP_MessageQueueManager *mqm, struct GNUNET_MQ_Envelope *env)
Send the message in env to cp.
struct CadetPeerPathEntry ** path_tails
Array of DLL of paths traversing the peer, organized by the offset of the peer on the larger path...
unsigned int GCP_iterate_paths(struct CadetPeer *cp, GCP_PathIterator callback, void *callback_cls)
Iterate over the paths to a peer.
static struct GNUNET_SCHEDULER_Task * t
Main task.
void * cb_cls
Closure for cb.
struct GNUNET_MessageHeader * GNUNET_HELLO_get_header(struct GNUNET_HELLO_Message *hello)
Get the header from a HELLO message, used so other code can correctly send HELLO messages.
Definition: hello.c:693
int(* GCP_PathIterator)(void *cls, struct CadetPeerPath *path, unsigned int off)
Peer path iterator.
#define IDLE_PEER_TIMEOUT
How long do we wait until tearing down an idle peer?
struct GCP_MessageQueueManager * next
Kept in a DLL.
#define LOG(level,...)
struct GNUNET_ATS_ConnectivitySuggestHandle * connectivity_suggestion
Handle to our ATS request asking ATS to suggest an address to TRANSPORT for this peer (to establish a...
const char * GCP_2s(const struct CadetPeer *cp)
Get the static string for a peer ID.
struct GNUNET_ATS_ConnectivitySuggestHandle * GNUNET_ATS_connectivity_suggest(struct GNUNET_ATS_ConnectivityHandle *ch, const struct GNUNET_PeerIdentity *peer, uint32_t strength)
We would like to receive address suggestions for a peer.
static void hello_offer_done(void *cls)
Hello offer was passed to the transport service.
unsigned int path_dll_length
Current length of the path_heads and arrays.
void GCP_path_entry_remove(struct CadetPeer *cp, struct CadetPeerPathEntry *entry, unsigned int off)
Remove an entry from the DLL of all of the paths that this peer is on.
GCP_MessageQueueNotificationCallback cb
Function to call with updated message queue object.
void GCP_destroy_all_peers()
Clean up all entries about all peers.
struct GCP_MessageQueueManager * mqm_ready_ptr
Pointer to first "ready" entry in mqm_head.
static int should_I_drop(void)
Debug function should NEVER return true in production code, useful to simulate losses for testcases...
const char * GCPP_2s(struct CadetPeerPath *path)
Convert a path to a human-readable string.
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:1253
#define IDLE_PATH_TIMEOUT
How long do we keep paths around if we no longer care about the peer?
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
Information we track per peer.
unsigned int queue_n
How many messages are in the queue to this peer.
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
static char * value
Value of the record to add/remove.
void GCP_remove_connection(struct CadetPeer *cp, struct CadetConnection *cc)
Remove a connection that went via this cp.
struct CadetPeerPath * GCPP_get_path_from_route(unsigned int path_length, const struct GNUNET_PeerIdentity *pids)
We got an incoming connection, obtain the corresponding path.
struct GCD_search_handle * search_h
Handle to stop the DHT search for paths to this peer.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:335
char * GNUNET_CRYPTO_eddsa_public_key_to_string(const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a public key to a string.
Definition: crypto_ecc.c:365
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1280
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
void GCP_send_ooo(struct CadetPeer *cp, struct GNUNET_MQ_Envelope *env)
Send the message in env to cp, overriding queueing logic.
struct CadetPeerPath * path
Path this entry belongs to.
unsigned int num_paths
How many paths do we have to this peer (in all path_heads DLLs combined).
static char buf[2048]
Handle for ATS address suggestion requests.
struct GNUNET_CADET_ConnectionTunnelIdentifier cid
ID of the connection.
int GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
struct GNUNET_MQ_Envelope * env
Envelope this manager would like to transmit once it is its turn.
Handle to a node in a heap.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
Heap with the minimum cost at the root.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
static void consider_peer_activate(struct CadetPeer *cp)
This peer is now on more "active" duty, activate processes related to it.
struct GNUNET_PeerIdentity pid
ID of the peer.
void GNUNET_TRANSPORT_offer_hello_cancel(struct GNUNET_TRANSPORT_OfferHelloHandle *ohh)
Cancel the request to transport to offer the HELLO message.
void GCP_add_connection(struct CadetPeer *cp, struct CadetConnection *cc)
Add a connection to this cp.
unsigned long long drop_percent
Set to non-zero values to create random drops to test retransmissions.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:321
Node in the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
Struct containing all information regarding a tunnel to a peer.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
static void mqm_execute(struct GCP_MessageQueueManager *mqm)
Transmit current envelope from this mqm.
Internal representation of the hash map.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
uint64_t GNUNET_CONTAINER_HeapCostType
Cost by which elements in a heap can be ordered.
struct GCP_MessageQueueManager * mqm_tail
Notifications to call when core_mq changes.
GNUNET_CONTAINER_HeapCostType GCPP_get_desirability(const struct CadetPeerPath *path)
Return how much we like keeping the path.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void GCT_consider_path(struct CadetTunnel *t, struct CadetPeerPath *p, unsigned int off)
Consider using the path p for the tunnel t.
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
P2P messages used by CADET.
unsigned int GCP_iterate_paths_at(struct CadetPeer *cp, unsigned int dist, GCP_PathIterator callback, void *callback_cls)
Iterate over the paths to cp where cp is at distance dist from us.
void GCP_path_entry_add(struct CadetPeer *cp, struct CadetPeerPathEntry *entry, unsigned int off)
Add an entry to the DLL of all of the paths that this peer is on.
int GCP_has_core_connection(struct CadetPeer *cp)
Test if cp has a core-level connection.
static void drop_paths(void *cls)
We really no longere care about a peer, stop hogging memory with paths to it.
unsigned int GCP_iterate_indirect_paths(struct CadetPeer *cp, GCP_PathIterator callback, void *callback_cls)
Iterate over the paths to a peer without direct link.
Handle to a message queue.
Definition: mq.c:85
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
The identity of the host (wraps the signing key of the peer).
void GCP_drop_tunnel(struct CadetPeer *cp, struct CadetTunnel *t)
The tunnel to the given peer no longer exists, remove it from our data structures, and possibly clean up the peer itself.
unsigned int mqm_ready_counter
Number of message queue managers of this peer that have a message in waiting.
struct CadetPeer * GCP_get(const struct GNUNET_PeerIdentity *peer_id, int create)
Retrieve the CadetPeer stucture associated with the peer.
static struct CadetPeer * peers
Operation to get peer ids.
void GCP_request_mq_cancel(struct GCP_MessageQueueManager *mqm, struct GNUNET_MQ_Envelope *last_env)
Stops message queue change notifications.
void GCP_detach_path(struct CadetPeer *cp, struct CadetPeerPath *path, struct GNUNET_CONTAINER_HeapNode *hn)
This peer can no longer own path as the path has been extended and a peer further down the line is no...
Message for a Key eXchange for a tunnel.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
double GCP_get_desirability_of_path(struct CadetPeer *cp, unsigned int off)
Calculate how desirable a path is for cp if cp is at offset off.
struct GNUNET_SCHEDULER_Task * destroy_task
Task to destroy this entry.
Automatic transport selection and outbound bandwidth determination.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GCD_search_handle * GCD_search(const struct GNUNET_PeerIdentity *peer_id)
Search DHT for paths to peeR_id.
struct CadetConnection * GCPP_get_connection(struct CadetPeerPath *path, struct CadetPeer *destination, unsigned int off)
Return connection to destination using path, or return NULL if no such connection exists...
Entry in list of pending tasks.
Definition: scheduler.c:134
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
struct GNUNET_TRANSPORT_OfferHelloHandle * GNUNET_TRANSPORT_offer_hello(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_MessageHeader *hello, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Offer the transport service the HELLO of another peer.
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:652
struct CadetPeer * GCPP_get_peer_at_offset(struct CadetPeerPath *path, unsigned int off)
Obtain the peer at offset off in path.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#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:353
cadet service; dealing with DHT requests and results
struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key
Sender&#39;s ephemeral public ECC key encoded in a format suitable for network transmission, as created using &#39;gcry_sexp_sprint&#39;.
static void path_heap_cleanup(void *cls)
Prune down the number of paths to this peer, we seem to have way too many.
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
void GCP_iterate_all(GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
Iterate over all known peers.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
struct CadetPeer * cp
The peer this is for.
struct GNUNET_CONTAINER_Heap * path_heap
MIN-heap of paths owned by this peer (they also end at this peer).
Information regarding a possible path to reach a peer.
unsigned int GCP_count_paths(const struct CadetPeer *cp)
Count the number of known paths toward the peer.
struct GNUNET_TIME_Absolute GNUNET_HELLO_get_last_expiration(const struct GNUNET_HELLO_Message *msg)
When does the last address in the given HELLO expire?
Definition: hello.c:892
struct GNUNET_ShortHashCode connection_of_tunnel
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
unsigned int GCPP_get_length(struct CadetPeerPath *path)
Return the length of the path.
struct CadetTunnel * t
Tunnel to this peer, if any.
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:219
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
static void mqm_send_done(void *cls)
Function called when CORE took one of the messages from a message queue manager and transmitted it...
struct CadetPeerPathEntry * next
DLL of paths where the same peer is at the same offset.
static struct GNUNET_ATS_ConnectivityHandle * ats_ch
Our connectivity handle.
Definition: gnunet-ats.c:121
#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
Axolotl key exchange.
#define GNUNET_free(ptr)
Wrapper around free.
const struct GNUNET_PeerIdentity * GCP_get_id(struct CadetPeer *cp)
Obtain the peer identity for a struct CadetPeer.
Time for relative time used by GNUnet, in microseconds.
void GCPP_release(struct CadetPeerPath *path)
The owning peer of this path is no longer interested in maintaining it, so the path should be discard...
struct GNUNET_CRYPTO_EddsaPublicKey public_key
struct GCP_MessageQueueManager * GCP_request_mq(struct CadetPeer *cp, GCP_MessageQueueNotificationCallback cb, void *cb_cls)
Start message queue change notifications.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
struct GNUNET_SCHEDULER_Task * heap_cleanup_task
Task to clean up path_heap asynchronously.
static int destroy_iterator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called to destroy a peer now.