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 
77 
82 
87 
91  void *cb_cls;
92 
96  struct CadetPeer *cp;
97 
102 };
103 
104 
108 struct CadetPeer {
113 
117  struct GNUNET_TIME_Absolute last_contactXXX;
118 
124 
130 
135 
140 
145 
151 
156 
161 
166 
170  struct CadetTunnel *t;
171 
176 
181 
186 
191 
197 
201  unsigned int queue_n;
202 
206  unsigned int num_paths;
207 
212  unsigned int off_sum;
213 
221  unsigned int mqm_ready_counter;
222 
227  unsigned int path_dll_length;
228 };
229 
230 
237 const char *
238 GCP_2s(const struct CadetPeer *cp)
239 {
240  static char buf[5];
241  char *ret;
242 
243  if ((NULL == cp) ||
244  (0 == GNUNET_is_zero(&cp->pid.public_key)))
245  return "NULL";
246 
248  if (NULL == ret)
249  return "NULL";
250 
251  GNUNET_strlcpy(buf,
252  ret,
253  sizeof(buf));
254  GNUNET_free(ret);
255  return buf;
256 }
257 
258 
274 double
276  unsigned int off)
277 {
278  unsigned int num_alts = cp->num_paths;
279  unsigned int off_sum;
280  double avg_sum;
281  double path_delta;
282  double weight_alts;
283 
284  GNUNET_assert(num_alts >= 1); /* 'path' should be in there! */
285  GNUNET_assert(0 != cp->path_dll_length);
286 
287  /* We maintain 'off_sum' in 'peer' and thereby
288  avoid the SLOW recalculation each time. Kept here
289  just to document what is going on. */
290 #if SLOW
291  off_sum = 0;
292  for (unsigned int j = 0; j < cp->path_dll_length; j++)
293  for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
294  NULL != pe;
295  pe = pe->next)
296  off_sum += j;
297  GNUNET_assert(off_sum == cp->off_sum);
298 #else
299  off_sum = cp->off_sum;
300 #endif
301  avg_sum = off_sum * 1.0 / cp->path_dll_length;
302  path_delta = off - avg_sum;
303  /* path_delta positiv: path off of peer above average (bad path for peer),
304  path_delta negativ: path off of peer below average (good path for peer) */
305  if (path_delta <= -1.0)
306  weight_alts = -num_alts / path_delta; /* discount alternative paths */
307  else if (path_delta >= 1.0)
308  weight_alts = num_alts * path_delta; /* overcount alternative paths */
309  else
310  weight_alts = num_alts; /* count alternative paths normally */
311 
312 
313  /* off+1: long paths are generally harder to find and thus count
314  a bit more as they get longer. However, above-average paths
315  still need to count less, hence the squaring of that factor. */
316  return (off + 1.0) / (weight_alts * weight_alts);
317 }
318 
319 
325 static void
326 destroy_peer(void *cls)
327 {
328  struct CadetPeer *cp = cls;
329 
331  "Destroying state about peer %s\n",
332  GCP_2s(cp));
333  cp->destroy_task = NULL;
334  GNUNET_assert(NULL == cp->t);
335  GNUNET_assert(NULL == cp->core_mq);
336  GNUNET_assert(0 == cp->num_paths);
337  for (unsigned int i = 0; i < cp->path_dll_length; i++)
338  GNUNET_assert(NULL == cp->path_heads[i]);
342  &cp->pid,
343  cp));
346  cp->path_dll_length = 0;
347  if (NULL != cp->search_h)
348  {
350  cp->search_h = NULL;
351  }
352  /* FIXME: clean up search_delayedXXX! */
353 
354  if (NULL != cp->hello_offer)
355  {
357  cp->hello_offer = NULL;
358  }
359  if (NULL != cp->connectivity_suggestion)
360  {
362  cp->connectivity_suggestion = NULL;
363  }
365  if (NULL != cp->path_heap)
366  {
368  cp->path_heap = NULL;
369  }
370  if (NULL != cp->heap_cleanup_task)
371  {
373  cp->heap_cleanup_task = NULL;
374  }
376  /* Peer should not be freed if paths exist; if there are no paths,
377  there ought to be no connections, and without connections, no
378  notifications. Thus we can assert that mqm_head is empty at this
379  point. */
380  GNUNET_assert(NULL == cp->mqm_head);
381  GNUNET_assert(NULL == cp->mqm_ready_ptr);
382  GNUNET_free(cp);
383 }
384 
385 
391 static void
393 {
394  uint32_t strength;
395 
397  "Updating peer %s activation state (%u connections)%s%s\n",
398  GCP_2s(cp),
400  (NULL == cp->t) ? "" : " with tunnel",
401  (NULL == cp->core_mq) ? "" : " with CORE link");
402  if (NULL != cp->destroy_task)
403  {
404  /* It's active, do not destory! */
406  cp->destroy_task = NULL;
407  }
409  (NULL == cp->t))
410  {
411  /* We're just on a path or directly connected; don't bother too much */
412  if (NULL != cp->connectivity_suggestion)
413  {
415  cp->connectivity_suggestion = NULL;
416  }
417  if (NULL != cp->search_h)
418  {
420  cp->search_h = NULL;
421  }
422  return;
423  }
424  if (NULL == cp->core_mq)
425  {
426  /* Lacks direct connection, try to create one by querying the DHT */
427  if ((NULL == cp->search_h) &&
429  cp->search_h
430  = GCD_search(&cp->pid);
431  }
432  else
433  {
434  /* Have direct connection, stop DHT search if active */
435  if (NULL != cp->search_h)
436  {
438  cp->search_h = NULL;
439  }
440  }
441 
442  /* If we have a tunnel, our urge for connections is much bigger */
443  strength = (NULL != cp->t) ? 32 : 1;
444  if (NULL != cp->connectivity_suggestion)
448  &cp->pid,
449  strength);
450 }
451 
452 
458 static void
460 
461 
468 static void
469 drop_paths(void *cls)
470 {
471  struct CadetPeer *cp = cls;
472  struct CadetPeerPath *path;
473 
474  cp->destroy_task = NULL;
475  while (NULL != (path = GNUNET_CONTAINER_heap_remove_root(cp->path_heap)))
476  GCPP_release(path);
478 }
479 
480 
486 static void
488 {
489  struct GNUNET_TIME_Relative exp;
490 
491  if (NULL != cp->destroy_task)
492  {
494  cp->destroy_task = NULL;
495  }
496  if (NULL != cp->t)
497  return; /* still relevant! */
498  if (NULL != cp->core_mq)
499  return; /* still relevant! */
501  return; /* still relevant! */
502  if ((NULL != cp->path_heap) &&
504  {
506  &drop_paths,
507  cp);
508  return;
509  }
510  if (0 != cp->num_paths)
511  return; /* still relevant! */
512  if (NULL != cp->hello)
513  {
514  /* relevant only until HELLO expires */
517  &destroy_peer,
518  cp);
519  return;
520  }
522  &destroy_peer,
523  cp);
524 }
525 
526 
533 void
535  struct GNUNET_MQ_Handle *mq)
536 {
538  "Message queue for peer %s is now %p\n",
539  GCP_2s(cp),
540  mq);
541  cp->core_mq = mq;
542  for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
543  NULL != mqm;
544  mqm = next)
545  {
546  /* Save next pointer in case mqm gets freed by the callback */
547  next = mqm->next;
548  if (NULL == mq)
549  {
550  if (NULL != mqm->env)
551  {
552  GNUNET_MQ_discard(mqm->env);
553  mqm->env = NULL;
554  mqm->cb(mqm->cb_cls,
555  GNUNET_SYSERR);
556  }
557  else
558  {
559  mqm->cb(mqm->cb_cls,
560  GNUNET_NO);
561  }
562  }
563  else
564  {
565  GNUNET_assert(NULL == mqm->env);
566  mqm->cb(mqm->cb_cls,
567  GNUNET_YES);
568  }
569  }
570  if ((NULL != mq) ||
571  (NULL != cp->t))
573  else
575 
576  if ((NULL != mq) &&
577  (NULL != cp->t))
578  {
579  /* have a new, direct path to the target, notify tunnel */
580  struct CadetPeerPath *path;
581 
582  path = GCPP_get_path_from_route(1,
583  &cp->pid);
584  GCT_consider_path(cp->t,
585  path,
586  0);
587  }
588 }
589 
590 
597 static int
599 {
600  if (0 == drop_percent)
601  return GNUNET_NO;
603  101) < drop_percent)
604  return GNUNET_YES;
605  return GNUNET_NO;
606 }
607 
608 
615 static void
616 mqm_send_done(void *cls);
617 
618 
624 static void
626 {
627  struct CadetPeer *cp = mqm->cp;
628 
629  /* Move ready pointer to the next entry that might be ready. */
630  if ((mqm == cp->mqm_ready_ptr) &&
631  (NULL != mqm->next))
632  cp->mqm_ready_ptr = mqm->next;
633  /* Move entry to the end of the DLL, to be fair. */
634  if (mqm != cp->mqm_tail)
635  {
637  cp->mqm_tail,
638  mqm);
640  cp->mqm_tail,
641  mqm);
642  }
643  cp->mqm_ready_counter--;
644  if (GNUNET_YES == should_I_drop())
645  {
647  "DROPPING message to peer %s from MQM %p\n",
648  GCP_2s(cp),
649  mqm);
650  GNUNET_MQ_discard(mqm->env);
651  mqm->env = NULL;
652  mqm_send_done(cp);
653  }
654  else
655  {
656  {
657  const struct GNUNET_MessageHeader *mh;
658 
659  mh = GNUNET_MQ_env_get_msg(mqm->env);
660  switch (ntohs(mh->type))
661  {
663  {
665  = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *)mh;
667  "P2P forwarding KX with ephemeral %s to %s on CID %s\n",
668  GNUNET_e2s(&msg->ephemeral_key),
669  GCP_2s(cp),
671  }
672  break;
673 
674  default:
675  break;
676  }
677  }
679  "Sending to peer %s from MQM %p\n",
680  GCP_2s(cp),
681  mqm);
683  mqm->env);
684  mqm->env = NULL;
685  }
686  mqm->cb(mqm->cb_cls,
687  GNUNET_YES);
688 }
689 
690 
698 static void
700 {
701  struct GCP_MessageQueueManager *mqm;
702 
703  if (0 == cp->mqm_ready_counter)
704  return;
705  while ((NULL != (mqm = cp->mqm_ready_ptr)) &&
706  (NULL == mqm->env))
707  cp->mqm_ready_ptr = mqm->next;
708  if (NULL == mqm)
709  return; /* nothing to do */
710  mqm_execute(mqm);
711 }
712 
713 
720 static void
721 mqm_send_done(void *cls)
722 {
723  struct CadetPeer *cp = cls;
724 
726  "Sending to peer %s completed\n",
727  GCP_2s(cp));
728  send_next_ready(cp);
729 }
730 
731 
739 void
741  struct GNUNET_MQ_Envelope *env)
742 {
743  struct CadetPeer *cp = mqm->cp;
744 
745  GNUNET_assert(NULL != env);
747  "Queueing message to peer %s in MQM %p\n",
748  GCP_2s(cp),
749  mqm);
750  GNUNET_assert(NULL != cp->core_mq);
751  GNUNET_assert(NULL == mqm->env);
753  &mqm_send_done,
754  cp);
755  mqm->env = env;
756  cp->mqm_ready_counter++;
757  if (mqm != cp->mqm_ready_ptr)
758  cp->mqm_ready_ptr = cp->mqm_head;
759  if (1 == cp->mqm_ready_counter)
760  cp->mqm_ready_ptr = mqm;
761  if (0 != GNUNET_MQ_get_length(cp->core_mq))
762  return;
763  send_next_ready(cp);
764 }
765 
766 
775 static int
777  const struct GNUNET_PeerIdentity *pid,
778  void *value)
779 {
780  struct CadetPeer *cp = value;
781 
782  if (NULL != cp->destroy_task)
783  {
785  cp->destroy_task = NULL;
786  }
787  destroy_peer(cp);
788  return GNUNET_OK;
789 }
790 
791 
797 void
799 {
801  "Destroying all peers now\n");
804  NULL);
805 }
806 
807 
814 void
816 {
817  struct CadetPeerPath *path;
818 
820  "Destroying all paths to %s\n",
821  GCP_2s(cp));
822  while (NULL != (path =
824  GCPP_release(path);
826  cp->path_heap = NULL;
827 }
828 
829 
837 void
839  struct CadetPeerPathEntry *entry,
840  unsigned int off)
841 {
843  off));
845  "Discovered that peer %s is on path %s at offset %u\n",
846  GCP_2s(cp),
847  GCPP_2s(entry->path),
848  off);
849  if (off >= cp->path_dll_length)
850  {
851  unsigned int len = cp->path_dll_length;
852 
854  len,
855  off + 4);
857  cp->path_dll_length,
858  off + 4);
859  }
861  cp->path_tails[off],
862  entry);
863  cp->off_sum += off;
864  cp->num_paths++;
865 
866  /* If we have a tunnel to this peer, tell the tunnel that there is a
867  new path available. */
868  if (NULL != cp->t)
869  GCT_consider_path(cp->t,
870  entry->path,
871  off);
872 
873  if ((NULL != cp->search_h) &&
874  (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths))
875  {
876  /* Now I have enough paths, stop search */
878  cp->search_h = NULL;
879  }
880  if (NULL != cp->destroy_task)
881  {
882  /* paths changed, this resets the destroy timeout counter
883  and aborts a destroy task that may no longer be valid
884  to have (as we now have more paths via this peer). */
886  }
887 }
888 
889 
897 void
899  struct CadetPeerPathEntry *entry,
900  unsigned int off)
901 {
903  "Removing knowledge about peer %s beging on path %s at offset %u\n",
904  GCP_2s(cp),
905  GCPP_2s(entry->path),
906  off);
908  cp->path_tails[off],
909  entry);
910  GNUNET_assert(0 < cp->num_paths);
911  cp->off_sum -= off;
912  cp->num_paths--;
913  if ((NULL == cp->core_mq) &&
914  (NULL != cp->t) &&
915  (NULL == cp->search_h) &&
917  cp->search_h
918  = GCD_search(&cp->pid);
919  if (NULL == cp->destroy_task)
920  {
921  /* paths changed, we might now be ready for destruction, check again */
923  }
924 }
925 
926 
933 static void
935 {
936  struct CadetPeer *cp = cls;
937  struct CadetPeerPath *root;
938 
939  cp->heap_cleanup_task = NULL;
942  {
943  /* Now we have way too many, drop least desirable UNLESS it is in use!
944  (Note that this intentionally keeps highly desireable, but currently
945  unused paths around in the hope that we might be able to switch, even
946  if the number of paths exceeds the threshold.) */
948  GNUNET_assert(NULL != root);
949  if (NULL !=
950  GCPP_get_connection(root,
951  cp,
952  GCPP_get_length(root) - 1))
953  break; /* can't fix */
954  /* Got plenty of paths to this destination, and this is a low-quality
955  one that we don't care about. Allow it to die. */
956  GNUNET_assert(root ==
958  GCPP_release(root);
959  }
960 }
961 
962 
976  struct CadetPeerPath *path,
977  unsigned int off,
978  int force)
979 {
980  GNUNET_CONTAINER_HeapCostType desirability;
981  struct CadetPeerPath *root;
982  GNUNET_CONTAINER_HeapCostType root_desirability;
983  struct GNUNET_CONTAINER_HeapNode *hn;
984 
985  GNUNET_assert(off == GCPP_get_length(path) - 1);
987  off));
988  if (NULL == cp->path_heap)
989  {
990  /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
991  GNUNET_assert(GNUNET_NO == force);
992  return NULL;
993  }
994  desirability = GCPP_get_desirability(path);
995  if (GNUNET_NO == force)
996  {
997  /* FIXME: desirability is not yet initialized; tricky! */
998  if (GNUNET_NO ==
1000  (void **)&root,
1001  &root_desirability))
1002  {
1003  root = NULL;
1004  root_desirability = 0;
1005  }
1006 
1008  (desirability < root_desirability))
1009  {
1011  "Decided to not attach path %s to peer %s due to undesirability\n",
1012  GCPP_2s(path),
1013  GCP_2s(cp));
1014  return NULL;
1015  }
1016  }
1017 
1019  "Attaching path %s to peer %s (%s)\n",
1020  GCPP_2s(path),
1021  GCP_2s(cp),
1022  (GNUNET_NO == force) ? "desirable" : "forced");
1023 
1024  /* Yes, we'd like to add this path, add to our heap */
1026  path,
1027  desirability);
1028 
1029  /* Consider maybe dropping other paths because of the new one */
1032  (NULL != cp->heap_cleanup_task))
1034  cp);
1035  return hn;
1036 }
1037 
1038 
1048 void
1050  struct CadetPeerPath *path,
1051  struct GNUNET_CONTAINER_HeapNode *hn)
1052 {
1054  "Detatching path %s from peer %s\n",
1055  GCPP_2s(path),
1056  GCP_2s(cp));
1057  GNUNET_assert(path ==
1059 }
1060 
1061 
1068 void
1070  struct CadetConnection *cc)
1071 {
1073  "Adding %s to peer %s\n",
1074  GCC_2s(cc),
1075  GCP_2s(cp));
1078  &GCC_get_id(cc)->connection_of_tunnel,
1079  cc,
1081  if (NULL != cp->destroy_task)
1082  {
1084  cp->destroy_task = NULL;
1085  }
1086 }
1087 
1088 
1095 void
1097  struct CadetConnection *cc)
1098 {
1100  "Removing connection %s from peer %s\n",
1101  GCC_2s(cc),
1102  GCP_2s(cp));
1105  &GCC_get_id(cc)->connection_of_tunnel,
1106  cc));
1108 }
1109 
1110 
1122 struct CadetPeer *
1124  int create)
1125 {
1126  struct CadetPeer *cp;
1127 
1129  peer_id);
1130  if (NULL != cp)
1131  return cp;
1132  if (GNUNET_NO == create)
1133  return NULL;
1134  cp = GNUNET_new(struct CadetPeer);
1135  cp->pid = *peer_id;
1137  GNUNET_YES);
1141  &cp->pid,
1142  cp,
1145  "Creating peer %s\n",
1146  GCP_2s(cp));
1147  return cp;
1148 }
1149 
1150 
1157 const struct GNUNET_PeerIdentity *
1159 {
1160  return &cp->pid;
1161 }
1162 
1163 
1170 void
1172  void *cls)
1173 {
1175  iter,
1176  cls);
1177 }
1178 
1179 
1186 unsigned int
1187 GCP_count_paths(const struct CadetPeer *cp)
1188 {
1189  return cp->num_paths;
1190 }
1191 
1192 
1201 unsigned int
1203  GCP_PathIterator callback,
1204  void *callback_cls)
1205 {
1206  unsigned int ret = 0;
1207 
1209  "Iterating over paths to peer %s%s\n",
1210  GCP_2s(cp),
1211  (NULL == cp->core_mq) ? "" : " including direct link");
1212  if (NULL != cp->core_mq)
1213  {
1214  /* FIXME: this branch seems to duplicate the
1215  i=0 case below (direct link). Leave out!??? -CG */
1216  struct CadetPeerPath *path;
1217 
1218  path = GCPP_get_path_from_route(1,
1219  &cp->pid);
1220  ret++;
1221  if (GNUNET_NO ==
1222  callback(callback_cls,
1223  path,
1224  0))
1225  return ret;
1226  }
1227  for (unsigned int i = 0; i < cp->path_dll_length; i++)
1228  {
1229  for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1230  NULL != pe;
1231  pe = pe->next)
1232  {
1233  ret++;
1234  if (GNUNET_NO ==
1235  callback(callback_cls,
1236  pe->path,
1237  i))
1238  return ret;
1239  }
1240  }
1241  return ret;
1242 }
1243 
1252 unsigned int
1254  GCP_PathIterator callback,
1255  void *callback_cls)
1256 {
1257  unsigned int ret = 0;
1258 
1260  "Iterating over paths to peer %s without direct link\n",
1261  GCP_2s(cp));
1262  for (unsigned int i = 1; i < cp->path_dll_length; i++)
1263  {
1264  for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1265  NULL != pe;
1266  pe = pe->next)
1267  {
1268  ret++;
1269  if (GNUNET_NO ==
1270  callback(callback_cls,
1271  pe->path,
1272  i))
1273  return ret;
1274  }
1275  }
1276  return ret;
1277 }
1278 
1279 
1290 unsigned int
1292  unsigned int dist,
1293  GCP_PathIterator callback,
1294  void *callback_cls)
1295 {
1296  unsigned int ret = 0;
1297 
1298  if (dist >= cp->path_dll_length)
1299  {
1301  "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1302  dist,
1303  cp->path_dll_length);
1304  return 0;
1305  }
1306  for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1307  NULL != pe;
1308  pe = pe->next)
1309  {
1310  if (GNUNET_NO ==
1311  callback(callback_cls,
1312  pe->path,
1313  dist))
1314  return ret;
1315  ret++;
1316  }
1317  return ret;
1318 }
1319 
1320 
1328 struct CadetTunnel *
1330  int create)
1331 {
1332  if (NULL == cp)
1333  return NULL;
1334  if ((NULL != cp->t) ||
1335  (GNUNET_NO == create))
1336  return cp->t;
1337  cp->t = GCT_create_tunnel(cp);
1339  return cp->t;
1340 }
1341 
1342 
1349 static void
1351 {
1352  struct CadetPeer *cp = cls;
1353 
1354  cp->hello_offer = NULL;
1355 }
1356 
1357 
1365 void
1367  const struct GNUNET_HELLO_Message *hello)
1368 {
1369  struct GNUNET_HELLO_Message *mrg;
1370 
1372  "Got %u byte HELLO for peer %s\n",
1373  (unsigned int)GNUNET_HELLO_size(hello),
1374  GCP_2s(cp));
1375  if (NULL != cp->hello_offer)
1376  {
1378  cp->hello_offer = NULL;
1379  }
1380  if (NULL != cp->hello)
1381  {
1382  mrg = GNUNET_HELLO_merge(hello,
1383  cp->hello);
1384  GNUNET_free(cp->hello);
1385  cp->hello = mrg;
1386  }
1387  else
1388  {
1389  cp->hello = GNUNET_memdup(hello,
1390  GNUNET_HELLO_size(hello));
1391  }
1392  cp->hello_offer
1396  cp);
1397  /* New HELLO means cp's destruction time may change... */
1399 }
1400 
1401 
1409 void
1411  struct CadetTunnel *t)
1412 {
1414  "Dropping tunnel %s to peer %s\n",
1415  GCT_2s(t),
1416  GCP_2s(cp));
1417  GNUNET_assert(cp->t == t);
1418  cp->t = NULL;
1420 }
1421 
1422 
1429 int
1431 {
1432  return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1433 }
1434 
1435 
1444 struct GCP_MessageQueueManager *
1447  void *cb_cls)
1448 {
1449  struct GCP_MessageQueueManager *mqm;
1450 
1451  mqm = GNUNET_new(struct GCP_MessageQueueManager);
1452  mqm->cb = cb;
1453  mqm->cb_cls = cb_cls;
1454  mqm->cp = cp;
1456  cp->mqm_tail,
1457  mqm);
1459  "Creating MQM %p for peer %s\n",
1460  mqm,
1461  GCP_2s(cp));
1462  if (NULL != cp->core_mq)
1463  cb(cb_cls,
1464  GNUNET_YES);
1465  return mqm;
1466 }
1467 
1468 
1475 void
1477  struct GNUNET_MQ_Envelope *last_env)
1478 {
1479  struct CadetPeer *cp = mqm->cp;
1480 
1482  "Destroying MQM %p for peer %s%s\n",
1483  mqm,
1484  GCP_2s(cp),
1485  (NULL == last_env) ? "" : " with last ditch transmission");
1486  if (NULL != mqm->env)
1487  GNUNET_MQ_discard(mqm->env);
1488  if (NULL != last_env)
1489  {
1490  if (NULL != cp->core_mq)
1491  {
1492  GNUNET_MQ_notify_sent(last_env,
1493  &mqm_send_done,
1494  cp);
1495  GNUNET_MQ_send(cp->core_mq,
1496  last_env);
1497  }
1498  else
1499  {
1500  GNUNET_MQ_discard(last_env);
1501  }
1502  }
1503  if (cp->mqm_ready_ptr == mqm)
1504  cp->mqm_ready_ptr = mqm->next;
1506  cp->mqm_tail,
1507  mqm);
1508  GNUNET_free(mqm);
1509 }
1510 
1511 
1521 void
1523  struct GNUNET_MQ_Envelope *env)
1524 {
1526  "Sending message to %s out of management\n",
1527  GCP_2s(cp));
1528  if (NULL == cp->core_mq)
1529  {
1530  GNUNET_MQ_discard(env);
1531  return;
1532  }
1534  {
1535  GNUNET_MQ_discard(env);
1536  return;
1537  }
1539  &mqm_send_done,
1540  cp);
1541  GNUNET_MQ_send(cp->core_mq,
1542  env);
1543 }
1544 
1545 
1546 
1547 
1548 /* 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:1077
#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:519
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: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:684
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:1237
#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:772
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:333
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:1264
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:319
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: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:84
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:131
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:643
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:351
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:882
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:956
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.