GNUnet 0.21.2
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_time_lib.h"
35#include "gnunet_util_lib.h"
37#include "gnunet_signatures.h"
39#include "gnunet_core_service.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
74{
79
84
89
93 void *cb_cls;
94
98 struct CadetPeer *cp;
99
104};
105
106
111{
116
121
127
133
138
143
148
154
159
164
169
173 struct CadetTunnel *t;
174
179
184
189
193 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
194
199
203 unsigned int queue_n;
204
208 unsigned int num_paths;
209
214 unsigned int off_sum;
215
223 unsigned int mqm_ready_counter;
224
229 unsigned int path_dll_length;
230};
231
232
233const char *
234GCP_2s (const struct CadetPeer *cp)
235{
236 static char buf[5];
237 char *ret;
238
239 if ((NULL == cp) ||
241 return "NULL";
242
244 if (NULL == ret)
245 return "NULL";
246
247 GNUNET_strlcpy (buf,
248 ret,
249 sizeof(buf));
251 return buf;
252}
253
254
255double
257 unsigned int off)
258{
259 unsigned int num_alts = cp->num_paths;
260 unsigned int off_sum;
261 double avg_sum;
262 double path_delta;
263 double weight_alts;
264
265 GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
267
268 /* We maintain 'off_sum' in 'peer' and thereby
269 avoid the SLOW recalculation each time. Kept here
270 just to document what is going on. */
271#if SLOW
272 off_sum = 0;
273 for (unsigned int j = 0; j < cp->path_dll_length; j++)
274 for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
275 NULL != pe;
276 pe = pe->next)
277 off_sum += j;
278 GNUNET_assert (off_sum == cp->off_sum);
279#else
280 off_sum = cp->off_sum;
281#endif
282 avg_sum = off_sum * 1.0 / cp->path_dll_length;
283 path_delta = off - avg_sum;
284 /* path_delta positive: path off of peer above average (bad path for peer),
285 path_delta negative: path off of peer below average (good path for peer) */
286 if (path_delta <= -1.0)
287 weight_alts = -num_alts / path_delta; /* discount alternative paths */
288 else if (path_delta >= 1.0)
289 weight_alts = num_alts * path_delta; /* overcount alternative paths */
290 else
291 weight_alts = num_alts; /* count alternative paths normally */
292
293
294 /* off+1: long paths are generally harder to find and thus count
295 a bit more as they get longer. However, above-average paths
296 still need to count less, hence the squaring of that factor. */
297 return (off + 1.0) / (weight_alts * weight_alts);
298}
299
300
306static void
307destroy_peer (void *cls)
308{
309 struct CadetPeer *cp = cls;
310
312 "Destroying state about peer %s\n",
313 GCP_2s (cp));
314 cp->destroy_task = NULL;
315 GNUNET_assert (NULL == cp->t);
316 GNUNET_assert (NULL == cp->core_mq);
317 GNUNET_assert (0 == cp->num_paths);
318 for (unsigned int i = 0; i < cp->path_dll_length; i++)
319 GNUNET_assert (NULL == cp->path_heads[i]);
323 &cp->pid,
324 cp));
327 cp->path_dll_length = 0;
328 if (NULL != cp->search_h)
329 {
331 cp->search_h = NULL;
332 }
333 /* FIXME: clean up search_delayedXXX! */
334
335
336 if (NULL != cp->ash)
337 {
339 cp->ash = NULL;
340 }
342 if (NULL != cp->path_heap)
343 {
345 cp->path_heap = NULL;
346 }
347 if (NULL != cp->heap_cleanup_task)
348 {
350 cp->heap_cleanup_task = NULL;
351 }
352 GNUNET_free (cp->hello);
353 /* Peer should not be freed if paths exist; if there are no paths,
354 there ought to be no connections, and without connections, no
355 notifications. Thus we can assert that mqm_head is empty at this
356 point. */
357 GNUNET_assert (NULL == cp->mqm_head);
358 GNUNET_assert (NULL == cp->mqm_ready_ptr);
359 GNUNET_free (cp);
360}
361
362
368static void
370{
372
374 "Updating peer %s activation state (%u connections)%s%s\n",
375 GCP_2s (cp),
377 (NULL == cp->t) ? "" : " with tunnel",
378 (NULL == cp->core_mq) ? "" : " with CORE link");
379 if (NULL != cp->destroy_task)
380 {
381 /* It's active, do not destroy! */
383 cp->destroy_task = NULL;
384 }
386 (NULL == cp->t))
387 {
388 /* We're just on a path or directly connected; don't bother too much */
389 if (NULL != cp->ash)
390 {
392 cp->ash = NULL;
393 }
394 if (NULL != cp->search_h)
395 {
397 cp->search_h = NULL;
398 }
399 return;
400 }
401 if (NULL == cp->core_mq)
402 {
403 /* Lacks direct connection, try to create one by querying the DHT */
404 if ((NULL == cp->search_h) &&
406 cp->search_h
407 = GCD_search (&cp->pid);
408 }
409 else
410 {
411 /* Have direct connection, stop DHT search if active */
412 if (NULL != cp->search_h)
413 {
415 cp->search_h = NULL;
416 }
417 }
418
419 if (NULL != cp->ash)
421 bw.value__ = 0;
422 cp->ash
424 &cp->pid,
426 bw);
427}
428
429
435static void
437
438
445static void
446drop_paths (void *cls)
447{
448 struct CadetPeer *cp = cls;
449 struct CadetPeerPath *path;
450
451 cp->destroy_task = NULL;
452 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
453 GCPP_release (path);
455}
456
457
463static void
465{
466 struct GNUNET_TIME_Relative exp;
467
468 if (NULL != cp->destroy_task)
469 {
471 cp->destroy_task = NULL;
472 }
473 if (NULL != cp->t)
474 return; /* still relevant! */
475 if (NULL != cp->core_mq)
476 return; /* still relevant! */
478 return; /* still relevant! */
479 if ((NULL != cp->path_heap) &&
481 {
483 &drop_paths,
484 cp);
485 return;
486 }
487 if (0 != cp->num_paths)
488 return; /* still relevant! */
489 if (NULL != cp->hello)
490 {
491 /* relevant only until HELLO expires */
494 ->hello));
497 cp);
498 return;
499 }
502 cp);
503}
504
505
512void
514 struct GNUNET_MQ_Handle *mq)
515{
517 "Message queue for peer %s is now %p\n",
518 GCP_2s (cp),
519 mq);
520 cp->core_mq = mq;
521 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
522 NULL != mqm;
523 mqm = next)
524 {
525 /* Save next pointer in case mqm gets freed by the callback */
526 next = mqm->next;
527 if (NULL == mq)
528 {
529 if (NULL != mqm->env)
530 {
531 GNUNET_MQ_discard (mqm->env);
532 mqm->env = NULL;
533 mqm->cb (mqm->cb_cls,
535 }
536 else
537 {
538 mqm->cb (mqm->cb_cls,
539 GNUNET_NO);
540 }
541 }
542 else
543 {
544 GNUNET_assert (NULL == mqm->env);
545 mqm->cb (mqm->cb_cls,
546 GNUNET_YES);
547 }
548 }
549 if ((NULL != mq) ||
550 (NULL != cp->t))
552 else
554
555 if ((NULL != mq) &&
556 (NULL != cp->t))
557 {
558 /* have a new, direct path to the target, notify tunnel */
559 struct CadetPeerPath *path;
560
561 path = GCPP_get_path_from_route (1,
562 &cp->pid);
563 GCT_consider_path (cp->t,
564 path,
565 0);
566 }
567}
568
569
576static int
578{
579 if (0 == drop_percent)
580 return GNUNET_NO;
582 101) < drop_percent)
583 return GNUNET_YES;
584 return GNUNET_NO;
585}
586
587
594static void
595mqm_send_done (void *cls);
596
597
603static void
605{
606 struct CadetPeer *cp = mqm->cp;
607
608 /* Move ready pointer to the next entry that might be ready. */
609 if ((mqm == cp->mqm_ready_ptr) &&
610 (NULL != mqm->next))
611 cp->mqm_ready_ptr = mqm->next;
612 /* Move entry to the end of the DLL, to be fair. */
613 if (mqm != cp->mqm_tail)
614 {
616 cp->mqm_tail,
617 mqm);
619 cp->mqm_tail,
620 mqm);
621 }
622 cp->mqm_ready_counter--;
623 if (GNUNET_YES == should_I_drop ())
624 {
626 "DROPPING message to peer %s from MQM %p\n",
627 GCP_2s (cp),
628 mqm);
629 GNUNET_MQ_discard (mqm->env);
630 mqm->env = NULL;
631 mqm_send_done (cp);
632 }
633 else
634 {
635 {
636 const struct GNUNET_MessageHeader *mh;
637
639 switch (ntohs (mh->type))
640 {
642 {
644 = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh;
646 "P2P forwarding KX with ephemeral %s to %s on CID %s\n",
647 GNUNET_e2s (&msg->ephemeral_key),
648 GCP_2s (cp),
649 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
650 }
651 break;
652
653 default:
654 break;
655 }
656 }
658 "Sending to peer %s from MQM %p\n",
659 GCP_2s (cp),
660 mqm);
662 mqm->env);
663 mqm->env = NULL;
664 }
665 mqm->cb (mqm->cb_cls,
666 GNUNET_YES);
667}
668
669
677static void
679{
680 struct GCP_MessageQueueManager *mqm;
681
682 if (0 == cp->mqm_ready_counter)
683 return;
684 while ((NULL != (mqm = cp->mqm_ready_ptr)) &&
685 (NULL == mqm->env))
686 cp->mqm_ready_ptr = mqm->next;
687 if (NULL == mqm)
688 return; /* nothing to do */
689 mqm_execute (mqm);
690}
691
692
699static void
700mqm_send_done (void *cls)
701{
702 struct CadetPeer *cp = cls;
703
705 "Sending to peer %s completed\n",
706 GCP_2s (cp));
707 send_next_ready (cp);
708}
709
710
718void
720 struct GNUNET_MQ_Envelope *env)
721{
722 struct CadetPeer *cp = mqm->cp;
723
724 GNUNET_assert (NULL != env);
726 "Queueing message to peer %s in MQM %p\n",
727 GCP_2s (cp),
728 mqm);
729 GNUNET_assert (NULL != cp->core_mq);
730 GNUNET_assert (NULL == mqm->env);
733 cp);
734 mqm->env = env;
735 cp->mqm_ready_counter++;
736 if (mqm != cp->mqm_ready_ptr)
737 cp->mqm_ready_ptr = cp->mqm_head;
738 if (1 == cp->mqm_ready_counter)
739 cp->mqm_ready_ptr = mqm;
740 if (0 != GNUNET_MQ_get_length (cp->core_mq))
741 return;
742 send_next_ready (cp);
743}
744
745
754static int
756 const struct GNUNET_PeerIdentity *pid,
757 void *value)
758{
759 struct CadetPeer *cp = value;
760
761 if (NULL != cp->destroy_task)
762 {
764 cp->destroy_task = NULL;
765 }
766 destroy_peer (cp);
767 return GNUNET_OK;
768}
769
770
776void
778{
780 "Destroying all peers now\n");
783 NULL);
784}
785
786
793void
795{
796 struct CadetPeerPath *path;
797
799 "Destroying all paths to %s\n",
800 GCP_2s (cp));
801 while (NULL != (path =
803 GCPP_release (path);
805 cp->path_heap = NULL;
806}
807
808
816void
818 struct CadetPeerPathEntry *entry,
819 unsigned int off)
820{
822 off));
824 "Discovered that peer %s is on path %s at offset %u\n",
825 GCP_2s (cp),
826 GCPP_2s (entry->path),
827 off);
828 if (off >= cp->path_dll_length)
829 {
830 unsigned int len = cp->path_dll_length;
831
833 len,
834 off + 4);
836 cp->path_dll_length,
837 off + 4);
838 }
840 cp->path_tails[off],
841 entry);
842 cp->off_sum += off;
843 cp->num_paths++;
844
845 /* If we have a tunnel to this peer, tell the tunnel that there is a
846 new path available. */
847 if (NULL != cp->t)
848 GCT_consider_path (cp->t,
849 entry->path,
850 off);
851
852 if ((NULL != cp->search_h) &&
853 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths))
854 {
855 /* Now I have enough paths, stop search */
857 cp->search_h = NULL;
858 }
859 if (NULL != cp->destroy_task)
860 {
861 /* paths changed, this resets the destroy timeout counter
862 and aborts a destroy task that may no longer be valid
863 to have (as we now have more paths via this peer). */
865 }
866}
867
868
876void
878 struct CadetPeerPathEntry *entry,
879 unsigned int off)
880{
882 "Removing knowledge about peer %s being on path %s at offset %u\n",
883 GCP_2s (cp),
884 GCPP_2s (entry->path),
885 off);
887 cp->path_tails[off],
888 entry);
889 GNUNET_assert (0 < cp->num_paths);
890 cp->off_sum -= off;
891 cp->num_paths--;
892 if ((NULL == cp->core_mq) &&
893 (NULL != cp->t) &&
894 (NULL == cp->search_h) &&
896 cp->search_h
897 = GCD_search (&cp->pid);
898 if (NULL == cp->destroy_task)
899 {
900 /* paths changed, we might now be ready for destruction, check again */
902 }
903}
904
905
912static void
914{
915 struct CadetPeer *cp = cls;
916 struct CadetPeerPath *root;
917
918 cp->heap_cleanup_task = NULL;
921 {
922 /* Now we have way too many, drop least desirable UNLESS it is in use!
923 (Note that this intentionally keeps highly desirable, but currently
924 unused paths around in the hope that we might be able to switch, even
925 if the number of paths exceeds the threshold.) */
927 GNUNET_assert (NULL != root);
928 if (NULL !=
930 cp,
931 GCPP_get_length (root) - 1))
932 break; /* can't fix */
933 /* Got plenty of paths to this destination, and this is a low-quality
934 one that we don't care about. Allow it to die. */
935 GNUNET_assert (root ==
937 GCPP_release (root);
938 }
939}
940
941
944 struct CadetPeerPath *path,
945 unsigned int off,
946 int force)
947{
949 struct CadetPeerPath *root;
950 GNUNET_CONTAINER_HeapCostType root_desirability;
951 struct GNUNET_CONTAINER_HeapNode *hn;
952
953 GNUNET_assert (off == GCPP_get_length (path) - 1);
955 off));
956 if (NULL == cp->path_heap)
957 {
958 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
959 GNUNET_assert (GNUNET_NO == force);
960 return NULL;
961 }
962 desirability = GCPP_get_desirability (path);
963 if (GNUNET_NO == force)
964 {
965 /* FIXME: desirability is not yet initialized; tricky! */
966 if (GNUNET_NO ==
968 (void **) &root,
969 &root_desirability))
970 {
971 root = NULL;
972 root_desirability = 0;
973 }
974
976 (desirability < root_desirability))
977 {
979 "Decided to not attach path %s to peer %s due to undesirability\n",
980 GCPP_2s (path),
981 GCP_2s (cp));
982 return NULL;
983 }
984 }
985
987 "Attaching path %s to peer %s (%s)\n",
988 GCPP_2s (path),
989 GCP_2s (cp),
990 (GNUNET_NO == force) ? "desirable" : "forced");
991
992 /* Yes, we'd like to add this path, add to our heap */
994 path,
995 desirability);
996
997 /* Consider maybe dropping other paths because of the new one */
1000 (NULL != cp->heap_cleanup_task))
1002 cp);
1003 return hn;
1004}
1005
1006
1016void
1018 struct CadetPeerPath *path,
1019 struct GNUNET_CONTAINER_HeapNode *hn)
1020{
1022 "Detaching path %s from peer %s\n",
1023 GCPP_2s (path),
1024 GCP_2s (cp));
1025 GNUNET_assert (path ==
1027}
1028
1029
1036void
1038 struct CadetConnection *cc)
1039{
1041 "Adding %s to peer %s\n",
1042 GCC_2s (cc),
1043 GCP_2s (cp));
1046 &GCC_get_id (
1047 cc)->connection_of_tunnel,
1048 cc,
1050 if (NULL != cp->destroy_task)
1051 {
1053 cp->destroy_task = NULL;
1054 }
1055}
1056
1057
1064void
1066 struct CadetConnection *cc)
1067{
1069 "Removing connection %s from peer %s\n",
1070 GCC_2s (cc),
1071 GCP_2s (cp));
1074 &GCC_get_id (
1075 cc)->
1076 connection_of_tunnel,
1077 cc));
1079}
1080
1081
1093struct CadetPeer *
1095 int create)
1096{
1097 struct CadetPeer *cp;
1098
1100 peer_id);
1101 if (NULL != cp)
1102 return cp;
1103 if (GNUNET_NO == create)
1104 return NULL;
1105 cp = GNUNET_new (struct CadetPeer);
1106 cp->pid = *peer_id;
1108 GNUNET_YES);
1113 &cp->pid,
1114 cp,
1117 "Creating peer %s\n",
1118 GCP_2s (cp));
1119 return cp;
1120}
1121
1122
1129const struct GNUNET_PeerIdentity *
1131{
1132 return &cp->pid;
1133}
1134
1135
1142void
1144 void *cls)
1145{
1147 iter,
1148 cls);
1149}
1150
1151
1158unsigned int
1159GCP_count_paths (const struct CadetPeer *cp)
1160{
1161 return cp->num_paths;
1162}
1163
1164
1173unsigned int
1175 GCP_PathIterator callback,
1176 void *callback_cls)
1177{
1178 unsigned int ret = 0;
1179
1181 "Iterating over paths to peer %s%s\n",
1182 GCP_2s (cp),
1183 (NULL == cp->core_mq) ? "" : " including direct link");
1184 if (NULL != cp->core_mq)
1185 {
1186 /* FIXME: this branch seems to duplicate the
1187 i=0 case below (direct link). Leave out!??? -CG */
1188 struct CadetPeerPath *path;
1189
1190 path = GCPP_get_path_from_route (1,
1191 &cp->pid);
1192 ret++;
1193 if (GNUNET_NO ==
1194 callback (callback_cls,
1195 path,
1196 0))
1197 return ret;
1198 }
1199 for (unsigned int i = 0; i < cp->path_dll_length; i++)
1200 {
1201 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1202 NULL != pe;
1203 pe = pe->next)
1204 {
1205 ret++;
1206 if (GNUNET_NO ==
1207 callback (callback_cls,
1208 pe->path,
1209 i))
1210 return ret;
1211 }
1212 }
1213 return ret;
1214}
1215
1216
1225unsigned int
1227 GCP_PathIterator callback,
1228 void *callback_cls)
1229{
1230 unsigned int ret = 0;
1231
1233 "Iterating over paths to peer %s without direct link\n",
1234 GCP_2s (cp));
1235 for (unsigned int i = 1; i < cp->path_dll_length; i++)
1236 {
1237 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1238 NULL != pe;
1239 pe = pe->next)
1240 {
1241 ret++;
1242 if (GNUNET_NO ==
1243 callback (callback_cls,
1244 pe->path,
1245 i))
1246 return ret;
1247 }
1248 }
1249 return ret;
1250}
1251
1252
1253unsigned int
1255 unsigned int dist,
1256 GCP_PathIterator callback,
1257 void *callback_cls)
1258{
1259 unsigned int ret = 0;
1260
1261 if (dist >= cp->path_dll_length)
1262 {
1264 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1265 dist,
1266 cp->path_dll_length);
1267 return 0;
1268 }
1269 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1270 NULL != pe;
1271 pe = pe->next)
1272 {
1273 if (GNUNET_NO ==
1274 callback (callback_cls,
1275 pe->path,
1276 dist))
1277 return ret;
1278 ret++;
1279 }
1280 return ret;
1281}
1282
1283
1291struct CadetTunnel *
1293 int create)
1294{
1295 if (NULL == cp)
1296 return NULL;
1297 if ((NULL != cp->t) ||
1298 (GNUNET_NO == create))
1299 return cp->t;
1300 cp->t = GCT_create_tunnel (cp);
1302 return cp->t;
1303}
1304
1305
1306void
1308 const struct GNUNET_MessageHeader *hello)
1309{
1311 uint16_t size = ntohs (hello->size);
1312
1314 "Got %u byte HELLO for peer %s\n",
1315 (unsigned int) size,
1316 GCP_2s (cp));
1317 if (NULL != cp->hello)
1318 {
1320
1321 struct GNUNET_TIME_Absolute new_hello_exp =
1323 struct GNUNET_TIME_Absolute old_hello_exp =
1325 ->hello);
1326
1327 if (GNUNET_TIME_absolute_cmp (new_hello_exp, >, now) &&
1328 GNUNET_TIME_absolute_cmp (new_hello_exp, >, old_hello_exp))
1329 {
1330 GNUNET_free (cp->hello);
1331 cp->hello = GNUNET_malloc (size);
1332 GNUNET_memcpy (cp->hello, hello, size);
1333 }
1334 else
1335 {
1336 return;
1337 }
1338 }
1339 else
1340 {
1341 cp->hello = GNUNET_memdup (hello,
1342 size);
1343 }
1344 if (NULL != cp->ash)
1346 bw.value__ = 0;
1347 cp->ash
1349 &cp->pid,
1351 bw);
1352 /* New HELLO means cp's destruction time may change... */
1354}
1355
1356
1364void
1366 struct CadetTunnel *t)
1367{
1369 "Dropping tunnel %s to peer %s\n",
1370 GCT_2s (t),
1371 GCP_2s (cp));
1372 GNUNET_assert (cp->t == t);
1373 cp->t = NULL;
1375}
1376
1377
1384int
1386{
1387 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1388}
1389
1390
1402 void *cb_cls)
1403{
1404 struct GCP_MessageQueueManager *mqm;
1405
1406 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1407 mqm->cb = cb;
1408 mqm->cb_cls = cb_cls;
1409 mqm->cp = cp;
1411 cp->mqm_tail,
1412 mqm);
1414 "Creating MQM %p for peer %s\n",
1415 mqm,
1416 GCP_2s (cp));
1417 if (NULL != cp->core_mq)
1418 cb (cb_cls,
1419 GNUNET_YES);
1420 return mqm;
1421}
1422
1423
1430void
1432 struct GNUNET_MQ_Envelope *last_env)
1433{
1434 struct CadetPeer *cp = mqm->cp;
1435
1437 "Destroying MQM %p for peer %s%s\n",
1438 mqm,
1439 GCP_2s (cp),
1440 (NULL == last_env) ? "" : " with last ditch transmission");
1441 if (NULL != mqm->env)
1442 GNUNET_MQ_discard (mqm->env);
1443 if (NULL != last_env)
1444 {
1445 if (NULL != cp->core_mq)
1446 {
1447 GNUNET_MQ_notify_sent (last_env,
1449 cp);
1451 last_env);
1452 }
1453 else
1454 {
1455 GNUNET_MQ_discard (last_env);
1456 }
1457 }
1458 if (cp->mqm_ready_ptr == mqm)
1459 cp->mqm_ready_ptr = mqm->next;
1461 cp->mqm_tail,
1462 mqm);
1463 GNUNET_free (mqm);
1464}
1465
1466
1476void
1478 struct GNUNET_MQ_Envelope *env)
1479{
1481 "Sending message to %s out of management\n",
1482 GCP_2s (cp));
1483 if (NULL == cp->core_mq)
1484 {
1486 return;
1487 }
1489 {
1491 return;
1492 }
1495 cp);
1497 env);
1498}
1499
1500
1508int
1510 struct GNUNET_TIME_AbsoluteNBO monotime)
1511{
1512
1513 struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime);
1514
1516 {
1517 peer->last_connection_create = mt;
1518 return GNUNET_YES;
1519 }
1520 return GNUNET_NO;
1521}
1522
1523
1531int
1534{
1535 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
1537 .purpose.size = htonl (sizeof(cp)),
1538 .monotonic_time = msg->monotime};
1539
1540 if (GNUNET_OK !=
1543 &cp,
1544 &msg->monotime_sig,
1545 &peer->pid.public_key))
1546 {
1547 GNUNET_break_op (0);
1548 return GNUNET_SYSERR;
1549 }
1550 return GNUNET_OK;
1551}
1552
1553
1554/* end of gnunet-service-cadet-new_peer.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static int ret
Final status code.
Definition: gnunet-arm.c:94
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
static int create
Create DID Document Flag.
Definition: gnunet-did.c:68
static char * value
Value of the record to add/remove.
struct GNUNET_CONTAINER_MultiPeerMap * peers
Map from PIDs to struct CadetPeer entries.
unsigned long long drop_percent
Set to non-zero values to create random drops to test retransmissions.
struct GNUNET_TRANSPORT_ApplicationHandle * transport
Handle to Transport service.
Information we track per peer.
const char * GCC_2s(const struct CadetConnection *cc)
Get a (static) string for a connection.
const struct GNUNET_CADET_ConnectionTunnelIdentifier * GCC_get_id(struct CadetConnection *cc)
Obtain unique ID for the connection.
A connection is a live end-to-end messaging mechanism where the peers are identified by a path and kn...
void GCD_search_stop(struct GCD_search_handle *h)
Stop DHT search started with GCD_search().
struct GCD_search_handle * GCD_search(const struct GNUNET_PeerIdentity *peer_id)
Search DHT for paths to peeR_id.
cadet service; dealing with DHT requests and results
const char * GCPP_2s(struct CadetPeerPath *path)
Convert a path to a human-readable string.
unsigned int GCPP_get_length(struct CadetPeerPath *path)
Return the length of the path.
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.
GNUNET_CONTAINER_HeapCostType GCPP_get_desirability(const struct CadetPeerPath *path)
Return how much we like keeping the path.
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 CadetPeer * GCPP_get_peer_at_offset(struct CadetPeerPath *path, unsigned int off)
Obtain the peer at offset off in path.
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.
static void consider_peer_activate(struct CadetPeer *cp)
This peer is now on more "active" duty, activate processes related to it.
int GCP_check_monotime_sig(struct CadetPeer *peer, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
void GCP_add_connection(struct CadetPeer *cp, struct CadetConnection *cc)
Add a connection to this cp.
const struct GNUNET_PeerIdentity * GCP_get_id(struct CadetPeer *cp)
Obtain the peer identity for a struct CadetPeer.
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...
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.
static void path_heap_cleanup(void *cls)
Prune down the number of paths to this peer, we seem to have way too many.
struct CadetPeer * GCP_get(const struct GNUNET_PeerIdentity *peer_id, int create)
Retrieve the CadetPeer structure associated with the peer.
int GCP_has_core_connection(struct CadetPeer *cp)
Test if cp has a core-level connection.
#define IDLE_PEER_TIMEOUT
How long do we wait until tearing down an idle peer?
static void mqm_send_done(void *cls)
Function called when CORE took one of the messages from a message queue manager and transmitted it.
static void drop_paths(void *cls)
We really no longere care about a peer, stop hogging memory with paths to it.
struct CadetTunnel * GCP_get_tunnel(struct CadetPeer *cp, int create)
Get the tunnel towards a peer.
unsigned int GCP_count_paths(const struct CadetPeer *cp)
Count the number of known paths toward the peer.
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.
void GCP_send_ooo(struct CadetPeer *cp, struct GNUNET_MQ_Envelope *env)
Send the message in env to cp, overriding queueing logic.
static void consider_peer_destroy(struct CadetPeer *cp)
This peer may no longer be needed, consider cleaning it up.
int GCP_check_and_update_monotime(struct CadetPeer *peer, struct GNUNET_TIME_AbsoluteNBO monotime)
Checking if a monotime value is newer than the last monotime value received from a peer.
void GCP_request_mq_cancel(struct GCP_MessageQueueManager *mqm, struct GNUNET_MQ_Envelope *last_env)
Stops message queue change notifications.
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...
#define MAX_OOO_QUEUE_SIZE
Queue size when we start dropping OOO messages.
void GCP_set_hello(struct CadetPeer *cp, const struct GNUNET_MessageHeader *hello)
We got a HELLO for a cp, remember it, and possibly trigger adequate actions (like trying to connect).
static int should_I_drop(void)
Debug function should NEVER return true in production code, useful to simulate losses for testcases.
struct GNUNET_CONTAINER_HeapNode * GCP_attach_path(struct CadetPeer *cp, struct CadetPeerPath *path, unsigned int off, int force)
Try adding a path to this cp.
unsigned int GCP_iterate_paths_at(struct CadetPeer *cp, unsigned int dist, GCP_PathIterator callback, void *callback_cls)
Iterate over the paths to peer where peer is at distance dist from us.
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 in the path.
void GCP_set_mq(struct CadetPeer *cp, struct GNUNET_MQ_Handle *mq)
Set the message queue to mq for peer cp and notify watchers.
static void mqm_execute(struct GCP_MessageQueueManager *mqm)
Transmit current envelope from this mqm.
static void destroy_peer(void *cls)
This peer is no longer be needed, clean it up now.
#define IDLE_PATH_TIMEOUT
How long do we keep paths around if we no longer care about 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,...
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.
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.
#define LOG(level,...)
static int destroy_iterator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called to destroy a peer now.
void GCP_send(struct GCP_MessageQueueManager *mqm, struct GNUNET_MQ_Envelope *env)
Send the message in env to cp.
void GCP_remove_connection(struct CadetPeer *cp, struct CadetConnection *cc)
Remove a connection that went via this cp.
const char * GCP_2s(const struct CadetPeer *cp)
Get the static string for a peer ID.
unsigned int GCP_iterate_paths(struct CadetPeer *cp, GCP_PathIterator callback, void *callback_cls)
Iterate over the paths to a peer.
void GCP_destroy_all_peers()
Clean up all entries about all peers.
struct GCP_MessageQueueManager * GCP_request_mq(struct CadetPeer *cp, GCP_MessageQueueNotificationCallback cb, void *cb_cls)
Start message queue change notifications.
void GCP_iterate_all(GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
Iterate over all known peers.
Information we track per peer.
int(* GCP_PathIterator)(void *cls, struct CadetPeerPath *path, unsigned int off)
Peer path iterator.
void(* GCP_MessageQueueNotificationCallback)(void *cls, int available)
Function to call with updated message queue object.
struct CadetTunnel * GCT_create_tunnel(struct CadetPeer *destination)
Create a tunnel to destination.
void GCT_consider_path(struct CadetTunnel *t, struct CadetPeerPath *p, unsigned int off)
Consider using the path p for the tunnel t.
const char * GCT_2s(const struct CadetTunnel *t)
Get the static string for the peer this tunnel is directed.
Information we track per tunnel.
#define DESIRED_CONNECTIONS_PER_TUNNEL
How many connections would we like to have per tunnel?
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_SCHEDULER_Task * t
Main task.
Core service; the main API for encrypted P2P communications.
Helper library for handling HELLO URIs.
API to create, modify and access statistics.
Functions related to time.
Bandwidth allocation API for applications to interact with.
struct GNUNET_TRANSPORT_ApplicationSuggestHandle * GNUNET_TRANSPORT_application_suggest(struct GNUNET_TRANSPORT_ApplicationHandle *ch, const struct GNUNET_PeerIdentity *peer, enum GNUNET_MQ_PriorityPreferences pk, struct GNUNET_BANDWIDTH_Value32NBO bw)
An application would like TRANSPORT to connect to a peer.
void GNUNET_TRANSPORT_application_suggest_cancel(struct GNUNET_TRANSPORT_ApplicationSuggestHandle *sh)
We no longer care about being connected to a peer.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
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.
enum GNUNET_GenericReturnValue(* GNUNET_CONTAINER_PeerMapIterator)(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
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).
enum GNUNET_GenericReturnValue 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.
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
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_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
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.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
uint64_t GNUNET_CONTAINER_HeapCostType
Cost by which elements in a heap can be ordered.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
struct GNUNET_TIME_Absolute GNUNET_HELLO_builder_get_expiration_time(const struct GNUNET_MessageHeader *msg)
Get the expiration time for this HELLO.
Definition: hello-uri.c:470
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
enum GNUNET_GenericReturnValue 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.
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:254
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:293
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:305
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:285
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:655
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition: mq.c:896
@ GNUNET_MQ_PRIO_BEST_EFFORT
Best-effort traffic (e.g.
#define GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
Axolotl key exchange.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
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:1305
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:1278
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:138
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:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR
Signature by a peer that like to create a connection.
Purpose for the signature of a monotime.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR.
Low-level connection to a destination.
Entry in a peer path.
struct CadetPeerPathEntry * next
DLL of paths where the same peer is at the same offset.
struct CadetPeerPath * path
Path this entry belongs to.
Information regarding a possible path to reach a peer.
Struct containing all information regarding a given peer.
struct GCP_MessageQueueManager * mqm_tail
Notifications to call when core_mq changes.
struct GCD_search_handle * search_h
Handle to stop the DHT search for paths to this peer.
struct GNUNET_SCHEDULER_Task * heap_cleanup_task
Task to clean up path_heap asynchronously.
struct GNUNET_MQ_Handle * core_mq
Handle for core transmissions.
unsigned int queue_n
How many messages are in the queue to this peer.
struct GNUNET_TIME_Absolute last_connection_create
Last time we heard from this peer (currently not used!)
struct GNUNET_MessageHeader * hello
Hello message of the peer.
struct GNUNET_TRANSPORT_ApplicationSuggestHandle * ash
Transport suggest handle.
struct GNUNET_CONTAINER_Heap * path_heap
MIN-heap of paths owned by this peer (they also end at this peer).
struct CadetPeerPathEntry ** path_heads
Array of DLLs of paths traversing the peer, organized by the offset of the peer on the larger path.
unsigned int mqm_ready_counter
Number of message queue managers of this peer that have a message in waiting.
unsigned int num_paths
How many paths do we have to this peer (in all path_heads DLLs combined).
struct GNUNET_SCHEDULER_Task * destroy_task
Task to destroy this entry.
unsigned int off_sum
Sum over all of the offsets of all of the paths in the path_heads DLLs.
struct GCP_MessageQueueManager * mqm_head
Notifications to call when core_mq changes.
struct GNUNET_CONTAINER_MultiShortmap * connections
Connections that go through this peer; indexed by tid.
struct GNUNET_TRANSPORT_OfferHelloHandle * hello_offer
Handle to us offering the HELLO to the transport.
struct GNUNET_PeerIdentity pid
ID of the peer.
struct CadetTunnel * t
Tunnel to this peer, if any.
struct GCP_MessageQueueManager * mqm_ready_ptr
Pointer to first "ready" entry in mqm_head.
unsigned int path_dll_length
Current length of the path_heads and path_tails arrays.
struct CadetPeerPathEntry ** path_tails
Array of DLL of paths traversing the peer, organized by the offset of the peer on the larger path.
Struct containing all information regarding a tunnel to a peer.
Data structure used to track whom we have to notify about changes to our message queue.
struct CadetPeer * cp
The peer this is for.
GCP_MessageQueueNotificationCallback cb
Function to call with updated message queue object.
struct GNUNET_MQ_Envelope * env
Envelope this manager would like to transmit once it is its turn.
struct GCP_MessageQueueManager * next
Kept in a DLL.
struct GCP_MessageQueueManager * prev
Kept in a DLL.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
uint32_t value__
The actual value (bytes per second).
Message for cadet connection creation.
Message for a Key eXchange for a tunnel.
Handle to a node in a heap.
Internal representation of the hash map.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Handle to a message queue.
Definition: mq.c:87
Header for all communications.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
Handle for TRANSPORT address suggestion requests.