GNUnet  0.10.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(GNUNET_TIME_UNIT_MINUTES, 5)
56 
60 #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
61 
65 #define MAX_OOO_QUEUE_SIZE 100
66 
67 
73 {
74 
79 
84 
89 
93  void *cb_cls;
94 
98  struct CadetPeer *cp;
99 
104 
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 
235 
242 const char *
243 GCP_2s (const struct CadetPeer *cp)
244 {
245  static char buf[5];
246  char *ret;
247 
248  if ((NULL == cp) ||
249  (NULL == &cp->pid.public_key))
250  return "NULL";
251 
252 
254 
255  if (NULL == ret)
256  return "NULL";
257 
258 
259  GNUNET_strlcpy (buf,
260  ret,
261  sizeof (buf));
262  GNUNET_free (ret);
263  return buf;
264 }
265 
266 
282 double
284  unsigned int off)
285 {
286  unsigned int num_alts = cp->num_paths;
287  unsigned int off_sum;
288  double avg_sum;
289  double path_delta;
290  double weight_alts;
291 
292  GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
293  GNUNET_assert (0 != cp->path_dll_length);
294 
295  /* We maintain 'off_sum' in 'peer' and thereby
296  avoid the SLOW recalculation each time. Kept here
297  just to document what is going on. */
298 #if SLOW
299  off_sum = 0;
300  for (unsigned int j=0;j<cp->path_dll_length;j++)
301  for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
302  NULL != pe;
303  pe = pe->next)
304  off_sum += j;
305  GNUNET_assert (off_sum == cp->off_sum);
306 #else
307  off_sum = cp->off_sum;
308 #endif
309  avg_sum = off_sum * 1.0 / cp->path_dll_length;
310  path_delta = off - avg_sum;
311  /* path_delta positiv: path off of peer above average (bad path for peer),
312  path_delta negativ: path off of peer below average (good path for peer) */
313  if (path_delta <= - 1.0)
314  weight_alts = - num_alts / path_delta; /* discount alternative paths */
315  else if (path_delta >= 1.0)
316  weight_alts = num_alts * path_delta; /* overcount alternative paths */
317  else
318  weight_alts = num_alts; /* count alternative paths normally */
319 
320 
321  /* off+1: long paths are generally harder to find and thus count
322  a bit more as they get longer. However, above-average paths
323  still need to count less, hence the squaring of that factor. */
324  return (off + 1.0) / (weight_alts * weight_alts);
325 }
326 
327 
333 static void
334 destroy_peer (void *cls)
335 {
336  struct CadetPeer *cp = cls;
337 
339  "Destroying state about peer %s\n",
340  GCP_2s (cp));
341  cp->destroy_task = NULL;
342  GNUNET_assert (NULL == cp->t);
343  GNUNET_assert (NULL == cp->core_mq);
344  GNUNET_assert (0 == cp->num_paths);
345  for (unsigned int i=0;i<cp->path_dll_length;i++)
346  GNUNET_assert (NULL == cp->path_heads[i]);
350  &cp->pid,
351  cp));
354  cp->path_dll_length = 0;
355  if (NULL != cp->search_h)
356  {
358  cp->search_h = NULL;
359  }
360  /* FIXME: clean up search_delayedXXX! */
361 
362  if (NULL != cp->hello_offer)
363  {
365  cp->hello_offer = NULL;
366  }
367  if (NULL != cp->connectivity_suggestion)
368  {
370  cp->connectivity_suggestion = NULL;
371  }
373  if (NULL != cp->path_heap)
374  {
376  cp->path_heap = NULL;
377  }
378  if (NULL != cp->heap_cleanup_task)
379  {
381  cp->heap_cleanup_task = NULL;
382  }
384  /* Peer should not be freed if paths exist; if there are no paths,
385  there ought to be no connections, and without connections, no
386  notifications. Thus we can assert that mqm_head is empty at this
387  point. */
388  GNUNET_assert (NULL == cp->mqm_head);
389  GNUNET_assert (NULL == cp->mqm_ready_ptr);
390  GNUNET_free (cp);
391 }
392 
393 
399 static void
401 {
402  uint32_t strength;
403 
405  "Updating peer %s activation state (%u connections)%s%s\n",
406  GCP_2s (cp),
408  (NULL == cp->t) ? "" : " with tunnel",
409  (NULL == cp->core_mq) ? "" : " with CORE link");
410  if (NULL != cp->destroy_task)
411  {
412  /* It's active, do not destory! */
414  cp->destroy_task = NULL;
415  }
417  (NULL == cp->t) )
418  {
419  /* We're just on a path or directly connected; don't bother too much */
420  if (NULL != cp->connectivity_suggestion)
421  {
423  cp->connectivity_suggestion = NULL;
424  }
425  if (NULL != cp->search_h)
426  {
428  cp->search_h = NULL;
429  }
430  return;
431  }
432  if (NULL == cp->core_mq)
433  {
434  /* Lacks direct connection, try to create one by querying the DHT */
435  if ( (NULL == cp->search_h) &&
437  cp->search_h
438  = GCD_search (&cp->pid);
439  }
440  else
441  {
442  /* Have direct connection, stop DHT search if active */
443  if (NULL != cp->search_h)
444  {
446  cp->search_h = NULL;
447  }
448  }
449 
450  /* If we have a tunnel, our urge for connections is much bigger */
451  strength = (NULL != cp->t) ? 32 : 1;
452  if (NULL != cp->connectivity_suggestion)
456  &cp->pid,
457  strength);
458 }
459 
460 
466 static void
468 
469 
476 static void
477 drop_paths (void *cls)
478 {
479  struct CadetPeer *cp = cls;
480  struct CadetPeerPath *path;
481 
482  cp->destroy_task = NULL;
483  while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
484  GCPP_release (path);
486 }
487 
488 
494 static void
496 {
497  struct GNUNET_TIME_Relative exp;
498 
499  if (NULL != cp->destroy_task)
500  {
502  cp->destroy_task = NULL;
503  }
504  if (NULL != cp->t)
505  return; /* still relevant! */
506  if (NULL != cp->core_mq)
507  return; /* still relevant! */
509  return; /* still relevant! */
510  if ( (NULL != cp->path_heap) &&
512  {
514  &drop_paths,
515  cp);
516  return;
517  }
518  if (0 != cp->num_paths)
519  return; /* still relevant! */
520  if (NULL != cp->hello)
521  {
522  /* relevant only until HELLO expires */
525  &destroy_peer,
526  cp);
527  return;
528  }
530  &destroy_peer,
531  cp);
532 }
533 
534 
541 void
542 GCP_set_mq (struct CadetPeer *cp,
543  struct GNUNET_MQ_Handle *mq)
544 {
546  "Message queue for peer %s is now %p\n",
547  GCP_2s (cp),
548  mq);
549  cp->core_mq = mq;
550  for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
551  NULL != mqm;
552  mqm = next)
553  {
554  /* Save next pointer in case mqm gets freed by the callback */
555  next = mqm->next;
556  if (NULL == mq)
557  {
558  if (NULL != mqm->env)
559  {
560  GNUNET_MQ_discard (mqm->env);
561  mqm->env = NULL;
562  mqm->cb (mqm->cb_cls,
563  GNUNET_SYSERR);
564  }
565  else
566  {
567  mqm->cb (mqm->cb_cls,
568  GNUNET_NO);
569  }
570  }
571  else
572  {
573  GNUNET_assert (NULL == mqm->env);
574  mqm->cb (mqm->cb_cls,
575  GNUNET_YES);
576  }
577  }
578  if ( (NULL != mq) ||
579  (NULL != cp->t) )
581  else
583 
584  if ( (NULL != mq) &&
585  (NULL != cp->t) )
586  {
587  /* have a new, direct path to the target, notify tunnel */
588  struct CadetPeerPath *path;
589 
590  path = GCPP_get_path_from_route (1,
591  &cp->pid);
592  GCT_consider_path (cp->t,
593  path,
594  0);
595  }
596 }
597 
598 
605 static int
607 {
608  if (0 == drop_percent)
609  return GNUNET_NO;
611  101) < drop_percent)
612  return GNUNET_YES;
613  return GNUNET_NO;
614 }
615 
616 
623 static void
624 mqm_send_done (void *cls);
625 
626 
632 static void
634 {
635  struct CadetPeer *cp = mqm->cp;
636 
637  /* Move ready pointer to the next entry that might be ready. */
638  if ( (mqm == cp->mqm_ready_ptr) &&
639  (NULL != mqm->next) )
640  cp->mqm_ready_ptr = mqm->next;
641  /* Move entry to the end of the DLL, to be fair. */
642  if (mqm != cp->mqm_tail)
643  {
645  cp->mqm_tail,
646  mqm);
648  cp->mqm_tail,
649  mqm);
650  }
651  cp->mqm_ready_counter--;
652  if (GNUNET_YES == should_I_drop ())
653  {
655  "DROPPING message to peer %s from MQM %p\n",
656  GCP_2s (cp),
657  mqm);
658  GNUNET_MQ_discard (mqm->env);
659  mqm->env = NULL;
660  mqm_send_done (cp);
661  }
662  else
663  {
664  {
665  const struct GNUNET_MessageHeader *mh;
666 
667  mh = GNUNET_MQ_env_get_msg (mqm->env);
668  switch (ntohs (mh->type))
669  {
671  {
673  = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh;
675  "P2P forwarding KX with ephemeral %s to %s on CID %s\n",
676  GNUNET_e2s (&msg->ephemeral_key),
677  GCP_2s (cp),
679  }
680  break;
681  default:
682  break;
683  }
684  }
686  "Sending to peer %s from MQM %p\n",
687  GCP_2s (cp),
688  mqm);
689  GNUNET_MQ_send (cp->core_mq,
690  mqm->env);
691  mqm->env = NULL;
692  }
693  mqm->cb (mqm->cb_cls,
694  GNUNET_YES);
695 }
696 
697 
705 static void
707 {
708  struct GCP_MessageQueueManager *mqm;
709 
710  if (0 == cp->mqm_ready_counter)
711  return;
712  while ( (NULL != (mqm = cp->mqm_ready_ptr)) &&
713  (NULL == mqm->env) )
714  cp->mqm_ready_ptr = mqm->next;
715  if (NULL == mqm)
716  return; /* nothing to do */
717  mqm_execute (mqm);
718 }
719 
720 
727 static void
728 mqm_send_done (void *cls)
729 {
730  struct CadetPeer *cp = cls;
731 
733  "Sending to peer %s completed\n",
734  GCP_2s (cp));
735  send_next_ready (cp);
736 }
737 
738 
746 void
748  struct GNUNET_MQ_Envelope *env)
749 {
750  struct CadetPeer *cp = mqm->cp;
751 
752  GNUNET_assert (NULL != env);
754  "Queueing message to peer %s in MQM %p\n",
755  GCP_2s (cp),
756  mqm);
757  GNUNET_assert (NULL != cp->core_mq);
758  GNUNET_assert (NULL == mqm->env);
760  &mqm_send_done,
761  cp);
762  mqm->env = env;
763  cp->mqm_ready_counter++;
764  if (mqm != cp->mqm_ready_ptr)
765  cp->mqm_ready_ptr = cp->mqm_head;
766  if (1 == cp->mqm_ready_counter)
767  cp->mqm_ready_ptr = mqm;
768  if (0 != GNUNET_MQ_get_length (cp->core_mq))
769  return;
770  send_next_ready (cp);
771 }
772 
773 
782 static int
784  const struct GNUNET_PeerIdentity *pid,
785  void *value)
786 {
787  struct CadetPeer *cp = value;
788 
789  if (NULL != cp->destroy_task)
790  {
792  cp->destroy_task = NULL;
793  }
794  destroy_peer (cp);
795  return GNUNET_OK;
796 }
797 
798 
804 void
806 {
808  "Destroying all peers now\n");
811  NULL);
812 }
813 
814 
821 void
823 {
824  struct CadetPeerPath *path;
825 
827  "Destroying all paths to %s\n",
828  GCP_2s (cp));
829  while (NULL != (path =
831  GCPP_release (path);
833  cp->path_heap = NULL;
834 }
835 
836 
844 void
846  struct CadetPeerPathEntry *entry,
847  unsigned int off)
848 {
850  off));
852  "Discovered that peer %s is on path %s at offset %u\n",
853  GCP_2s (cp),
854  GCPP_2s (entry->path),
855  off);
856  if (off >= cp->path_dll_length)
857  {
858  unsigned int len = cp->path_dll_length;
859 
861  len,
862  off + 4);
864  cp->path_dll_length,
865  off + 4);
866  }
868  cp->path_tails[off],
869  entry);
870  cp->off_sum += off;
871  cp->num_paths++;
872 
873  /* If we have a tunnel to this peer, tell the tunnel that there is a
874  new path available. */
875  if (NULL != cp->t)
876  GCT_consider_path (cp->t,
877  entry->path,
878  off);
879 
880  if ( (NULL != cp->search_h) &&
881  (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
882  {
883  /* Now I have enough paths, stop search */
885  cp->search_h = NULL;
886  }
887  if (NULL != cp->destroy_task)
888  {
889  /* paths changed, this resets the destroy timeout counter
890  and aborts a destroy task that may no longer be valid
891  to have (as we now have more paths via this peer). */
893  }
894 }
895 
896 
904 void
906  struct CadetPeerPathEntry *entry,
907  unsigned int off)
908 {
910  "Removing knowledge about peer %s beging on path %s at offset %u\n",
911  GCP_2s (cp),
912  GCPP_2s (entry->path),
913  off);
915  cp->path_tails[off],
916  entry);
917  GNUNET_assert (0 < cp->num_paths);
918  cp->off_sum -= off;
919  cp->num_paths--;
920  if ( (NULL == cp->core_mq) &&
921  (NULL != cp->t) &&
922  (NULL == cp->search_h) &&
924  cp->search_h
925  = GCD_search (&cp->pid);
926  if (NULL == cp->destroy_task)
927  {
928  /* paths changed, we might now be ready for destruction, check again */
930  }
931 }
932 
933 
940 static void
941 path_heap_cleanup (void *cls)
942 {
943  struct CadetPeer *cp = cls;
944  struct CadetPeerPath *root;
945 
946  cp->heap_cleanup_task = NULL;
949  {
950  /* Now we have way too many, drop least desirable UNLESS it is in use!
951  (Note that this intentionally keeps highly desireable, but currently
952  unused paths around in the hope that we might be able to switch, even
953  if the number of paths exceeds the threshold.) */
955  GNUNET_assert (NULL != root);
956  if (NULL !=
957  GCPP_get_connection (root,
958  cp,
959  GCPP_get_length (root) - 1))
960  break; /* can't fix */
961  /* Got plenty of paths to this destination, and this is a low-quality
962  one that we don't care about. Allow it to die. */
963  GNUNET_assert (root ==
965  GCPP_release (root);
966  }
967 }
968 
969 
983  struct CadetPeerPath *path,
984  unsigned int off,
985  int force)
986 {
987  GNUNET_CONTAINER_HeapCostType desirability;
988  struct CadetPeerPath *root;
989  GNUNET_CONTAINER_HeapCostType root_desirability;
990  struct GNUNET_CONTAINER_HeapNode *hn;
991 
992  GNUNET_assert (off == GCPP_get_length (path) - 1);
994  off));
995  if (NULL == cp->path_heap)
996  {
997  /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
998  GNUNET_assert (GNUNET_NO == force);
999  return NULL;
1000  }
1001  desirability = GCPP_get_desirability (path);
1002  if (GNUNET_NO == force)
1003  {
1004  /* FIXME: desirability is not yet initialized; tricky! */
1005  if (GNUNET_NO ==
1007  (void **) &root,
1008  &root_desirability))
1009  {
1010  root = NULL;
1011  root_desirability = 0;
1012  }
1013 
1015  (desirability < root_desirability) )
1016  {
1018  "Decided to not attach path %s to peer %s due to undesirability\n",
1019  GCPP_2s (path),
1020  GCP_2s (cp));
1021  return NULL;
1022  }
1023  }
1024 
1026  "Attaching path %s to peer %s (%s)\n",
1027  GCPP_2s (path),
1028  GCP_2s (cp),
1029  (GNUNET_NO == force) ? "desirable" : "forced");
1030 
1031  /* Yes, we'd like to add this path, add to our heap */
1033  path,
1034  desirability);
1035 
1036  /* Consider maybe dropping other paths because of the new one */
1039  (NULL != cp->heap_cleanup_task) )
1041  cp);
1042  return hn;
1043 }
1044 
1045 
1055 void
1057  struct CadetPeerPath *path,
1058  struct GNUNET_CONTAINER_HeapNode *hn)
1059 {
1061  "Detatching path %s from peer %s\n",
1062  GCPP_2s (path),
1063  GCP_2s (cp));
1064  GNUNET_assert (path ==
1066 }
1067 
1068 
1075 void
1077  struct CadetConnection *cc)
1078 {
1080  "Adding %s to peer %s\n",
1081  GCC_2s (cc),
1082  GCP_2s (cp));
1085  &GCC_get_id (cc)->connection_of_tunnel,
1086  cc,
1088  if (NULL != cp->destroy_task)
1089  {
1091  cp->destroy_task = NULL;
1092  }
1093 }
1094 
1095 
1102 void
1104  struct CadetConnection *cc)
1105 {
1107  "Removing connection %s from peer %s\n",
1108  GCC_2s (cc),
1109  GCP_2s (cp));
1112  &GCC_get_id (cc)->connection_of_tunnel,
1113  cc));
1114  consider_peer_destroy (cp);
1115 }
1116 
1117 
1129 struct CadetPeer *
1131  int create)
1132 {
1133  struct CadetPeer *cp;
1134 
1136  peer_id);
1137  if (NULL != cp)
1138  return cp;
1139  if (GNUNET_NO == create)
1140  return NULL;
1141  cp = GNUNET_new (struct CadetPeer);
1142  cp->pid = *peer_id;
1144  GNUNET_YES);
1148  &cp->pid,
1149  cp,
1152  "Creating peer %s\n",
1153  GCP_2s (cp));
1154  return cp;
1155 }
1156 
1157 
1164 const struct GNUNET_PeerIdentity *
1165 GCP_get_id (struct CadetPeer *cp)
1166 {
1167  return &cp->pid;
1168 }
1169 
1170 
1177 void
1179  void *cls)
1180 {
1182  iter,
1183  cls);
1184 }
1185 
1186 
1193 unsigned int
1194 GCP_count_paths (const struct CadetPeer *cp)
1195 {
1196  return cp->num_paths;
1197 }
1198 
1199 
1208 unsigned int
1210  GCP_PathIterator callback,
1211  void *callback_cls)
1212 {
1213  unsigned int ret = 0;
1214 
1216  "Iterating over paths to peer %s%s\n",
1217  GCP_2s (cp),
1218  (NULL == cp->core_mq) ? "" : " including direct link");
1219  if (NULL != cp->core_mq)
1220  {
1221  /* FIXME: this branch seems to duplicate the
1222  i=0 case below (direct link). Leave out!??? -CG */
1223  struct CadetPeerPath *path;
1224 
1225  path = GCPP_get_path_from_route (1,
1226  &cp->pid);
1227  ret++;
1228  if (GNUNET_NO ==
1229  callback (callback_cls,
1230  path,
1231  0))
1232  return ret;
1233  }
1234  for (unsigned int i=0;i<cp->path_dll_length;i++)
1235  {
1236  for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1237  NULL != pe;
1238  pe = pe->next)
1239  {
1240  ret++;
1241  if (GNUNET_NO ==
1242  callback (callback_cls,
1243  pe->path,
1244  i))
1245  return ret;
1246  }
1247  }
1248  return ret;
1249 }
1250 
1259 unsigned int
1261  GCP_PathIterator callback,
1262  void *callback_cls)
1263 {
1264  unsigned int ret = 0;
1265 
1267  "Iterating over paths to peer %s without direct link\n",
1268  GCP_2s (cp));
1269  for (unsigned int i=1;i<cp->path_dll_length;i++)
1270  {
1271  for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1272  NULL != pe;
1273  pe = pe->next)
1274  {
1275  ret++;
1276  if (GNUNET_NO ==
1277  callback (callback_cls,
1278  pe->path,
1279  i))
1280  return ret;
1281  }
1282  }
1283  return ret;
1284 }
1285 
1286 
1297 unsigned int
1299  unsigned int dist,
1300  GCP_PathIterator callback,
1301  void *callback_cls)
1302 {
1303  unsigned int ret = 0;
1304 
1305  if (dist >= cp->path_dll_length)
1306  {
1308  "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1309  dist,
1310  cp->path_dll_length);
1311  return 0;
1312  }
1313  for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1314  NULL != pe;
1315  pe = pe->next)
1316  {
1317  if (GNUNET_NO ==
1318  callback (callback_cls,
1319  pe->path,
1320  dist))
1321  return ret;
1322  ret++;
1323  }
1324  return ret;
1325 }
1326 
1327 
1335 struct CadetTunnel *
1337  int create)
1338 {
1339  if (NULL == cp)
1340  return NULL;
1341  if ( (NULL != cp->t) ||
1342  (GNUNET_NO == create) )
1343  return cp->t;
1344  cp->t = GCT_create_tunnel (cp);
1346  return cp->t;
1347 }
1348 
1349 
1356 static void
1357 hello_offer_done (void *cls)
1358 {
1359  struct CadetPeer *cp = cls;
1360 
1361  cp->hello_offer = NULL;
1362 }
1363 
1364 
1372 void
1374  const struct GNUNET_HELLO_Message *hello)
1375 {
1376  struct GNUNET_HELLO_Message *mrg;
1377 
1379  "Got %u byte HELLO for peer %s\n",
1380  (unsigned int) GNUNET_HELLO_size (hello),
1381  GCP_2s (cp));
1382  if (NULL != cp->hello_offer)
1383  {
1385  cp->hello_offer = NULL;
1386  }
1387  if (NULL != cp->hello)
1388  {
1389  mrg = GNUNET_HELLO_merge (hello,
1390  cp->hello);
1391  GNUNET_free (cp->hello);
1392  cp->hello = mrg;
1393  }
1394  else
1395  {
1396  cp->hello = GNUNET_memdup (hello,
1397  GNUNET_HELLO_size (hello));
1398  }
1399  cp->hello_offer
1403  cp);
1404  /* New HELLO means cp's destruction time may change... */
1405  consider_peer_destroy (cp);
1406 }
1407 
1408 
1416 void
1418  struct CadetTunnel *t)
1419 {
1421  "Dropping tunnel %s to peer %s\n",
1422  GCT_2s (t),
1423  GCP_2s (cp));
1424  GNUNET_assert (cp->t == t);
1425  cp->t = NULL;
1426  consider_peer_destroy (cp);
1427 }
1428 
1429 
1436 int
1438 {
1439  return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1440 }
1441 
1442 
1451 struct GCP_MessageQueueManager *
1454  void *cb_cls)
1455 {
1456  struct GCP_MessageQueueManager *mqm;
1457 
1458  mqm = GNUNET_new (struct GCP_MessageQueueManager);
1459  mqm->cb = cb;
1460  mqm->cb_cls = cb_cls;
1461  mqm->cp = cp;
1463  cp->mqm_tail,
1464  mqm);
1466  "Creating MQM %p for peer %s\n",
1467  mqm,
1468  GCP_2s (cp));
1469  if (NULL != cp->core_mq)
1470  cb (cb_cls,
1471  GNUNET_YES);
1472  return mqm;
1473 }
1474 
1475 
1482 void
1484  struct GNUNET_MQ_Envelope *last_env)
1485 {
1486  struct CadetPeer *cp = mqm->cp;
1487 
1489  "Destroying MQM %p for peer %s%s\n",
1490  mqm,
1491  GCP_2s (cp),
1492  (NULL == last_env) ? "" : " with last ditch transmission");
1493  if (NULL != mqm->env)
1494  GNUNET_MQ_discard (mqm->env);
1495  if (NULL != last_env)
1496  {
1497  if (NULL != cp->core_mq)
1498  {
1499  GNUNET_MQ_notify_sent (last_env,
1500  &mqm_send_done,
1501  cp);
1502  GNUNET_MQ_send (cp->core_mq,
1503  last_env);
1504  }
1505  else
1506  {
1507  GNUNET_MQ_discard (last_env);
1508  }
1509  }
1510  if (cp->mqm_ready_ptr == mqm)
1511  cp->mqm_ready_ptr = mqm->next;
1513  cp->mqm_tail,
1514  mqm);
1515  GNUNET_free (mqm);
1516 }
1517 
1518 
1528 void
1530  struct GNUNET_MQ_Envelope *env)
1531 {
1533  "Sending message to %s out of management\n",
1534  GCP_2s (cp));
1535  if (NULL == cp->core_mq)
1536  {
1537  GNUNET_MQ_discard (env);
1538  return;
1539  }
1541  {
1542  GNUNET_MQ_discard (env);
1543  return;
1544  }
1545  GNUNET_MQ_notify_sent (env,
1546  &mqm_send_done,
1547  cp);
1548  GNUNET_MQ_send (cp->core_mq,
1549  env);
1550 }
1551 
1552 
1553 
1554 
1555 /* 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.
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.
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:81
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:78
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:690
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:1246
#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:367
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:1273
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
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
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:79
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.
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:649
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: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
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:890
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.
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:965
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.