GNUnet 0.29.1-2-g89ecb1bfd
 
Loading...
Searching...
No Matches
gnunet-service-transport.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018-2019, 2026 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 */
75#include "platform.h"
76#include "gnunet_common.h"
77#include "gnunet_util_lib.h"
80#include "gnunet_pils_service.h"
82#include "gnunet_nat_service.h"
84#include "gnunet_signatures.h"
85#include "transport.h"
86
90#define RING_BUFFER_SIZE 16
91
95#define MAX_FC_RETRANSMIT_COUNT 1000
96
102#define MIN_FC_RETRANSMIT_DELAY \
103 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
104
109#define UNCONFIRMED_LINK_TIMEOUT \
110 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
111
116#define MAX_CUMMULATIVE_ACKS 64
117
130#define FC_NO_CHANGE_REPLY_PROBABILITY 8
131
136#define IN_PACKET_SIZE_WITHOUT_MTU 128
137
142#define GOODPUT_AGING_SLOTS 4
143
148#define DEFAULT_WINDOW_SIZE (128 * 1024)
149
158#define MAX_INCOMING_REQUEST 16
159
164#define MAX_DV_DISCOVERY_SELECTION 16
165
174#define RECV_WINDOW_SIZE 4
175
190#define CORE_FC_STALL_TIMEOUT \
191 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
192
204#define MAX_STALLED_CMCS (4 * RECV_WINDOW_SIZE)
205
213#define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
214
218#define MAX_DV_HOPS_ALLOWED 16
219
225#define MAX_DV_PICK_TRIES 1000
226
231#define MAX_DV_LEARN_PENDING 64
232
236#define MAX_DV_PATHS_TO_TARGET 3
237
244#define PILS_FEED_ADDRESSES_DELAY \
245 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
246
252#define DELAY_WARN_THRESHOLD \
253 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
254
259#define DV_FORWARD_TIMEOUT \
260 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
261
265#define DEFAULT_ACK_WAIT_DURATION \
266 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
267
284#define MIN_ACK_WAIT_DURATION \
285 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10)
286
292#define DV_QUALITY_RTT_THRESHOLD \
293 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
294
299#define DV_PATH_VALIDITY_TIMEOUT \
300 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
301
306#define BACKCHANNEL_INACTIVITY_TIMEOUT \
307 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
308
313#define DV_PATH_DISCOVERY_FREQUENCY \
314 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
315
319#define EPHEMERAL_VALIDITY \
320 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
321
325#define REASSEMBLY_EXPIRATION \
326 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
327
334#define MAX_REASSEMBLY_CONTEXTS 32
335
340#define FAST_VALIDATION_CHALLENGE_FREQ \
341 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
342
346#define MAX_VALIDATION_CHALLENGE_FREQ \
347 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
348
354#define WANTED_VALIDATION_CHALLENGE_FREQ \
355 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
356
361#define SUGGEST_RETRY_MIN \
362 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
363
370#define SUGGEST_RETRY_MAX \
371 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
372
378#define ACK_CUMMULATOR_TIMEOUT \
379 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
380
385#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
386
391#define DV_LEARN_QUALITY_THRESHOLD 100
392
396#define MAX_ADDRESS_VALID_UNTIL \
397 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
398
402#define ADDRESS_VALIDATION_LIFETIME \
403 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
404
421#define NEIGHBOUR_LIVENESS_TIMEOUT \
422 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
423
452#define FC_KEEPALIVE_INTERVAL \
453 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, \
454 2)
455
461#define MIN_ADDRESS_REFRESH_INTERVAL \
462 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
463
470#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
471
478#define VALIDATION_RTT_BUFFER_FACTOR 3
479
486#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
487
493#define QUEUE_LENGTH_LIMIT 32
494
498#define QUEUE_ENTRY_TIMEOUT \
499 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
500
505#define RTT_DIFF \
506 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
507
514#define SHUTDOWN_CLIENT_GRACE_PERIOD \
515 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
516
518
523{
529};
530
531
542
547{
552
553 /* Followed by *another* message header which is the message to
554 the communicator */
555
556 /* Followed by a 0-terminated name of the communicator */
557};
558
559
597
598
604{
609
615
627
628 /* Followed by a `struct GNUNET_MessageHeader` with a message
629 for the target peer */
630};
631
632
659
660
679
680
689{
694
700
701 /* followed by any number of `struct TransportCummulativeAckPayloadP`
702 messages providing ACKs */
703};
704
705
741
742
786
787
826
827
845
846
861{
866
872
882
889
903
909
914
919
920 /* Followed by @e num_hops `struct DVPathEntryP` values,
921 excluding the initiator of the DV trace; the last entry is the
922 current sender; the current peer must not be included. */
923};
924
925
949{
954
959
967
974
980
987
994
1001
1002 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
1003 excluding the @e origin and the current peer, the last must be
1004 the ultimate target; if @e num_hops is zero, the receiver of this
1005 message is the ultimate target. */
1006
1007 /* Followed by encrypted, variable-size payload, which
1008 must begin with a `struct TransportDVBoxPayloadP` */
1009
1010 /* Followed by the actual message, which itself must not be a
1011 a DV_LEARN or DV_BOX message! */
1012};
1013
1014
1042
1043
1066
1067
1107
1109{
1114
1115 /* Followed by @e address_length bytes of the address. */
1116};
1117
1127{
1132
1141
1147
1154
1164
1174
1179
1184
1189
1195
1196 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1197};
1198
1200
1201/* GNUNET_NETWORK_STRUCT_BEGIN/_END expand to nothing; only the per-member
1202 GNUNET_PACKED keeps these layouts free of compiler padding. Pin the sizes
1203 so that adding an unpacked or non-fixed-width member cannot silently put
1204 padding bytes -- i.e. uninitialised stack -- on the wire again. */
1206
1215
1216
1221{
1226
1231
1236
1241
1245 CT_APPLICATION = 4
1247
1248
1282
1283
1310
1311
1317{
1321 uint64_t bytes_sent;
1322
1328};
1329
1330
1353
1354
1358struct TransportClient;
1359
1363struct Neighbour;
1364
1369struct DistanceVector;
1370
1375struct Queue;
1376
1380struct PendingMessage;
1381
1385struct DistanceVectorHop;
1386
1395struct VirtualLink;
1396
1397
1454
1455
1471
1472
1477{
1482
1487
1492
1496 uint16_t size;
1497
1504 uint16_t isize;
1505};
1506
1507
1512{
1518
1523
1528
1536 uint8_t *bitfield;
1537
1542
1548
1552 uint16_t msg_size;
1553
1558 uint16_t msg_missing;
1559
1560 /* Followed by @e msg_size bytes of the (partially) defragmented original
1561 * message */
1562
1563 /* Followed by @e bitfield data */
1564};
1565
1566
1576{
1581
1588
1595
1600
1606
1612
1617 unsigned int cmc_count;
1618
1625
1630
1635
1640
1645
1653
1659
1665
1670
1675
1680
1685 unsigned int confirmed;
1686
1690 struct Neighbour *n;
1691
1696
1703
1710
1719
1725
1731
1736
1742
1751
1759
1766
1775
1788
1794
1801
1812
1817 uint32_t fc_seq_gen;
1818
1824 uint32_t last_fc_seq;
1825
1838
1843};
1844
1845
1929
1930
2010
2011
2070
2071
2082{
2087
2092
2096 struct Queue *queue;
2097
2102
2106 uint64_t mid;
2107
2112};
2113
2114
2119struct Queue
2120{
2125
2130
2135
2140
2145
2150
2155
2160
2165
2170
2174 const char *address;
2175
2179 unsigned int unlimited_length;
2180
2186
2195
2200
2206
2211 uint64_t mid_gen;
2212
2216 uint32_t qid;
2217
2221 uint32_t mtu;
2222
2227
2232
2236 unsigned int queue_length;
2237
2241 uint64_t q_capacity;
2242
2246 uint32_t priority;
2247
2252
2257
2262 int idle;
2263
2268};
2269
2270
2361
2362
2389
2390
2394struct PeerRequest
2395{
2400
2405
2410
2416
2422
2429
2434};
2435
2436
2462
2463
2490struct PendingMessage
2491{
2496
2501
2506
2511
2517
2523
2528
2533
2539
2545
2550
2560
2565
2570
2575
2580
2585
2590
2596
2602
2607
2613
2618
2622 uint16_t bytes_msg;
2623
2627 uint16_t frag_off;
2628
2633
2638
2642 uint16_t frag_count;
2643
2648
2657
2658 /* Followed by @e bytes_msg to transmit */
2659};
2660
2661
2678
2679
2720
2721
2727
2728
2808
2809
2814{
2819
2824
2829
2834
2839
2840 union
2841 {
2845 struct
2846 {
2852
2858
2862 struct
2863 {
2870
2876
2877
2881 struct
2882 {
2888
2893
2898
2904
2910
2917
2922
2927
2932
2934
2938 struct
2939 {
2947};
2948
2949
2955{
2961
2969
2975
2982 struct GNUNET_TIME_Absolute first_challenge_use;
2983
2990 struct GNUNET_TIME_Absolute last_challenge_use;
2991
2999 struct GNUNET_TIME_Absolute next_challenge;
3000
3009 struct GNUNET_TIME_Relative challenge_backoff;
3010
3015 struct GNUNET_TIME_Relative validation_rtt;
3016
3024 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
3025
3029 struct GNUNET_HashCode hc;
3030
3034 struct GNUNET_SCHEDULER_Task *revalidation_task;
3035
3039 char *address;
3040
3046 struct GNUNET_CONTAINER_HeapNode *hn;
3047
3053
3059 uint32_t last_window_consum_limit;
3060
3065 int awaiting_queue;
3066};
3067
3068
3126
3131
3135static unsigned int ring_buffer_head;
3136
3140static unsigned int is_ring_buffer_full;
3141
3146
3150static unsigned int ring_buffer_dv_head;
3151
3155static unsigned int is_ring_buffer_dv_full;
3156
3161
3166
3171
3176
3183
3189
3194
3200
3206
3212
3218
3224
3230
3236
3242
3247
3251static struct LearnLaunchEntry *lle_head = NULL;
3252
3256static struct LearnLaunchEntry *lle_tail = NULL;
3257
3264
3269
3274
3279
3283struct PilsRequest
3284{
3288 struct PilsRequest *prev;
3289
3293 struct PilsRequest *next;
3294
3298 struct GNUNET_PILS_Operation *op;
3299};
3300
3305
3310
3335static enum GNUNET_GenericReturnValue
3337 struct GNUNET_CRYPTO_EddsaSignature *sig)
3338{
3340
3342 if (NULL == my_private_key)
3343 {
3344 /* #run() enables local key access, so this means the key on disk does
3345 not match the identity PILS announced, or no identity is known yet. */
3347 "No private key for our peer identity, cannot sign\n");
3349 "# signatures failed (no private key)",
3350 1,
3351 GNUNET_NO);
3352 return GNUNET_SYSERR;
3353 }
3354 return GNUNET_CRYPTO_eddsa_sign_ (my_private_key, purpose, sig);
3355}
3356
3357
3362
3367
3372
3377
3384
3389
3393static unsigned int ir_total;
3394
3398static unsigned long long logging_uuid_gen;
3399
3404
3414
3419static int in_shutdown;
3420
3425
3432
3434
3436
3447static unsigned int
3449{
3450 struct GNUNET_TIME_Absolute now;
3451
3452 now = GNUNET_TIME_absolute_get ();
3453 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3454}
3455
3456
3462static void
3464{
3466 GNUNET_assert (ir_total > 0);
3467 ir_total--;
3468 if (NULL != ir->nc)
3470 ir->nc = NULL;
3471 GNUNET_free (ir);
3472}
3473
3474
3480static void
3482{
3483 struct Queue *q = pa->queue;
3484 struct PendingMessage *pm = pa->pm;
3485 struct DistanceVectorHop *dvh = pa->dvh;
3486
3488 "free_pending_acknowledgement\n");
3489 if (NULL != q)
3490 {
3491 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3492 pa->queue = NULL;
3493 }
3494 if (NULL != pm)
3495 {
3497 "remove pa from message\n");
3499 "remove pa from message %" PRIu64 "\n",
3500 pm->logging_uuid);
3502 "remove pa from message %u\n",
3503 pm->pmt);
3505 "remove pa from message %s\n",
3507 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3508 pa->pm = NULL;
3509 }
3510 if (NULL != dvh)
3511 {
3512 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3513 pa->dvh = NULL;
3514 }
3517 &pa->ack_uuid.value,
3518 pa));
3519 GNUNET_free (pa);
3520}
3521
3522
3531static void
3533{
3534 struct PendingMessage *frag;
3535
3536 while (NULL != (frag = root->head_frag))
3537 {
3538 struct PendingAcknowledgement *pa;
3539
3540 free_fragment_tree (frag);
3541 /* Release them: a `struct PendingAcknowledgement' whose @e pm is gone
3542 can never do anything useful again -- handle_acknowledged() would
3543 just free it -- but it stays in #pending_acks, and only an ACK that
3544 may never come takes it out. Merely detaching it here leaked one
3545 entry per fragment that was not acknowledged before its message went
3546 away, which on a lossy link is unbounded growth. */
3547 while (NULL != (pa = frag->pa_head))
3549 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3550 if (NULL != frag->qe)
3551 {
3552 GNUNET_assert (frag == frag->qe->pm);
3553 frag->qe->pm = NULL;
3554 }
3556 "Free frag %p\n",
3557 frag);
3558 GNUNET_free (frag);
3559 }
3560}
3561
3562
3570static void
3572{
3573 struct TransportClient *tc = pm->client;
3574 struct VirtualLink *vl = pm->vl;
3575 struct PendingAcknowledgement *pa;
3576
3578 "Freeing pm %p\n",
3579 pm);
3580 if (NULL != tc)
3581 {
3583 tc->details.core.pending_msg_head,
3584 tc->details.core.pending_msg_tail,
3585 pm);
3586 }
3587 if ((NULL != vl) && (NULL == pm->frag_parent))
3588 {
3590 "Removing pm %" PRIu64 "\n",
3591 pm->logging_uuid);
3593 vl->pending_msg_head,
3594 vl->pending_msg_tail,
3595 pm);
3596 }
3597 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3598 {
3599 struct PendingMessage *root = pm->frag_parent;
3600
3601 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3602 root = root->frag_parent;
3603
3604 root->frag_count--;
3605 }
3606 /* Same as in #free_fragment_tree(): the message these acknowledgements
3607 belong to is going away, so they are garbage rather than orphans. */
3608 while (NULL != (pa = pm->pa_head))
3610
3611 free_fragment_tree (pm);
3612 if (NULL != pm->qe)
3613 {
3614 GNUNET_assert (pm == pm->qe->pm);
3615 pm->qe->pm = NULL;
3616 }
3617 if (NULL != pm->bpm)
3618 {
3619 free_fragment_tree (pm->bpm);
3620 /* @e bpm is released with GNUNET_free() rather than through
3621 #free_pending_message(), so nothing here ever unlinked the
3622 acknowledgements attached to the box itself -- only those of its
3623 fragments, via the call above. They kept @e pm pointing into the
3624 block we are about to release, and #handle_acknowledged() follows
3625 that pointer when the ACK finally arrives. */
3626 while (NULL != (pa = pm->bpm->pa_head))
3628 if (NULL != pm->bpm->qe)
3629 {
3630 struct QueueEntry *qe = pm->bpm->qe;
3631
3632 qe->pm = NULL;
3633 }
3634 GNUNET_free (pm->bpm);
3635 }
3636
3637 GNUNET_free (pm);
3639 "Freeing pm done\n");
3640}
3641
3642
3648static void
3660
3661
3667static void
3669{
3670 struct VirtualLink *vl = cls;
3671 struct ReassemblyContext *rc;
3672
3673 vl->reassembly_timeout_task = NULL;
3674 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3675 {
3677 .rel_value_us)
3678 {
3680 continue;
3681 }
3686 vl);
3687 return;
3688 }
3689}
3690
3691
3700static int
3701free_reassembly_cb (void *cls, uint32_t key, void *value)
3702{
3703 struct ReassemblyContext *rc = value;
3704
3705 (void) cls;
3706 (void) key;
3708 return GNUNET_OK;
3709}
3710
3711
3718static void
3720 unsigned int free_cmc);
3721
3722
3730static void
3732 struct CommunicatorMessageContext *cmc);
3733
3734
3741static void
3742free_burst_cls (struct GNUNET_StartBurstCls *sb_cls);
3743
3744
3762static void
3764 const struct GNUNET_PeerIdentity *pid)
3765{
3766 struct GNUNET_MQ_Envelope *env;
3767 struct SendOkMessage *so_msg;
3768
3769 if (NULL == tc)
3770 return;
3772 so_msg->peer = *pid;
3773 GNUNET_MQ_send (tc->mq, env);
3774}
3775
3776
3789static void
3791{
3792 if ((NULL == pm->client) || (GNUNET_YES == pm->client_credited))
3793 return;
3795 send_ok_to_client (pm->client, &pm->vl->target);
3796}
3797
3798
3804static void
3806{
3807 struct PendingMessage *pm;
3808 struct CoreSentContext *csc;
3809 struct CommunicatorMessageContext *cmc;
3810
3812 "free virtual link %p\n",
3813 vl);
3814
3815 /* Communicators that are blocked on CORE flow control for this link MUST
3816 be resumed here. Otherwise their `struct CommunicatorMessageContext's
3817 leak and -- worse -- those clients never get their
3818 GNUNET_SERVICE_client_continue() and stall forever. */
3819 while (NULL != (cmc = vl->cmc_head))
3820 release_stalled_cmc (vl, cmc);
3821 if (NULL != vl->core_fc_stall_task)
3822 {
3824 vl->core_fc_stall_task = NULL;
3825 }
3826
3827 if (NULL != vl->reassembly_map)
3828 {
3831 NULL);
3833 vl->reassembly_map = NULL;
3835 vl->reassembly_heap = NULL;
3836 }
3837 if (NULL != vl->reassembly_timeout_task)
3838 {
3840 vl->reassembly_timeout_task = NULL;
3841 }
3842 while (NULL != (pm = vl->pending_msg_head))
3843 {
3844 /* These never got transmitted, so #completed_pending_message() will not
3845 run for them and nobody else answers their SEND either. Return the
3846 window credit anyway: CORE keeps its `struct Neighbour' -- and thus
3847 the window -- until it sees our DISCONNECT, and #handle_client_send()
3848 deliberately tolerates a SEND for a link that is already gone, so a
3849 client can easily still be sending while we free this. */
3850 credit_client (pm);
3852 }
3855 if (NULL != vl->visibility_task)
3856 {
3858 vl->visibility_task = NULL;
3859 }
3860 if (NULL != vl->fc_retransmit_task)
3861 {
3863 vl->fc_retransmit_task = NULL;
3864 }
3865 while (NULL != (csc = vl->csc_head))
3866 {
3868 GNUNET_assert (vl == csc->vl);
3869 csc->vl = NULL;
3870 }
3871 if (NULL != vl->unconfirmed_timeout_task)
3872 {
3874 vl->unconfirmed_timeout_task = NULL;
3875 }
3876 if (NULL != vl->ic)
3877 {
3878 /* the closure of this iteration is @e sb_cls, released just below */
3880 vl->ic = NULL;
3881 }
3882 if (NULL != vl->sb_cls)
3883 {
3884 /* Cancels #burst_task if that task's closure is ours: it would
3885 otherwise run on this (freed) link. */
3886 free_burst_cls (vl->sb_cls);
3887 GNUNET_assert (NULL == vl->sb_cls);
3888 }
3889 GNUNET_free (vl->burst_addr);
3890 GNUNET_break (NULL == vl->n);
3891 GNUNET_break (NULL == vl->dv);
3892 GNUNET_free (vl);
3893}
3894
3895
3901static void
3903{
3904 if (NULL != vs->revalidation_task)
3905 {
3906 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3907 vs->revalidation_task = NULL;
3908 }
3909 /*memcpy (&hkey,
3910 &hc,
3911 sizeof (hkey));*/
3913 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3914 GNUNET_h2s (&vs->hc),
3915 vs->address,
3918 &vs->hc));
3921 GNUNET_YES ==
3924 vs->hn = NULL;
3925 if (NULL != vs->sc)
3926 {
3928 "store cancel\n");
3930 vs->sc = NULL;
3931 }
3932 GNUNET_free (vs->address);
3933 GNUNET_free (vs);
3934}
3935
3936
3943static struct Neighbour *
3948
3949
3956static struct VirtualLink *
3958{
3960}
3961
3962
3995
3996
4005static void
4007{
4008 struct Neighbour *n = dvh->next_hop;
4009 struct DistanceVector *dv = dvh->dv;
4010 struct PendingAcknowledgement *pa;
4011
4012 while (NULL != (pa = dvh->pa_head))
4013 {
4015 pa->dvh = NULL;
4016 }
4017 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
4019 GNUNET_free (dvh);
4020}
4021
4022
4029static void
4030check_link_down (void *cls);
4031
4032
4038static void
4040{
4042 "Informing CORE clients about disconnect from %s\n",
4043 GNUNET_i2s (pid));
4044 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4045 {
4046 struct GNUNET_MQ_Envelope *env;
4047 struct DisconnectInfoMessage *dim;
4048
4049 if (CT_CORE != tc->type)
4050 continue;
4052 dim->peer = *pid;
4053 GNUNET_MQ_send (tc->mq, env);
4054 }
4055}
4056
4057
4058static void
4059try_to_bring_link_up (const struct GNUNET_PeerIdentity *pid);
4060
4061
4084static void
4086{
4087 struct GNUNET_PeerIdentity target = vl->target;
4088
4089 for (struct PendingMessage *pm = vl->pending_msg_head;
4090 NULL != pm;
4091 pm = pm->next_vl)
4092 credit_client (pm);
4094 free_virtual_link (vl);
4095 /* Start getting it back now. Only #handle_validation_response() can
4096 rebuild it, and a successful validation parks @e revalidation_task just
4097 short of #ADDRESS_VALIDATION_LIFETIME -- four hours away. */
4098 try_to_bring_link_up (&target);
4099}
4100
4101
4108static void
4110{
4111 struct DistanceVectorHop *dvh;
4112 struct VirtualLink *vl;
4113
4114 while (NULL != (dvh = dv->dv_head))
4116
4118 GNUNET_YES ==
4120 if (NULL != (vl = dv->vl))
4121 {
4122 GNUNET_assert (dv == vl->dv);
4123 vl->dv = NULL;
4124 if (NULL == vl->n)
4125 {
4127 }
4128 else
4129 {
4130 /* @e visibility_task is NULL while #check_link_down() itself runs, and
4131 #GNUNET_SCHEDULER_cancel() dereferences its argument. */
4132 if (NULL != vl->visibility_task)
4135 }
4136 dv->vl = NULL;
4137 }
4138
4139 if (NULL != dv->timeout_task)
4140 {
4142 dv->timeout_task = NULL;
4143 }
4144 GNUNET_free (dv->km);
4145 GNUNET_free (dv);
4146}
4147
4148
4162static void
4164 const struct GNUNET_PeerIdentity *peer,
4165 const char *address,
4167 const struct MonitorEvent *me)
4168{
4169 struct GNUNET_MQ_Envelope *env;
4171 size_t addr_len = strlen (address) + 1;
4172
4174 addr_len,
4176 md->nt = htonl ((uint32_t) nt);
4177 md->peer = *peer;
4178 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
4179 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
4180 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
4181 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
4182 md->cs = htonl ((uint32_t) me->cs);
4183 md->num_msg_pending = htonl (me->num_msg_pending);
4184 md->num_bytes_pending = htonl (me->num_bytes_pending);
4185 memcpy (&md[1], address, addr_len);
4186 GNUNET_MQ_send (tc->mq, env);
4187}
4188
4189
4199static void
4201 const char *address,
4203 const struct MonitorEvent *me)
4204{
4205 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4206 {
4207 if (CT_MONITOR != tc->type)
4208 continue;
4209 if (tc->details.monitor.one_shot)
4210 continue;
4211 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
4212 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
4213 continue;
4215 }
4216}
4217
4218
4228static void *
4230 struct GNUNET_SERVICE_Client *client,
4231 struct GNUNET_MQ_Handle *mq)
4232{
4233 struct TransportClient *tc;
4234
4235 (void) cls;
4236 tc = GNUNET_new (struct TransportClient);
4237 tc->client = client;
4238 tc->mq = mq;
4241 "Client %p of type %u connected\n",
4242 tc,
4243 tc->type);
4244 return tc;
4245}
4246
4247
4248static enum GNUNET_GenericReturnValue
4250 const struct GNUNET_PeerIdentity *pid,
4251 void *value)
4252{
4253 struct TransportGlobalNattedAddress *tgna = value;
4254 (void) cls;
4255
4256 GNUNET_free (tgna);
4257
4258 return GNUNET_OK;
4259}
4260
4261
4268static void
4269free_neighbour (struct Neighbour *neighbour,
4270 enum GNUNET_GenericReturnValue drop_link)
4271{
4272 struct DistanceVectorHop *dvh;
4273 struct VirtualLink *vl;
4274
4275 GNUNET_assert (NULL == neighbour->queue_head);
4278 &neighbour->pid,
4279 neighbour));
4281 "Freeing neighbour\n");
4284 NULL);
4286 while (NULL != (dvh = neighbour->dv_head))
4287 {
4288 struct DistanceVector *dv = dvh->dv;
4289
4291 if (NULL == dv->dv_head)
4292 free_dv_route (dv);
4293 }
4294 if (NULL != neighbour->get)
4295 {
4297 neighbour->get = NULL;
4298 }
4299 if (NULL != neighbour->sc)
4300 {
4302 "store cancel\n");
4303 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
4304 neighbour->sc = NULL;
4305 }
4306 if (NULL != (vl = neighbour->vl))
4307 {
4308 GNUNET_assert (neighbour == vl->n);
4309 vl->n = NULL;
4310 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
4311 {
4313 }
4314 else
4315 {
4316 /* See #free_dv_route(): may be NULL under #check_link_down(). */
4317 if (NULL != vl->visibility_task)
4320 }
4321 neighbour->vl = NULL;
4322 }
4323 GNUNET_free (neighbour);
4324}
4325
4326
4333static void
4335 const struct GNUNET_PeerIdentity *pid)
4336{
4337 struct GNUNET_MQ_Envelope *env;
4338 struct ConnectInfoMessage *cim;
4339
4340 GNUNET_assert (CT_CORE == tc->type);
4342 cim->id = *pid;
4343 GNUNET_MQ_send (tc->mq, env);
4344}
4345
4346
4352static void
4354{
4356 "Informing CORE clients about connection to %s\n",
4357 GNUNET_i2s (pid));
4358 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4359 {
4360 if (CT_CORE != tc->type)
4361 continue;
4363 }
4364}
4365
4366
4374static void
4375transmit_on_queue (void *cls);
4376
4377
4386static unsigned int
4388{
4389 for (struct Queue *s = queue_head; NULL != s;
4390 s = s->next_neighbour)
4391 {
4392 if (s == queue)
4393 continue;
4394 if (s->tc->details.communicator.address_prefix !=
4395 queue->tc->details.communicator.address_prefix)
4396 {
4398 "queue address %s qid %u compare with queue: address %s qid %u\n",
4399 queue->address,
4400 queue->qid,
4401 s->address,
4402 s->qid);
4403 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
4404 (QUEUE_LENGTH_LIMIT > s->queue_length) )
4405 return GNUNET_YES;
4407 "Lower prio\n");
4408 }
4409 }
4410 return GNUNET_NO;
4411}
4412
4413
4420static void
4422
4423
4431static void
4433 struct Queue *queue,
4435{
4437
4438 if (queue->validated_until.abs_value_us < now.abs_value_us)
4439 return;
4441 queue->neighbour->queue_head))
4442 return;
4443
4444 if (queue->tc->details.communicator.total_queue_length >=
4446 {
4448 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
4449 queue->address,
4450 queue->qid);
4452 GST_stats,
4453 "# Transmission throttled due to communicator queue limit",
4454 1,
4455 GNUNET_NO);
4456 queue->idle = GNUNET_NO;
4457 /* @e total_queue_length is shared by every peer this communicator serves,
4458 so at the limit we can send to none of them, and the only things that
4459 lower it again are an ACK from the communicator, #free_queue() and
4460 #free_timedout_queue_entry(). If we got here because a peer stopped
4461 acknowledging, no ACK is coming; and we just declined to arm
4462 @e transmit_task, so #queue_send_msg() -- the *only* place that arms
4463 the sweeper -- will not run either. That leaves nothing at all to
4464 recover the count, and the communicator stays mute towards every peer
4465 until some unrelated queue happens to go down. Keep the sweeper
4466 going. */
4468 return;
4469 }
4470 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
4471 {
4473 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
4474 queue->address,
4475 queue->qid);
4477 "# Transmission throttled due to queue queue limit",
4478 1,
4479 GNUNET_NO);
4480 queue->idle = GNUNET_NO;
4481 /* Same reasoning as above, for the per-queue limit. */
4483 return;
4484 }
4485 if (0 == queue->q_capacity)
4486 {
4488 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
4489 PRIu64 ".\n",
4490 queue->address,
4491 queue->qid,
4492 queue->q_capacity);
4494 "# Transmission throttled due to message queue capacity",
4495 1,
4496 GNUNET_NO);
4497 queue->idle = GNUNET_NO;
4498 return;
4499 }
4500 /* queue might indeed be ready, schedule it */
4501 if (NULL != queue->transmit_task)
4502 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4503 queue->transmit_task =
4505 queue);
4507 "Considering transmission on queue `%s' QID %llu to %s\n",
4508 queue->address,
4509 (unsigned long long) queue->qid,
4510 GNUNET_i2s (&queue->neighbour->pid));
4511}
4512
4513
4514static void
4516 const char *address);
4517
4518
4525static void
4527{
4528 struct VirtualLink *vl = cls;
4529 struct DistanceVector *dv = vl->dv;
4530 struct Neighbour *n = vl->n;
4531 struct GNUNET_TIME_Absolute dvh_timeout;
4532 struct GNUNET_TIME_Absolute q_timeout;
4533
4535 "Checking if link is down\n");
4536 vl->visibility_task = NULL;
4537 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4538 if (NULL != dv)
4539 {
4540 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4541 pos = pos->next_dv)
4542 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4543 pos->path_valid_until);
4544 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4545 {
4546 vl->dv->vl = NULL;
4547 vl->dv = NULL;
4548 }
4549 }
4550 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4551 /* NOTE: @e n may be NULL here: #free_neighbour() clears vl->n and then
4552 schedules us when the link still has a DV route. */
4553 if (NULL != n)
4554 {
4555 struct GNUNET_TIME_Absolute liveness_deadline;
4556
4557 /* A successful validation is good for #ADDRESS_VALIDATION_LIFETIME (four
4558 hours). Do not take a communicator's word for that long: cap what the
4559 queues are worth by how recently this neighbour actually said anything
4560 to us. Otherwise a communicator that stops working without sending a
4561 QUEUE_TEARDOWN keeps this link -- and CORE's idea of the connection --
4562 alive until the validation expires. */
4563 liveness_deadline = GNUNET_TIME_absolute_add (n->last_inbound,
4565 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4566 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4567 if (GNUNET_TIME_absolute_cmp (liveness_deadline, <, q_timeout))
4568 {
4569 if (0 ==
4571 {
4572 /* Only reachable if a communicator failed to tear its queue down. */
4574 "Neighbour %s was silent for %s while its communicator "
4575 "kept claiming the queue works; treating link as down\n",
4576 GNUNET_i2s (&vl->target),
4579 GNUNET_YES));
4581 "# links dropped (neighbour silent)",
4582 1,
4583 GNUNET_NO);
4584 }
4585 q_timeout = liveness_deadline;
4586 }
4587 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
4588 {
4589 vl->n->vl = NULL;
4590 vl->n = NULL;
4591 }
4592 }
4593 if ((NULL == vl->n) && (NULL == vl->dv))
4594 {
4596 /* @e n (if any) outlives the link, and so do its queues: the liveness cap
4597 above drops a link whose addresses are still well inside
4598 #ADDRESS_VALIDATION_LIFETIME. In that state nothing would ever ask for
4599 a fresh challenge -- @e revalidation_task does not fire until the four
4600 hour validity is nearly over, and the HELLO path reaches
4601 #start_address_validation() only to find an address that still counts
4602 as valid. Since #handle_validation_response() is the only thing that
4603 can rebuild this link and tell CORE about the peer again, ask for that
4604 validation now, or CORE never hears about this peer again. */
4605 if (NULL != n)
4606 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4607 start_address_validation (&n->pid, q->address);
4608 return;
4609 }
4610 vl->visibility_task =
4611 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4613 vl);
4614}
4615
4616
4622static void
4624{
4625 struct Neighbour *neighbour = queue->neighbour;
4626 struct TransportClient *tc = queue->tc;
4627 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4629 struct QueueEntry *qe;
4630 int maxxed;
4631 struct PendingAcknowledgement *pa;
4632 struct VirtualLink *vl;
4633
4635 "Cleaning up queue %u\n", queue->qid);
4636 if (NULL != queue->mo)
4637 {
4639 queue->mo = NULL;
4640 }
4641 if (NULL != queue->transmit_task)
4642 {
4643 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4644 queue->transmit_task = NULL;
4645 }
4646 while (NULL != (pa = queue->pa_head))
4647 {
4648 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4649 pa->queue = NULL;
4650 }
4651
4653 neighbour->queue_head,
4654 neighbour->queue_tail,
4655 queue);
4657 tc->details.communicator.queue_head,
4658 tc->details.communicator.queue_tail,
4659 queue);
4661 tc->details.communicator.total_queue_length);
4663 "Cleaning up queue with length %u\n",
4664 queue->queue_length);
4665 while (NULL != (qe = queue->queue_head))
4666 {
4667 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4668 queue->queue_length--;
4669 tc->details.communicator.total_queue_length--;
4670 if (NULL != qe->pm)
4671 {
4672 GNUNET_assert (qe == qe->pm->qe);
4673 qe->pm->qe = NULL;
4674 }
4675 GNUNET_free (qe);
4676 }
4677 GNUNET_assert (0 == queue->queue_length);
4678 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4679 tc->details.communicator.total_queue_length))
4680 {
4681 /* Communicator dropped below threshold, resume all _other_ queues */
4683 GST_stats,
4684 "# Transmission throttled due to communicator queue limit",
4685 -1,
4686 GNUNET_NO);
4687 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4688 s = s->next_client)
4690 s,
4692 }
4693 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4695
4696 vl = lookup_virtual_link (&neighbour->pid);
4697 if ((NULL != vl) && (neighbour == vl->n))
4698 {
4699 /* See #free_dv_route(): may be NULL under #check_link_down(), which is
4700 also what clears it -- so the call below needs no re-arm here. */
4701 if (NULL != vl->visibility_task)
4703 vl->visibility_task = NULL;
4704 check_link_down (vl);
4705 }
4706 if (NULL == neighbour->queue_head)
4707 {
4708 free_neighbour (neighbour, GNUNET_NO);
4709 }
4710}
4711
4712
4720static void
4722
4723
4729static void
4731{
4732 struct TransportClient *tc = ale->tc;
4733
4734 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4735 tc->details.communicator.addr_tail,
4736 ale);
4737 /* Cancels @e sc, @e shc and the pending PILS signature request, all of
4738 which would otherwise run their callbacks on this freed entry. */
4740 if (NULL != ale->sc)
4741 {
4743 "store cancel\n");
4745 ale->sc = NULL;
4746 }
4747 if (NULL != ale->shc)
4748 {
4750 ale->shc = NULL;
4751 }
4752 if (NULL != ale->st)
4753 {
4755 ale->st = NULL;
4756 }
4757 if (NULL != ale->signed_address)
4759 GNUNET_free (ale);
4760}
4761
4762
4771static int
4773 const struct GNUNET_PeerIdentity *pid,
4774 void *value)
4775{
4776 struct TransportClient *tc = cls;
4777 struct PeerRequest *pr = value;
4778
4779 if (NULL != pr->retry_task)
4780 {
4781 GNUNET_SCHEDULER_cancel (pr->retry_task);
4782 pr->retry_task = NULL;
4783 }
4784 if (NULL != pr->nc)
4786 pr->nc = NULL;
4788 GNUNET_YES ==
4789 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4790 pid,
4791 pr));
4792 GNUNET_free (pr);
4793
4794 return GNUNET_OK;
4795}
4796
4797
4798static void
4799do_shutdown (void *cls);
4800
4801
4811static enum GNUNET_GenericReturnValue
4813 const struct GNUNET_PeerIdentity *pid,
4814 void *value)
4815{
4816 const struct TransportClient *tc = cls;
4817 struct VirtualLink *vl = value;
4818
4819 (void) pid;
4820 for (struct CommunicatorMessageContext *cmc = vl->cmc_head;
4821 NULL != cmc;
4822 cmc = cmc->next)
4823 if (tc == cmc->tc)
4824 cmc->tc = NULL;
4825 return GNUNET_OK;
4826}
4827
4828
4838static enum GNUNET_GenericReturnValue
4840 const struct GNUNET_PeerIdentity *pid,
4841 void *value)
4842{
4843 const struct TransportClient *tc = cls;
4844 struct Backtalker *b = value;
4845
4846 (void) pid;
4847 if ((NULL != b->cmc) && (tc == b->cmc->tc))
4848 b->cmc->tc = NULL;
4849 return GNUNET_OK;
4850}
4851
4852
4871static void
4873{
4876 (void *) tc);
4879 (void *) tc);
4880 for (unsigned int i = 0; i < RING_BUFFER_SIZE; i++)
4881 if ((NULL != ring_buffer[i]) &&
4882 (tc == ring_buffer[i]->cmc->tc))
4883 ring_buffer[i]->cmc->tc = NULL;
4884}
4885
4886
4895static void
4897 struct GNUNET_SERVICE_Client *client,
4898 void *app_ctx)
4899{
4900 struct TransportClient *tc = app_ctx;
4901
4902 (void) cls;
4903 (void) client;
4905 switch (tc->type)
4906 {
4907 case CT_NONE:
4909 "Unknown Client %p disconnected, cleaning up.\n",
4910 tc);
4911 break;
4912
4913 case CT_CORE: {
4914 struct PendingMessage *pm;
4916 "CORE Client %p disconnected, cleaning up.\n",
4917 tc);
4918
4919
4920 while (NULL != (pm = tc->details.core.pending_msg_head))
4921 {
4923 tc->details.core.pending_msg_head,
4924 tc->details.core.pending_msg_tail,
4925 pm);
4926 pm->client = NULL;
4927 }
4928 }
4929 break;
4930
4931 case CT_MONITOR:
4933 "MONITOR Client %p disconnected, cleaning up.\n",
4934 tc);
4935
4936 break;
4937
4938 case CT_COMMUNICATOR: {
4939 struct Queue *q;
4940 struct AddressListEntry *ale;
4941
4943 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4944 tc);
4945
4946 /* MUST come first: freeing the queues below can tear a virtual link
4947 down, and #free_virtual_link() releases the cmcs parked on it. */
4949 if (NULL != tc->details.communicator.free_queue_entry_task)
4951 tc->details.communicator.free_queue_entry_task);
4952 while (NULL != (q = tc->details.communicator.queue_head))
4953 free_queue (q);
4954 while (NULL != (ale = tc->details.communicator.addr_head))
4956 GNUNET_free (tc->details.communicator.address_prefix);
4957 }
4958 break;
4959
4960 case CT_APPLICATION:
4962 "APPLICATION Client %p disconnected, cleaning up.\n",
4963 tc);
4964
4965 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4967 tc);
4968 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4969 break;
4970 }
4971 GNUNET_free (tc);
4972 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4973 {
4975 "Our last client disconnected\n");
4976 do_shutdown (cls);
4977 }
4978}
4979
4980
4990static int
4992 const struct GNUNET_PeerIdentity *pid,
4993 void *value)
4994{
4995 struct TransportClient *tc = cls;
4996 struct VirtualLink *vl = value;
4997
4998 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4999 return GNUNET_OK;
5000
5002 "Telling new CORE client about existing connection to %s\n",
5003 GNUNET_i2s (pid));
5005 return GNUNET_OK;
5006}
5007
5008
5014static void
5016 unsigned
5017 int free_cmc);
5018
5019static enum GNUNET_GenericReturnValue
5021 const struct GNUNET_PeerIdentity *pid,
5022 void *value)
5023{
5024 struct VirtualLink *vl = value;
5025 struct CommunicatorMessageContext *cmc;
5026
5027 /* resume communicators */
5028 while (NULL != (cmc = vl->cmc_tail))
5029 release_stalled_cmc (vl, cmc);
5030 if (NULL != vl->core_fc_stall_task)
5031 {
5033 vl->core_fc_stall_task = NULL;
5034 }
5035 /* A CORE client that just attached has nothing outstanding, so give it a
5036 full window. The RECV_OKs that would have returned the credit spent by
5037 its predecessor died with that client, and #handle_client_recv_ok() is
5038 the only thing that ever raises this counter -- so without the reset
5039 every message on this link takes the "CORE ran out of window" path from
5040 here on, and only #core_fc_stalled() (after CORE_FC_STALL_TIMEOUT, and
5041 once per round) ever lets any through. */
5043 return GNUNET_OK;
5044}
5045
5046
5055static void
5056handle_client_start (void *cls, const struct StartMessage *start)
5057{
5058 // const struct GNUNET_PeerIdentity *my_identity;
5059 struct TransportClient *tc = cls;
5060 // uint32_t options;
5061 //
5062 // my_identity = GNUNET_PILS_get_identity (pils);
5063 // GNUNET_assert (my_identity);
5064 //
5065 // FIXME ignore the check of the peer ids for now.
5066 // (also deprecate the old way of obtaining our own peer ID)
5067 // options = ntohl (start->options);
5068 // if ((0 != (1 & options)) &&
5069 // (0 != GNUNET_memcmp (&start->self, my_identity)))
5070 // {
5071 // /* client thinks this is a different peer, reject */
5072 // GNUNET_break (0);
5073 // GNUNET_SERVICE_client_drop (tc->client);
5074 // return;
5075 // }
5076 if (CT_NONE != tc->type)
5077 {
5078 GNUNET_break (0);
5080 return;
5081 }
5082 tc->type = CT_CORE;
5084 "New CORE client with PID %s registered\n",
5085 GNUNET_i2s (&start->self));
5088 tc);
5091 NULL);
5093}
5094
5095
5102static int
5103check_client_send (void *cls, const struct OutboundMessage *obm)
5104{
5105 struct TransportClient *tc = cls;
5106 uint16_t size;
5107 const struct GNUNET_MessageHeader *obmm;
5108
5109 if (CT_CORE != tc->type)
5110 {
5111 GNUNET_break (0);
5112 return GNUNET_SYSERR;
5113 }
5114 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
5115 if (size < sizeof(struct GNUNET_MessageHeader))
5116 {
5117 GNUNET_break (0);
5118 return GNUNET_SYSERR;
5119 }
5120 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5121 if (size != ntohs (obmm->size))
5122 {
5123 GNUNET_break (0);
5124 return GNUNET_SYSERR;
5125 }
5126 return GNUNET_OK;
5127}
5128
5129
5137static void
5139{
5140 struct TransportClient *tc = pm->client;
5141 struct VirtualLink *vl = pm->vl;
5142
5144 "client send response\n");
5145 if (NULL != tc)
5146 {
5148 "Confirming transmission of <%" PRIu64 "> to %s\n",
5149 pm->logging_uuid,
5150 GNUNET_i2s (&vl->target));
5151 credit_client (pm);
5152 }
5154}
5155
5156
5166static unsigned int
5169 struct DistanceVectorHop **hops_array,
5170 unsigned int hops_array_length)
5171{
5172 uint64_t choices[hops_array_length];
5173 uint64_t num_dv;
5174 unsigned int dv_count;
5175
5176 /* Pick random vectors, but weighted by distance, giving more weight
5177 to shorter vectors */
5178 num_dv = 0;
5179 dv_count = 0;
5180 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5181 pos = pos->next_dv)
5182 {
5183 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
5184 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
5185 .rel_value_us == 0))
5186 continue; /* pos unconfirmed and confirmed required */
5187 /* A hop at (or past) the limit has weight zero -- past it, unsigned
5188 arithmetic makes the weight huge. Either way it can never be picked
5189 below, so it must not be counted: the sampling loop draws
5190 @a hops_array_length distinct values out of @e num_dv, and counting a
5191 hop that contributes nothing to @e num_dv can leave it with fewer
5192 values than draws, which never terminates. #learn_dv_path() caps
5193 @e distance well below the limit today, so this is defence in depth. */
5194 if (pos->distance >= MAX_DV_HOPS_ALLOWED)
5195 continue;
5196 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
5197 dv_count++;
5198 }
5199 if (0 == dv_count)
5200 return 0;
5201 if (dv_count <= hops_array_length)
5202 {
5203 dv_count = 0;
5204 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5205 pos = pos->next_dv)
5206 hops_array[dv_count++] = pos;
5207 return dv_count;
5208 }
5209 for (unsigned int i = 0; i < hops_array_length; i++)
5210 {
5211 int ok = GNUNET_NO;
5212 unsigned int tries = 0;
5213
5214 while (GNUNET_NO == ok)
5215 {
5216 choices[i] =
5217 GNUNET_CRYPTO_random_u64 (num_dv);
5218 ok = GNUNET_YES;
5219 for (unsigned int j = 0; j < i; j++)
5220 if (choices[i] == choices[j])
5221 {
5222 ok = GNUNET_NO;
5223 break;
5224 }
5225 /* Give up rather than spin: with weight >= 2 per hop the expected
5226 number of draws per pick is below four, so this many failures is a
5227 set we cannot sample distinctly. Returning fewer paths is a routing
5228 nuisance, hanging here is a deaf service; and a duplicated choice
5229 would at worst repeat a path, so stopping is safe. */
5230 if (MAX_DV_PICK_TRIES < ++tries)
5231 break;
5232 }
5233 if (GNUNET_NO == ok)
5234 {
5235 hops_array_length = i;
5236 break;
5237 }
5238 }
5239 dv_count = 0;
5240 num_dv = 0;
5241 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5242 pos = pos->next_dv)
5243 {
5244 uint64_t delta;
5245
5246 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
5247 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
5248 .rel_value_us == 0))
5249 continue; /* pos unconfirmed and confirmed required */
5250 if (pos->distance >= MAX_DV_HOPS_ALLOWED)
5251 continue; /* zero weight: not counted in @e num_dv above either */
5252 delta = MAX_DV_HOPS_ALLOWED - pos->distance;
5253 for (unsigned int i = 0; i < hops_array_length; i++)
5254 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
5255 hops_array[dv_count++] = pos;
5256 num_dv += delta;
5257 }
5258 return dv_count;
5259}
5260
5261
5268static int
5270 void *cls,
5272{
5273 struct TransportClient *tc = cls;
5274 uint16_t size;
5275
5276 if (CT_NONE != tc->type)
5277 {
5278 GNUNET_break (0);
5279 return GNUNET_SYSERR;
5280 }
5281 tc->type = CT_COMMUNICATOR;
5282 size = ntohs (cam->header.size) - sizeof(*cam);
5283 if (0 == size)
5284 return GNUNET_OK; /* receive-only communicator */
5286 return GNUNET_OK;
5287}
5288
5289
5301static void
5303{
5304 struct GNUNET_MQ_Envelope *env;
5306
5307 if (GNUNET_YES == cmc->ack_sent)
5308 return;
5309 cmc->ack_sent = GNUNET_YES;
5310 if (NULL == cmc->tc)
5311 return; /* communicator is gone, see #detach_cmcs_from_client() */
5312 if (0 == ntohl (cmc->im.fc_on))
5313 return; /* communicator did not ask for flow control */
5315 "Acknowledge message with flow control id %" PRIu64 "\n",
5316 cmc->im.fc_id);
5318 ack->reserved = htonl (0);
5319 ack->fc_id = cmc->im.fc_id;
5320 ack->sender = cmc->im.neighbour_sender;
5321 GNUNET_MQ_send (cmc->tc->mq, env);
5322}
5323
5324
5335static void
5337{
5338 if (GNUNET_YES == cmc->client_resumed)
5339 return;
5341 if (NULL == cmc->tc)
5342 return; /* communicator is gone, see #detach_cmcs_from_client() */
5344}
5345
5346
5355static void
5357 unsigned
5358 int free_cmc)
5359{
5360 send_cmc_ack (cmc);
5361 resume_cmc_client (cmc);
5362 if (GNUNET_YES == free_cmc)
5363 {
5364 GNUNET_free (cmc);
5365 }
5366}
5367
5368
5369static void
5378
5379
5380static void
5385
5386
5396static void
5397handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
5398{
5399 struct TransportClient *tc = cls;
5400 struct VirtualLink *vl;
5401 uint32_t delta;
5402 struct CommunicatorMessageContext *cmc;
5403
5404 if (CT_CORE != tc->type)
5405 {
5406 GNUNET_break (0);
5408 return;
5409 }
5410 vl = lookup_virtual_link (&rom->peer);
5411 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5412 {
5414 "# RECV_OK dropped: virtual link unknown",
5415 1,
5416 GNUNET_NO);
5418 return;
5419 }
5420 delta = ntohl (rom->increase_window_delta);
5421 vl->core_recv_window += delta;
5423 "CORE ack receiving message, increased CORE recv window to %d\n",
5424 vl->core_recv_window);
5426 if (vl->core_recv_window <= 0)
5427 return;
5428 /* release the flow control credit we withheld from the communicators */
5429 while (NULL != (cmc = vl->cmc_tail))
5430 release_stalled_cmc (vl, cmc);
5431 if (NULL != vl->core_fc_stall_task)
5432 {
5434 vl->core_fc_stall_task = NULL;
5435 }
5436}
5437
5438
5445static void
5447 void *cls,
5449{
5450 const struct GNUNET_PeerIdentity *my_identity;
5451 struct TransportClient *tc = cls;
5452 uint16_t size;
5453
5454 size = ntohs (cam->header.size) - sizeof(*cam);
5455 if (0 == size)
5456 {
5458 "Receive-only communicator connected\n");
5459 /* Receive-only communicator: it has no address prefix, but we still
5460 MUST resume the client or we will never read from it again. Use an
5461 empty prefix so that the various strcmp()s do not see NULL. */
5462 tc->details.communicator.address_prefix = GNUNET_strdup ("");
5464 return;
5465 }
5466 tc->details.communicator.address_prefix =
5467 GNUNET_strdup ((const char *) &cam[1]);
5468 tc->details.communicator.cc = ntohl (cam->cc);
5469 tc->details.communicator.can_burst = ntohl (cam->can_burst);
5471 if (NULL != my_identity)
5472 {
5474 "Communicator for peer %s with prefix '%s' connected %s\n",
5476 tc->details.communicator.address_prefix,
5477 tc->details.communicator.can_burst ? "can burst" :
5478 "can not burst");
5479 }
5480 else
5481 {
5483 "Communicator for local peer with prefix '%s' connected %s\n",
5484 tc->details.communicator.address_prefix,
5485 tc->details.communicator.can_burst ? "can burst" :
5486 "can not burst");
5487 }
5489}
5490
5491
5499static int
5501 void *cls,
5503{
5504 const struct GNUNET_MessageHeader *inbox;
5505 const char *is;
5506 uint16_t msize;
5507 uint16_t isize;
5508
5509 (void) cls;
5510 msize = ntohs (cb->header.size) - sizeof(*cb);
5511 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
5512 /* MUST bound the buffer before dereferencing @a inbox. */
5513 if (msize <= sizeof(struct GNUNET_MessageHeader))
5514 {
5515 GNUNET_break (0);
5516 return GNUNET_SYSERR;
5517 }
5518 isize = ntohs (inbox->size);
5519 if (isize >= msize)
5520 {
5521 GNUNET_break (0);
5522 return GNUNET_SYSERR;
5523 }
5524 is = (const char *) inbox;
5525 is += isize;
5526 msize -= isize;
5527 GNUNET_assert (0 < msize);
5528 if ('\0' != is[msize - 1])
5529 {
5530 GNUNET_break (0);
5531 return GNUNET_SYSERR;
5532 }
5533 return GNUNET_OK;
5534}
5535
5536
5551static enum GNUNET_GenericReturnValue
5566
5567
5568static void
5570 struct TransportClient *tc);
5571
5572
5573static void
5575{
5576 struct TransportClient *tc = cls;
5578
5580 "freeing timedout queue entries\n");
5581
5582 tc->details.communicator.free_queue_entry_task = NULL;
5583 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
5584 queue = queue->next_client)
5585 {
5586 struct QueueEntry *qep = queue->queue_head;
5587
5589 "checking QID %u for timedout queue entries\n",
5590 queue->qid);
5591 while (NULL != qep)
5592 {
5593 struct QueueEntry *pos = qep;
5595 pos->creation_timestamp, now);
5596 qep = qep->next;
5597
5599 "diff to now %s \n",
5602 {
5604 "Freeing timed out QueueEntry with MID %" PRIu64
5605 " and QID %u\n",
5606 pos->mid,
5607 queue->qid);
5609 "# QueueEntries timed out",
5610 1,
5611 GNUNET_NO);
5612 free_queue_entry (pos, tc);
5613 }
5614 }
5615 }
5616 /* Entries younger than #QUEUE_ENTRY_TIMEOUT are still to be reclaimed, and
5617 this task used to be a one-shot armed only by #queue_send_msg(). So the
5618 sweep that was supposed to bound how long an unacknowledged entry holds
5619 its slot only ever ran while *new* messages were being queued -- exactly
5620 not the case once the throttles in #schedule_transmit_on_queue() have
5621 stopped transmission. Keep going as long as anything is outstanding. */
5623}
5624
5625
5626static void
5628{
5629 if (NULL != tc->details.communicator.free_queue_entry_task)
5630 return;
5631 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
5632 queue = queue->next_client)
5633 {
5634 if (NULL == queue->queue_head)
5635 continue;
5636 tc->details.communicator.free_queue_entry_task =
5639 tc);
5640 return;
5641 }
5642}
5643
5644
5654static void
5656 struct PendingMessage *pm,
5657 const void *payload,
5658 size_t payload_size)
5659{
5660 struct Neighbour *n = queue->neighbour;
5662 struct GNUNET_MQ_Envelope *env;
5663 struct PendingAcknowledgement *pa;
5664
5665 GNUNET_log (
5667 "Queueing %u bytes of payload for transmission <%" PRIu64
5668 "> on queue %llu to %s\n",
5669 (unsigned int) payload_size,
5670 (NULL == pm) ? 0 : pm->logging_uuid,
5671 (unsigned long long) queue->qid,
5672 GNUNET_i2s (&queue->neighbour->pid));
5673 env = GNUNET_MQ_msg_extra (smt,
5674 payload_size,
5676 smt->qid = htonl (queue->qid);
5677 smt->mid = GNUNET_htonll (queue->mid_gen);
5678 smt->receiver = n->pid;
5679 memcpy (&smt[1], payload, payload_size);
5680 {
5681 /* Pass the env to the communicator of queue for transmission. */
5682 struct QueueEntry *qe;
5683
5684 qe = GNUNET_new (struct QueueEntry);
5685 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
5686 qe->mid = queue->mid_gen;
5688 "Create QueueEntry with MID %" PRIu64
5689 " and QID %u and prefix %s\n",
5690 qe->mid,
5691 queue->qid,
5692 queue->tc->details.communicator.address_prefix);
5693 queue->mid_gen++;
5694 qe->queue = queue;
5695 if (NULL != pm)
5696 {
5697 qe->pm = pm;
5698 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
5699 // GNUNET_assert (NULL == pm->qe);
5700 if (NULL != pm->qe)
5701 {
5703 "Retransmitting message <%" PRIu64
5704 "> remove pm from qe with MID: %llu \n",
5706 (unsigned long long) pm->qe->mid);
5707 pm->qe->pm = NULL;
5708 }
5709 pm->qe = qe;
5710 }
5711 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
5712 if (0 == queue->q_capacity)
5713 {
5714 // Messages without FC or fragments can get here.
5715 if (NULL != pm)
5716 {
5718 "Message %" PRIu64
5719 " (pm type %u) was not send because queue has no capacity.\n",
5721 pm->pmt);
5722 pm->qe = NULL;
5723 }
5724 GNUNET_free (env);
5725 GNUNET_free (qe);
5726 return;
5727 }
5728 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
5729 queue->queue_length++;
5730 queue->tc->details.communicator.total_queue_length++;
5731 if (GNUNET_NO == queue->unlimited_length)
5732 queue->q_capacity--;
5734 "Queue %s with qid %u has capacity %" PRIu64 "\n",
5735 queue->address,
5736 queue->qid,
5737 queue->q_capacity);
5739 queue->tc->details.communicator.total_queue_length)
5740 queue->idle = GNUNET_NO;
5741 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
5742 queue->idle = GNUNET_NO;
5743 if (0 == queue->q_capacity)
5744 queue->idle = GNUNET_NO;
5745
5746 if (GNUNET_NO == queue->idle)
5748 if (NULL != pm)
5749 {
5750 /* NOTE: @e next_pa was never the link of this list -- nothing ever
5751 assigned it, so it was NULL on every entry. The MDLL that
5752 #prepare_pending_acknowledgement() inserts into is keyed `pm', and
5753 thus threaded through @e next_pm. Walking @e next_pa dereferenced
5754 NULL the moment the head was not the entry we wanted. */
5755 for (pa = pm->pa_head; NULL != pa; pa = pa->next_pm)
5756 if (pm == pa->pm)
5757 {
5758 pa->num_send++;
5759 break;
5760 }
5761 }
5762 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
5764 "Sending message MID %" PRIu64
5765 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
5766 PRIu64 "\n",
5767 GNUNET_ntohll (smt->mid),
5768 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
5769 ntohs (smt->header.size),
5770 (unsigned long) payload_size,
5771 queue->tc->mq,
5772 queue->address,
5773 queue->qid,
5774 (NULL == pm) ? 0 : pm->logging_uuid);
5775 GNUNET_MQ_send (queue->tc->mq, env);
5776 }
5777}
5778
5779
5790static struct GNUNET_TIME_Relative
5792 const struct GNUNET_MessageHeader *hdr,
5794{
5795 struct GNUNET_TIME_Absolute now;
5796 unsigned int candidates;
5797 unsigned int sel1;
5798 unsigned int sel2;
5799 struct GNUNET_TIME_Relative rtt;
5800
5801 /* Pick one or two 'random' queues from n (under constraints of options) */
5802 now = GNUNET_TIME_absolute_get ();
5803 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
5804 weight in the future; weight could be assigned by observed
5805 bandwidth (note: not sure if we should do this for this type
5806 of control traffic though). */
5807 candidates = 0;
5808 for (struct Queue *pos = n->queue_head; NULL != pos;
5809 pos = pos->next_neighbour)
5810 {
5811 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5812 (pos->validated_until.abs_value_us > now.abs_value_us))
5813 candidates++;
5814 }
5815 if (0 == candidates)
5816 {
5817 /* This can happen rarely if the last confirmed queue timed
5818 out just as we were beginning to process this message. */
5820 "Could not route message of type %u to %s: no valid queue\n",
5821 ntohs (hdr->type),
5822 GNUNET_i2s (&n->pid));
5824 "# route selection failed (all no valid queue)",
5825 1,
5826 GNUNET_NO);
5828 }
5829
5831 sel1 = GNUNET_CRYPTO_random_u32 (candidates);
5832 if (0 == (options & RMO_REDUNDANT))
5833 sel2 = candidates; /* picks none! */
5834 else
5835 sel2 = GNUNET_CRYPTO_random_u32 (candidates);
5836 candidates = 0;
5837 for (struct Queue *pos = n->queue_head; NULL != pos;
5838 pos = pos->next_neighbour)
5839 {
5840 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5841 (pos->validated_until.abs_value_us > now.abs_value_us))
5842 {
5843 if ((sel1 == candidates) || (sel2 == candidates))
5844 {
5846 "Routing message of type %u to %s using %s (#%u)\n",
5847 ntohs (hdr->type),
5848 GNUNET_i2s (&n->pid),
5849 pos->address,
5850 (sel1 == candidates) ? 1 : 2);
5851 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5852 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5853 }
5854 candidates++;
5855 }
5856 }
5857 return rtt;
5858}
5859
5860
5871typedef void (*DVMessageHandler) (void *cls,
5872 struct Neighbour *next_hop,
5873 const struct GNUNET_MessageHeader *hdr,
5875
5890static struct GNUNET_TIME_Relative
5892 unsigned int num_dvhs,
5893 struct DistanceVectorHop **dvhs,
5894 const struct GNUNET_MessageHeader *hdr,
5895 DVMessageHandler use,
5896 void *use_cls,
5898 enum GNUNET_GenericReturnValue without_fc)
5899{
5900 const struct GNUNET_PeerIdentity *my_identity;
5901 struct TransportDVBoxMessage box_hdr;
5902 struct TransportDVBoxPayloadP *payload_hdr;
5903 uint16_t body_len_hbo = ntohs (hdr->size);
5904 unsigned char pt[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5906 unsigned char ct[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5908 struct GNUNET_TIME_Relative rtt;
5910
5911 payload_hdr = (struct TransportDVBoxPayloadP*) pt;
5914
5915 /* Encrypt payload */
5916 memset (&box_hdr, 0, sizeof (box_hdr));
5918 box_hdr.total_hops = htons (0);
5919 box_hdr.without_fc = htonl (without_fc);
5920 // update_ephemeral (dv);
5921 if ((0 ==
5922 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5923 || (NULL == dv->km))
5924 {
5925 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5926 &dv->ephemeral_key,
5927 (struct GNUNET_ShortHashCode*) &km);
5928 GNUNET_free (dv->km); /* do not leak the previous key material */
5929 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5930 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5931 if (GNUNET_OK != sign_ephemeral (dv))
5932 {
5933 /* Without a matching signature the box is undecryptable noise to the
5934 receiver; do not spend the bandwidth. Expire the ephemeral so the
5935 next attempt re-derives and re-signs rather than reusing it. */
5936 dv->ephemeral_validity = GNUNET_TIME_UNIT_ZERO_ABS;
5938 }
5939 }
5940 else
5941 {
5942 /* The ephemeral key is still valid, so reuse the cached key material.
5943 Without this @a km stayed UNINITIALISED stack memory and the
5944 receiver could not decrypt the box. */
5945 GNUNET_memcpy (&km, dv->km, sizeof(struct GNUNET_ShortHashCode));
5946 }
5947 box_hdr.ephemeral_key = dv->ephemeral_key;
5948 payload_hdr->sender_sig = dv->sender_sig;
5949 memcpy (&payload_hdr[1], hdr, body_len_hbo);
5951 sizeof(box_hdr.iv));
5952 payload_hdr->sender = *my_identity;
5953 payload_hdr->monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5954 GNUNET_CRYPTO_aead_encrypt (sizeof pt,
5955 pt,
5956 0,
5957 NULL,
5958 &km,
5959 &box_hdr.iv,
5960 ct,
5961 &box_hdr.mac);
5963 /* For each selected path, take the pre-computed header and body
5964 and add the path in the middle of the message; then send it. */
5965 for (unsigned int i = 0; i < num_dvhs; i++)
5966 {
5967 struct DistanceVectorHop *dvh = dvhs[i];
5968 unsigned int num_hops = dvh->distance + 1;
5969 char buf[sizeof(struct TransportDVBoxMessage)
5970 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5971 + sizeof(struct TransportDVBoxPayloadP)
5972 + body_len_hbo] GNUNET_ALIGN;
5973 struct GNUNET_PeerIdentity *dhops;
5974
5975 box_hdr.header.size = htons (sizeof(buf));
5976 box_hdr.orig_size = htons (sizeof(buf));
5977 box_hdr.num_hops = htons (num_hops);
5978 memcpy (buf, &box_hdr, sizeof(box_hdr));
5979 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5980 memcpy (dhops,
5981 dvh->path,
5982 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5983 dhops[dvh->distance] = dv->target;
5984 if (GNUNET_EXTRA_LOGGING > 0)
5985 {
5986 char *path;
5987
5989 for (unsigned int j = 0; j < num_hops; j++)
5990 {
5991 char *tmp;
5992
5993 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5994 GNUNET_free (path);
5995 path = tmp;
5996 }
5998 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5999 ntohs (hdr->type),
6000 GNUNET_i2s (&dv->target),
6001 i + 1,
6002 num_dvhs,
6003 path);
6004 GNUNET_free (path);
6005 }
6006 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
6007 memcpy (&dhops[num_hops], ct, sizeof(ct));
6008 use (use_cls,
6009 dvh->next_hop,
6010 (const struct GNUNET_MessageHeader *) buf,
6011 options);
6012 }
6013 return rtt;
6014}
6015
6016
6026static void
6028 struct Neighbour *next_hop,
6029 const struct GNUNET_MessageHeader *hdr,
6031{
6032 (void) cls;
6033 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
6034}
6035
6036
6048static struct GNUNET_TIME_Relative
6050// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
6051 const struct GNUNET_MessageHeader *hdr,
6053{
6054 // struct VirtualLink *vl;
6055 struct Neighbour *n;
6056 struct DistanceVector *dv;
6057 struct GNUNET_TIME_Relative rtt1;
6058 struct GNUNET_TIME_Relative rtt2;
6059 const struct GNUNET_PeerIdentity *target = &vl->target;
6060
6062 "Trying to route message of type %u to %s without fc\n",
6063 ntohs (hdr->type),
6064 GNUNET_i2s (target));
6065
6066 // TODO Do this elsewhere. vl should be given as parameter to method.
6067 // vl = lookup_virtual_link (target);
6068 /* An unconfirmed link is allowed here: it has no @e n and no @e dv of its
6069 own, so the "confirmed required" branch below resolves the route from
6070 #neighbours / #dv_routes. Refusing to route at all is what deadlocks a
6071 pair of peers, see #consider_sending_fc(). */
6072 GNUNET_assert (NULL != vl);
6073 n = vl->n;
6074 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
6075 /* An unconfirmed link has neither @e n nor @e dv of its own, so resolve
6076 the route from #neighbours / #dv_routes. This used to be done only
6077 while #RMO_UNCONFIRMED_ALLOWED was *not* set -- exactly backwards: with
6078 the flag set (the caller that needs it most) we would find no route at
6079 all and drop the message. Whether an unvalidated queue or an
6080 unvalidated path may then be used is still decided by @a options, in
6081 #route_via_neighbour() and #pick_random_dv_hops(). */
6082 if (NULL == n)
6083 n = lookup_neighbour (target);
6084 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
6086 if ((NULL == n) && (NULL == dv))
6087 {
6089 "Cannot route message of type %u to %s: no route\n",
6090 ntohs (hdr->type),
6091 GNUNET_i2s (target));
6093 "# Messages dropped in routing: no acceptable method",
6094 1,
6095 GNUNET_NO);
6097 }
6099 "Routing message of type %u to %s with options %X\n",
6100 ntohs (hdr->type),
6101 GNUNET_i2s (target),
6102 (unsigned int) options);
6103 /* If both dv and n are possible and we must choose:
6104 flip a coin for the choice between the two; for now 50/50 */
6105 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
6106 {
6107 if (0 == GNUNET_CRYPTO_random_u32 (2))
6108 n = NULL;
6109 else
6110 dv = NULL;
6111 }
6112 if ((NULL != n) && (NULL != dv))
6113 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
6114 enough for redundancy, so clear the flag. */
6117 if (NULL != n)
6118 {
6120 "Try to route message of type %u to %s without fc via neighbour\n",
6121 ntohs (hdr->type),
6122 GNUNET_i2s (target));
6123 rtt1 = route_via_neighbour (n, hdr, options);
6124 }
6125 if (NULL != dv)
6126 {
6127 struct DistanceVectorHop *hops[2];
6128 unsigned int res;
6129
6131 options,
6132 hops,
6133 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
6134 if (0 == res)
6135 {
6137 "Failed to route message, could not determine DV path\n");
6138 return rtt1;
6139 }
6141 "encapsulate_for_dv 1\n");
6142 rtt2 = encapsulate_for_dv (dv,
6143 res,
6144 hops,
6145 hdr,
6147 NULL,
6149 GNUNET_YES);
6150 }
6151 return GNUNET_TIME_relative_min (rtt1, rtt2);
6152}
6153
6154
6155static void
6156consider_sending_fc (void *cls);
6157
6164static void
6166{
6167 struct VirtualLink *vl = cls;
6168 vl->fc_retransmit_task = NULL;
6169 consider_sending_fc (cls);
6170}
6171
6172
6173static char *
6174get_address_without_port (const char *address);
6175
6176
6178{
6179 size_t off;
6180
6186 size_t size;
6187
6188 char *tgnas;
6189};
6190
6191
6192static enum GNUNET_GenericReturnValue
6194 const struct GNUNET_PeerIdentity *pid,
6195 void *value)
6196{
6197 struct AddGlobalAddressesContext *ctx = cls;
6198 struct TransportGlobalNattedAddress *tgna = value;
6199 char *addr = (char *) &tgna[1];
6200 size_t alen = ntohl (tgna->address_length);
6201 size_t need = sizeof (struct TransportGlobalNattedAddress) + alen;
6202
6203 /* NOTE: the address is NOT 0-terminated, it must be printed with an
6204 explicit precision. */
6206 "sending address %.*s length %lu\n",
6207 (int) alen,
6208 addr,
6209 (unsigned long) alen);
6210 if (ctx->off + need > ctx->size)
6211 {
6212 GNUNET_break (0);
6213 return GNUNET_NO;
6214 }
6215 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, need);
6216 ctx->off += need;
6217
6218 return GNUNET_OK;
6219}
6220
6221
6222static struct GNUNET_TIME_Relative
6223calculate_rtt (struct DistanceVector *dv);
6224
6225
6232static void
6234{
6235 struct VirtualLink *vl = cls;
6236 struct GNUNET_TIME_Absolute monotime;
6237 struct TransportFlowControlMessage *fc;
6239 struct GNUNET_TIME_Relative rtt;
6240 struct GNUNET_TIME_Relative rtt_average;
6241 struct Neighbour *n = vl->n;
6242 size_t addresses_size;
6243
6244 /* Most of our callers are not the retransmit task but inbound events:
6245 handle_flow_control() ends in check_vl_transmission(), which calls us
6246 once per flow-control-stalled message, and the peer's answer to what we
6247 send here arrives as another handle_flow_control(). On a link whose
6248 head message does not fit the window that is a ping-pong with nothing
6249 to damp it -- the backoff and the MIN_FC_RETRANSMIT_DELAY floor at the
6250 bottom of this function only ever governed @e fc_retransmit_task, which
6251 these callers bypass. If the chain is armed and we just sent one, let
6252 the task do it. */
6253 if ((NULL != vl->fc_retransmit_task) &&
6255 < MIN_FC_RETRANSMIT_DELAY.rel_value_us))
6256 {
6258 "Not sending FC to %s: one went out less than %s ago\n",
6259 GNUNET_i2s (&vl->target),
6262 GNUNET_YES));
6263 return;
6264 }
6265 if ((GNUNET_YES != vl->confirmed) &&
6266 (NULL == lookup_neighbour (&vl->target)) &&
6268 {
6269 /* Unconfirmed AND no way to reach the peer at all -- nothing to send on.
6270 An unconfirmed link that *does* have a route must still answer,
6271 see below.
6272
6273 Do NOT just return: #task_consider_sending_fc() cleared
6274 @e fc_retransmit_task before calling us, and the only other place that
6275 arms it is #handle_flow_control() -- which only does so when it is
6276 already non-NULL. Leaving without re-arming therefore ends the
6277 keepalive chain for this link permanently, and #check_link_down()
6278 tears it down #NEIGHBOUR_LIVENESS_TIMEOUT later. */
6280 "Not sending FC to %s: link unconfirmed and no route\n",
6281 GNUNET_i2s (&vl->target));
6282 if (NULL == vl->fc_retransmit_task)
6286 vl);
6287 return;
6288 }
6289 addresses_size = 0;
6290 if (NULL != n && 0 < n->number_of_addresses)
6291 {
6292 addresses_size =
6293 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
6294 ->size_of_global_addresses;
6295 if (addresses_size >
6296 UINT16_MAX - sizeof (struct TransportFlowControlMessage))
6297 {
6298 /* htons() below would silently truncate `header.size', leaving a
6299 message whose declared length does not match its contents. */
6300 GNUNET_break (0);
6301 addresses_size = 0;
6302 }
6303 }
6304 if (0 != addresses_size)
6305 {
6306 char *tgnas = GNUNET_malloc (addresses_size);
6308 ctx.off = 0;
6309 ctx.size = addresses_size;
6310 ctx.tgnas = tgnas;
6311
6313 + addresses_size);
6314 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
6315 + addresses_size);
6316 fc->size_of_addresses = htonl ((uint32_t) n->size_of_global_addresses);
6317 fc->number_of_addresses = htonl (n->number_of_addresses);
6320 &ctx);
6323 }
6324 else
6325 {
6326 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
6327 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
6328 }
6329
6331 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
6332 it always! */
6333 /* For example, we should probably ONLY do this if a bit more than
6334 an RTT has passed, or if the window changed "significantly" since
6335 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
6336 need an estimate for the bandwidth-delay-product for the entire
6337 VL, as that determines "significantly". We have the delay, but
6338 the bandwidth statistics need to be added for the VL!*/(void) duration;
6339
6340 if (NULL != vl->dv)
6341 rtt_average = calculate_rtt (vl->dv);
6342 else
6343 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
6344 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
6346 "Sending FC seq %u to %s with new window %llu %lu %u\n",
6347 (unsigned int) vl->fc_seq_gen,
6348 GNUNET_i2s (&vl->target),
6349 (unsigned long long) vl->incoming_fc_window_size,
6350 (unsigned long) rtt_average.rel_value_us,
6351 vl->sync_ready);
6353 vl->last_fc_transmission = monotime;
6354 fc->sync_ready = htonl ((uint32_t) vl->sync_ready);
6356 fc->seq = htonl (vl->fc_seq_gen++);
6357 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
6360 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
6361 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
6362 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
6363 /* On an unconfirmed link the only queues and paths we have are, by
6364 definition, unvalidated ones -- that is what "unconfirmed" means.
6365 Requiring a validated route here is what deadlocks the pair: the peer
6366 has a confirmed link to us and flow-controls us, we cannot answer, so
6367 its @e outbound_fc_window_size stays at zero and it cannot send us a
6368 single byte -- not its CORE handshake, not DHT traffic -- while its
6369 `gnunet-transport' shows an established link with messages pending
6370 forever. It reached us over that queue, so answering on it is sound. */
6372 &fc->header,
6373 (GNUNET_YES == vl->confirmed)
6376 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
6377 {
6380 "FC retransmission to %s failed, will retry in %s\n",
6381 GNUNET_i2s (&vl->target),
6384 }
6385 else
6386 {
6387 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
6388 vl->last_fc_rtt = rtt;
6389 }
6390 if (NULL != vl->fc_retransmit_task)
6392 /* Never re-arm with (near) zero delay: @a rtt is zero whenever we have no
6393 RTT sample yet, which turned this into a tight send loop. */
6395 {
6396 /* Back off while the peer stays silent. Retransmitting at the plain RTT
6397 for #MAX_FC_RETRANSMIT_COUNT rounds is a flood on a link that is not
6398 being answered -- and a peer that cannot answer keeps *every* one of
6399 its links in exactly that state, which is enough traffic to make
6400 transport fall behind its communicators. */
6402
6403 for (unsigned int i = 0;
6404 (i < vl->fc_retransmit_count) && (rtt.rel_value_us < cap.rel_value_us);
6405 i++)
6406 rtt = GNUNET_TIME_relative_multiply (rtt, 2);
6407 rtt = GNUNET_TIME_relative_min (rtt, cap);
6408 }
6409 vl->fc_retransmit_task =
6412 vl->fc_retransmit_count++;
6413 GNUNET_free (fc);
6414}
6415
6416
6433static void
6435{
6436 struct Neighbour *n = vl->n;
6437 struct DistanceVector *dv = vl->dv;
6438 struct GNUNET_TIME_Absolute now;
6439 struct VirtualLink *vl_next_hop;
6440 int elig;
6441
6443 "check_vl_transmission to target %s\n",
6444 GNUNET_i2s (&vl->target));
6445 /* Check that we have an eligible pending message!
6446 (cheaper than having #transmit_on_queue() find out!) */
6447 elig = GNUNET_NO;
6448 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
6449 pm = pm->next_vl)
6450 {
6452 "check_vl_transmission loop\n");
6453 if (NULL != pm->qe)
6454 continue; /* not eligible, is in a queue! */
6455 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
6457 {
6459 "Stalled message %" PRIu64
6460 " transmission on VL %s due to flow control: %llu < %llu\n",
6461 pm->logging_uuid,
6462 GNUNET_i2s (&vl->target),
6463 (unsigned long long) vl->outbound_fc_window_size,
6464 (unsigned long long) (pm->bytes_msg
6467 return; /* We have a message, but flow control says "nope" */
6468 }
6470 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
6471 GNUNET_i2s (&vl->target));
6472 /* Notify queues at direct neighbours that we are interested */
6473 now = GNUNET_TIME_absolute_get ();
6474 if (NULL != n)
6475 {
6476 for (struct Queue *queue = n->queue_head; NULL != queue;
6477 queue = queue->next_neighbour)
6478 {
6479 if ((GNUNET_YES == queue->idle) &&
6480 (queue->validated_until.abs_value_us > now.abs_value_us))
6481 {
6483 "Direct neighbour %s not stalled\n",
6484 GNUNET_i2s (&n->pid));
6486 queue,
6488 elig = GNUNET_YES;
6489 }
6490 else
6492 "Neighbour Queue QID: %u (%u) busy or invalid\n",
6493 queue->qid,
6494 queue->idle);
6495 }
6496 }
6497 /* Notify queues via DV that we are interested */
6498 if (NULL != dv)
6499 {
6500 /* Do DV with lower scheduler priority, which effectively means that
6501 IF a neighbour exists and is available, we prefer it. */
6502 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6503 pos = pos->next_dv)
6504 {
6505 struct Neighbour *nh_iter = pos->next_hop;
6506
6507
6508 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
6509 continue; /* skip this one: path not validated */
6510 else
6511 {
6512 /* The next hop is a neighbour we have queues to; it need not have
6513 a virtual link of its own, and then there is no window of it to
6514 respect either. */
6515 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
6516 if ((NULL != vl_next_hop) &&
6517 (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
6518 vl_next_hop->outbound_fc_window_size))
6519 {
6521 "Stalled message %" PRIu64
6522 " transmission on next hop %s due to flow control: %llu < %llu\n",
6523 pm->logging_uuid,
6524 GNUNET_i2s (&vl_next_hop->target),
6525 (unsigned long
6526 long) vl_next_hop->outbound_fc_window_size,
6527 (unsigned long long) (pm->bytes_msg
6528 + vl_next_hop->
6529 outbound_fc_window_size_used));
6530 consider_sending_fc (vl_next_hop);
6531 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
6532 }
6533 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
6534 queue = queue->next_neighbour)
6535 if ((GNUNET_YES == queue->idle) &&
6536 (queue->validated_until.abs_value_us > now.abs_value_us))
6537 {
6539 "Next hop neighbour %s not stalled\n",
6540 GNUNET_i2s (&nh_iter->pid));
6542 queue,
6544 elig = GNUNET_YES;
6545 }
6546 else
6548 "DV Queue QID: %u (%u) busy or invalid\n",
6549 queue->qid,
6550 queue->idle);
6551 }
6552 }
6553 }
6554 if (GNUNET_YES == elig)
6556 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
6557 pm->logging_uuid,
6558 pm->bytes_msg,
6559 GNUNET_i2s (&vl->target),
6560 (unsigned long long) vl->outbound_fc_window_size,
6561 (unsigned long long) (pm->bytes_msg
6563 break;
6564 }
6565}
6566
6567
6574static void
6575handle_client_send (void *cls, const struct OutboundMessage *obm)
6576{
6577 struct TransportClient *tc = cls;
6578 struct PendingMessage *pm;
6579 const struct GNUNET_MessageHeader *obmm;
6580 uint32_t bytes_msg;
6581 struct VirtualLink *vl;
6583
6584 GNUNET_assert (CT_CORE == tc->type);
6585 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
6586 bytes_msg = ntohs (obmm->size);
6587 pp = ntohl (obm->priority);
6588 vl = lookup_virtual_link (&obm->peer);
6589 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6590 {
6592 "Don't have %s as a neighbour (anymore).\n",
6593 GNUNET_i2s (&obm->peer));
6594 /* Failure: don't have this peer as a neighbour (anymore).
6595 Might have gone down asynchronously, so this is NOT
6596 a protocol violation by CORE. Still count the event,
6597 as this should be rare. */
6598 /* Precisely because this is not a protocol violation we leave the
6599 client's `struct Neighbour' -- and its send window -- in place, so we
6600 owe it the SEND_OK for the message we are dropping here. Without it
6601 the window shrinks by one every time this happens and never grows
6602 back; after #SEND_WINDOW_SIZE such drops #mq_send_impl() parks every
6603 further message for this peer forever ("Flow control delays
6604 transmission to CORE until we see SEND_OK") and CORE goes mute
6605 towards a peer it still believes it is connected to -- while
6606 continuing to receive from it, so its own idle timeout is what
6607 eventually reports the peer down. */
6608 send_ok_to_client (tc, &obm->peer);
6611 "# messages dropped (neighbour unknown)",
6612 1,
6613 GNUNET_NO);
6614 return;
6615 }
6616
6617 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
6619 "1 created pm %p storing vl %p\n",
6620 pm,
6621 vl);
6623 pm->prefs = pp;
6624 pm->client = tc;
6625 pm->vl = vl;
6626 pm->bytes_msg = bytes_msg;
6627 memcpy (&pm[1], obmm, bytes_msg);
6629 "Sending message of type %u with %u bytes as <%" PRIu64
6630 "> to %s\n",
6631 ntohs (obmm->type),
6632 bytes_msg,
6633 pm->logging_uuid,
6634 GNUNET_i2s (&obm->peer));
6636 tc->details.core.pending_msg_head,
6637 tc->details.core.pending_msg_tail,
6638 pm);
6640 vl->pending_msg_head,
6641 vl->pending_msg_tail,
6642 pm);
6645}
6646
6647
6657static void
6659 void *cls,
6661{
6662 struct Neighbour *n;
6663 struct VirtualLink *vl;
6664 struct TransportClient *tc = cls;
6665 const struct GNUNET_MessageHeader *inbox =
6666 (const struct GNUNET_MessageHeader *) &cb[1];
6667 uint16_t isize = ntohs (inbox->size);
6668 const char *is = ((const char *) &cb[1]) + isize;
6669 size_t slen = strlen (is) + 1;
6670 char
6671 mbuf[slen + isize
6672 + sizeof(struct
6676
6677 /* 0-termination of 'is' was checked already in
6678 #check_communicator_backchannel() */
6680 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
6681 GNUNET_i2s (&cb->pid),
6682 is,
6683 ntohs (inbox->type),
6684 ntohs (inbox->size));
6685 /* encapsulate and encrypt message */
6686 be->header.type =
6688 be->header.size = htons (sizeof(mbuf));
6689 memcpy (&be[1], inbox, isize);
6690 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
6691 + isize],
6692 is,
6693 strlen (is) + 1);
6694 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
6695 vl = lookup_virtual_link (&cb->pid);
6696 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6697 {
6699 }
6700 else
6701 {
6702 /* Use route via neighbour */
6703 n = lookup_neighbour (&cb->pid);
6704 if (NULL != n)
6706 n,
6707 &be->header,
6708 RMO_NONE);
6709 }
6711}
6712
6713
6721static int
6723 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6724{
6725 struct TransportClient *tc = cls;
6726
6727 if (CT_COMMUNICATOR != tc->type)
6728 {
6729 GNUNET_break (0);
6730 return GNUNET_SYSERR;
6731 }
6733 return GNUNET_OK;
6734}
6735
6736
6742static void
6743store_pi (void *cls);
6744
6745
6750{
6751
6756
6761
6762
6767};
6768
6769
6776static void
6778{
6779 struct PilsAddressSignContext *pc = ale->pc;
6780
6781 if (NULL == pc)
6782 return;
6783 ale->pc = NULL;
6784 /* Each stage of the chain passes @a pc as its closure, so every handle
6785 that could still deliver one has to go before @a pc is released. */
6786 if (NULL != ale->sc)
6787 {
6789 ale->sc = NULL;
6790 }
6791 if (NULL != ale->shc)
6792 {
6794 ale->shc = NULL;
6795 }
6796 if (NULL != pc->req)
6797 {
6798 if (NULL != pc->req->op)
6799 GNUNET_PILS_cancel (pc->req->op);
6802 pc->req);
6803 GNUNET_free (pc->req);
6804 pc->req = NULL;
6805 }
6806 GNUNET_free (pc);
6807}
6808
6809
6810static void
6811shc_cont (void *cls, int success)
6812{
6813 struct PilsAddressSignContext *pc = cls;
6814
6815 GNUNET_assert (NULL == pc->req);
6816 /* The store completed; the handle is dead and must not be cancelled
6817 later by #free_address_list_entry(). */
6818 pc->ale->shc = NULL;
6819 pc->ale->pc = NULL;
6820 if (GNUNET_OK != success)
6821 {
6823 "Failed to store our address `%s' with peerstore\n",
6824 pc->ale->address);
6825 if (NULL == pc->ale->st)
6826 {
6828 &store_pi,
6829 pc->ale);
6830 }
6831 }
6832 GNUNET_free (pc);
6833}
6834
6835
6839static void
6841 const struct GNUNET_PeerIdentity *pid,
6842 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6843{
6844 struct PilsAddressSignContext *pc = cls;
6845 struct GNUNET_MQ_Envelope *env;
6846 const struct GNUNET_MessageHeader *msg;
6847
6848 pc->req->op = NULL;
6851 pc->req);
6852 GNUNET_free (pc->req);
6853 pc->req = NULL;
6856 pid,
6857 sig,
6858 pc->et);
6861 "store_pi 1\n");
6863 msg,
6864 shc_cont,
6865 pc);
6866 GNUNET_free (env);
6867}
6868
6869
6876static void
6877peerstore_store_own_cb (void *cls, int success)
6878{
6879 struct PilsAddressSignContext *pc = cls;
6880
6881 pc->ale->sc = NULL;
6882 if (GNUNET_YES != success)
6884 "Failed to store our own address `%s' in peerstore!\n",
6885 pc->ale->address);
6886 else
6888 "Successfully stored our own address `%s' in peerstore!\n",
6889 pc->ale->address);
6890 /* refresh period is 1/4 of expiration time, that should be plenty
6891 without being excessive. */
6892 if (NULL == pc->ale->st)
6893 {
6894 /* @e expiration comes straight off the wire in ADD_ADDRESS and is not
6895 validated anywhere, so a communicator reporting a very short (or
6896 zero) lifetime would have us re-sign the HELLO and store it again on
6897 the next scheduler pass, forever. That is an EdDSA signature and a
6898 PEERSTORE round trip per iteration. */
6899 pc->ale->st =
6903 GNUNET_TIME_relative_divide (pc->ale->expiration,
6904 4ULL)),
6905 &store_pi,
6906 pc->ale);
6907 }
6908
6909 /* Now we have to update our HELLO! */
6911 pc->req = GNUNET_new (struct PilsRequest);
6914 pc->req);
6915 pc->req->op = GNUNET_PILS_sign_hello (pils,
6917 pc->et,
6919 pc);
6920}
6921
6922
6930static void
6932 const struct GNUNET_PeerIdentity *pid,
6933 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6934{
6935 char *sig_str;
6936 void *result;
6937 size_t result_size;
6938
6939 sig_str = NULL;
6940 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6941 result_size =
6942 1 + GNUNET_asprintf (
6943 (char **) &result,
6944 "%s;%llu;%u;%s",
6945 sig_str,
6946 (unsigned long long) pc->et.abs_value_us,
6947 (unsigned int) pc->ale->nt,
6948 pc->ale->address);
6949 GNUNET_free (sig_str);
6950
6952 "Build our HELLO URI `%s'\n",
6953 (char*) result);
6954
6955 GNUNET_free (pc->ale->signed_address);
6956 pc->ale->signed_address = result;
6957 pc->ale->signed_address_len = result_size;
6959
6960 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6962 "transport",
6963 pid,
6965 result,
6966 result_size,
6967 expiration,
6970 pc);
6971}
6972
6973
6994
6995
7009void
7011 struct AddressListEntry *ale,
7012 struct GNUNET_TIME_Absolute mono_time)
7013{
7014 struct SignedAddress sa;
7015 struct PilsAddressSignContext *pc;
7017 const struct GNUNET_PeerIdentity *my_identity;
7018
7020 sa.purpose.size = htonl (sizeof(sa));
7021 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
7022 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
7023 /* Only ever one chain per entry: the previous one (if any) still holds a
7024 pointer to @a ale and must be torn down first. */
7027 if ((NULL == my_identity) ||
7028 (GNUNET_OK != sign_by_my_identity (&sa.purpose, &sig)))
7029 {
7030 /* Nothing else re-arms @e st: #store_pi() cleared it before calling us,
7031 and the only other thing that sets it is #peerstore_store_own_cb(),
7032 which is on the far side of the store we just failed to start. So a
7033 single failure to sign used to end the refresh cycle for this address
7034 for the rest of the process' life. */
7035 if (NULL == ale->st)
7036 {
7039 &store_pi,
7040 ale);
7041 }
7042 return;
7043 }
7045 pc->ale = ale;
7046 pc->et = mono_time;
7047 ale->pc = pc;
7049}
7050
7051
7057static void
7058store_pi (void *cls)
7059{
7060 struct AddressListEntry *ale = cls;
7061 const char *dash;
7062 char *address_uri;
7063 char *prefix;
7064 unsigned int add_success;
7065
7066 if ((GNUNET_YES == in_shutdown) || (NULL == pils))
7067 {
7068 ale->st = NULL;
7069 return;
7070 }
7071 if (NULL == GNUNET_PILS_get_identity (pils))
7072 {
7073 /* Do NOT poll at 1kHz: that burns CPU and keeps the scheduler task
7074 list non-empty, which prevents the service from ever exiting. */
7077 &store_pi,
7078 ale);
7079 return;
7080 }
7083 dash = strchr (ale->address, '-');
7084 GNUNET_assert (NULL != dash);
7085 dash++;
7086 GNUNET_asprintf (&address_uri,
7087 "%s://%s",
7088 prefix,
7089 dash);
7091 ale->st = NULL;
7093 "Storing our address `%s' in peerstore until %s!\n",
7094 ale->address,
7097 address_uri);
7098 /* NOTE: #GNUNET_HELLO_builder_add_address() answers GNUNET_NO for an
7099 address that is already in the builder, and on every call after the
7100 first one for a given address that is exactly what happens: nothing
7101 ever removes an address from @a GST_my_hello except
7102 #handle_del_address(). This function is the *refresh* cycle --
7103 #peerstore_store_own_cb() re-arms it at a quarter of the address'
7104 expiration -- so bailing out on GNUNET_NO here stopped the refresh
7105 after precisely one round. Our own HELLO then expired
7106 (#GNUNET_HELLO_ADDRESS_EXPIRATION, twelve hours) and was never
7107 renewed: peers can no longer learn how to reach us, and a link that
7108 drops after that never comes back. Only GNUNET_SYSERR -- a malformed
7109 URI, which retrying cannot fix -- is a reason not to store. */
7110 if (GNUNET_SYSERR == add_success)
7111 {
7113 "Not storing our address `%s': not a valid HELLO URI\n",
7114 address_uri);
7115 GNUNET_free (address_uri);
7116 return;
7117 }
7118 GNUNET_log ((GNUNET_NO == add_success) ?
7120 "%s our address `%s' in PEERSTORE\n",
7121 (GNUNET_NO == add_success) ? "Refreshing" : "Storing",
7122 address_uri);
7123 // FIXME hello_mono_time used here?? What about expiration in ale?
7124 pils_sign_address (ale,
7126 // TODO keep track of op and potentially cancel/clean
7127 GNUNET_free (address_uri);
7128}
7129
7130
7131static struct AddressListEntry *
7135 const char *address,
7136 uint32_t aid,
7137 size_t slen)
7138{
7139 struct AddressListEntry *ale;
7140 char *address_without_port;
7141
7142 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
7143 ale->tc = tc;
7144 ale->address = (const char *) &ale[1];
7145 ale->expiration = expiration;
7146 ale->aid = aid;
7147 ale->nt = nt;
7148 memcpy (&ale[1], address, slen);
7149 address_without_port = get_address_without_port (ale->address);
7151 "Is this %s a local address (%s)\n",
7152 (NULL == address_without_port) ? "<unparsable>"
7153 : address_without_port,
7154 ale->address);
7155 if ((NULL == address_without_port) ||
7156 (0 != strcmp ("127.0.0.1", address_without_port)))
7157 {
7158 if (NULL != ale->st)
7159 {
7161 }
7162 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
7163 }
7164 GNUNET_free (address_without_port);
7165
7166 return ale;
7167}
7168
7169
7170static void
7172{
7173
7175 "Feeding addresses to PILS\n");
7176 pils_feed_task = NULL;
7177
7179 GST_my_hello);
7180}
7181
7182
7189static void
7191 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
7192{
7193 struct TransportClient *tc = cls;
7194 struct AddressListEntry *ale;
7195 size_t slen;
7196 char *address;
7197
7198 /* 0-termination of &aam[1] was checked in #check_add_address */
7200 "Communicator added address `%s'!\n",
7201 (const char *) &aam[1]);
7202 slen = ntohs (aam->header.size) - sizeof(*aam);
7203 address = GNUNET_malloc (slen);
7204 memcpy (address, &aam[1], slen);
7205 ale = create_address_entry (tc,
7207 ntohl (aam->nt),
7208 address,
7209 aam->aid,
7210 slen);
7211 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
7212 tc->details.communicator.addr_tail,
7213 ale);
7214 {
7215 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
7216 NULL != iter;
7217 iter = iter->next)
7218 {
7219 char *address_uri;
7220 const char *dash = strchr (iter->address, '-');
7221 char *prefix = GNUNET_HELLO_address_to_prefix (iter->address);
7222 GNUNET_assert (NULL != dash);
7223 dash++;
7224 GNUNET_asprintf (&address_uri,
7225 "%s://%s",
7226 prefix,
7227 dash);
7230 GNUNET_free (address_uri);
7231 }
7232 if (NULL != pils_feed_task)
7236 NULL);
7237 }
7240}
7241
7242
7249static void
7251 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
7252{
7253 struct TransportClient *tc = cls;
7254 struct AddressListEntry *alen;
7255
7256 if (CT_COMMUNICATOR != tc->type)
7257 {
7258 GNUNET_break (0);
7260 return;
7261 }
7262 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
7263 NULL != ale;
7264 ale = alen)
7265 {
7266 alen = ale->next;
7267 if (dam->aid != ale->aid)
7268 continue;
7269 GNUNET_assert (ale->tc == tc);
7271 "Communicator deleted address `%s'!\n",
7272 ale->address);
7274 ale->address);
7275 if (NULL != pils_feed_task)
7279 NULL);
7282 return;
7283 }
7285 "Communicator removed address we did not even have.\n");
7287 // GNUNET_SERVICE_client_drop (tc->client);
7288}
7289
7290
7298static void
7300
7301
7309static void
7311{
7312 struct CoreSentContext *ctx = cls;
7313 struct VirtualLink *vl = ctx->vl;
7314
7315 if (NULL == vl)
7316 {
7317 /* lost the link in the meantime, ignore */
7318 GNUNET_free (ctx);
7319 return;
7320 }
7323 vl->incoming_fc_window_size_ram -= ctx->size;
7324 vl->incoming_fc_window_size_used += ctx->isize;
7326 GNUNET_free (ctx);
7327}
7328
7329
7351static void
7353{
7354 struct VirtualLink *vl = cls;
7355 struct CommunicatorMessageContext *cmc;
7356
7357 vl->core_fc_stall_task = NULL;
7359 "CORE did not acknowledge messages from %s within %s; "
7360 "releasing the flow control credit anyway\n",
7361 GNUNET_i2s (&vl->target),
7363 GNUNET_YES));
7365 "# CORE flow control stalls",
7366 1,
7367 GNUNET_NO);
7368 while (NULL != (cmc = vl->cmc_tail))
7369 release_stalled_cmc (vl, cmc);
7372}
7373
7374
7375static void
7377 const struct GNUNET_MessageHeader *mh,
7378 struct CommunicatorMessageContext *cmc,
7379 unsigned int free_cmc)
7380{
7381 uint16_t size = ntohs (mh->size);
7382 int have_core;
7383
7384 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
7385 {
7387 "# CORE messages dropped (FC arithmetic overflow)",
7388 1,
7389 GNUNET_NO);
7391 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
7392 (unsigned int) ntohs (mh->type),
7393 (unsigned int) ntohs (mh->size));
7394 if (GNUNET_YES == free_cmc)
7396 return;
7397 }
7399 {
7401 "# CORE messages dropped (FC window overflow)",
7402 1,
7403 GNUNET_NO);
7405 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
7406 (unsigned int) ntohs (mh->type),
7407 (unsigned int) ntohs (mh->size));
7408 if (GNUNET_YES == free_cmc)
7410 return;
7411 }
7412
7413 /* Forward to all CORE clients */
7414 have_core = GNUNET_NO;
7415 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
7416 {
7417 struct GNUNET_MQ_Envelope *env;
7418 struct InboundMessage *im;
7419 struct CoreSentContext *ctx;
7420
7421 if (CT_CORE != tc->type)
7422 continue;
7425 ctx = GNUNET_new (struct CoreSentContext);
7426 ctx->vl = vl;
7427 ctx->size = size;
7428 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
7429 have_core = GNUNET_YES;
7432 im->peer = cmc->im.sender;
7433 memcpy (&im[1], mh, size);
7434 GNUNET_MQ_send (tc->mq, env);
7436 }
7437 if (GNUNET_NO == have_core)
7438 {
7440 "Dropped message to CORE: no CORE client connected!\n");
7441 /* Nevertheless, count window as used, as it is from the
7442 perspective of the other peer! */
7444 /* TODO-M1 */
7446 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
7447 (unsigned int) ntohs (mh->type),
7448 (unsigned int) ntohs (mh->size));
7449 if (GNUNET_YES == free_cmc)
7451 return;
7452 }
7454 "Delivered message from %s of type %u to CORE recv window %d\n",
7455 GNUNET_i2s (&cmc->im.sender),
7456 ntohs (mh->type),
7458 if (vl->core_recv_window > 0)
7459 {
7460 if (GNUNET_YES == free_cmc)
7462 return;
7463 }
7464 /* CORE ran out of receive window for *this* link. Withhold the
7465 per-message ACK -- that is what expresses the backpressure -- but
7466 resume the client immediately. The client is the communicator
7467 *process*, which carries every peer we reach through it, and a
7468 communicator we stop reading from does not stop receiving: it starts
7469 discarding, see "transport is too slow" in
7470 #GNUNET_TRANSPORT_communicator_receive(). Discarding is precisely
7471 what we cannot afford here, because among the messages dropped are
7472 the ones CORE needs in order to reopen the window it is waiting on. */
7473 if (GNUNET_YES == free_cmc)
7474 {
7475 resume_cmc_client (cmc);
7477 vl->cmc_count++;
7478 /* Nothing stalls the producer any more, so bound the list ourselves. */
7479 while (MAX_STALLED_CMCS < vl->cmc_count)
7481 /* ... and do not withhold the ACKs forever: see #core_fc_stalled(). */
7482 if (NULL == vl->core_fc_stall_task)
7486 vl);
7487 }
7488}
7489
7490
7499static void
7501{
7502 struct CommunicatorMessageContext *cmc = cls;
7503 // struct CommunicatorMessageContext *cmc_copy =
7504 // GNUNET_new (struct CommunicatorMessageContext);
7505 struct GNUNET_MessageHeader *mh_copy;
7506 struct RingBufferEntry *rbe;
7507 struct VirtualLink *vl;
7508 uint16_t size = ntohs (mh->size);
7509
7511 "Handling raw message of type %u with %u bytes\n",
7512 (unsigned int) ntohs (mh->type),
7513 (unsigned int) ntohs (mh->size));
7514
7515 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
7516 (size < sizeof(struct GNUNET_MessageHeader)))
7517 {
7518 /* @a mh was unwrapped from what a *remote peer* sent us, so a bad size
7519 is that peer's protocol violation and says nothing about the
7520 communicator that carried it. Dropping the client here disconnects
7521 the communicator process and with it every neighbour reachable
7522 through it -- see the rationale in #demultiplex_with_cmc(). */
7523 GNUNET_break_op (0);
7525 "# CORE messages dropped (bad size)",
7526 1,
7527 GNUNET_NO);
7528 finish_cmc_handling (cmc);
7529 return;
7530 }
7531 vl = lookup_virtual_link (&cmc->im.sender);
7532 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
7533 {
7534 /* FIXME: sender is giving us messages for CORE but we don't have
7535 the link up yet! I *suspect* this can happen right now (i.e.
7536 sender has verified us, but we didn't verify sender), but if
7537 we pass this on, CORE would be confused (link down, messages
7538 arrive). We should investigate more if this happens often,
7539 or in a persistent manner, and possibly do "something" about
7540 it. Thus logging as error for now. */
7541
7542 mh_copy = GNUNET_malloc (size);
7543 rbe = GNUNET_new (struct RingBufferEntry);
7544 rbe->cmc = cmc;
7545 /*cmc_copy->tc = cmc->tc;
7546 cmc_copy->im = cmc->im;*/
7547 GNUNET_memcpy (mh_copy, mh, size);
7548
7549 rbe->mh = mh_copy;
7550
7552 {
7553 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
7554 GNUNET_free (rbe_old->cmc);
7555 GNUNET_free (rbe_old->mh);
7556 GNUNET_free (rbe_old);
7557 }
7558 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
7559 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
7560 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
7562 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
7563 GNUNET_i2s (&cmc->im.sender),
7564 (unsigned int) ntohs (mh->type),
7565 (unsigned int) ntohs (mh_copy->type),
7569 {
7570 ring_buffer_head = 0;
7572 }
7573 else
7575
7577 "%u items stored in ring buffer\n",
7580
7581 /*GNUNET_break_op (0);
7582 GNUNET_STATISTICS_update (GST_stats,
7583 "# CORE messages dropped (virtual link still down)",
7584 1,
7585 GNUNET_NO);
7586
7587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7588 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
7589 (unsigned int) ntohs (mh->type),
7590 (unsigned int) ntohs (mh->size));
7591 finish_cmc_handling (cmc);*/
7592 /* @a cmc lives on in the ring buffer; #send_cmc_ack() and
7593 #resume_cmc_client() have recorded that they ran, so replaying it
7594 from #send_msg_from_cache() cannot ACK or continue a second time. */
7596 return;
7597 }
7599}
7600
7601
7609static int
7611{
7612 uint16_t size = ntohs (fb->header.size);
7613 uint16_t bsize = size - sizeof(*fb);
7614
7615 (void) cls;
7616 if (0 == bsize)
7617 {
7618 GNUNET_break_op (0);
7619 return GNUNET_SYSERR;
7620 }
7621 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
7622 {
7623 GNUNET_break_op (0);
7624 return GNUNET_SYSERR;
7625 }
7626 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
7627 {
7628 GNUNET_break_op (0);
7629 return GNUNET_SYSERR;
7630 }
7631 return GNUNET_YES;
7632}
7633
7634
7640static void
7642{
7643 struct AcknowledgementCummulator *ac = cls;
7644
7645 ac->task = NULL;
7646 GNUNET_assert (0 == ac->num_acks);
7648 GNUNET_YES ==
7650 GNUNET_free (ac);
7651}
7652
7653
7659static void
7661{
7662 struct Neighbour *n;
7663 struct VirtualLink *vl;
7664 struct AcknowledgementCummulator *ac = cls;
7665 char buf[sizeof(struct TransportReliabilityAckMessage)
7666 + ac->num_acks
7668 struct TransportReliabilityAckMessage *ack =
7669 (struct TransportReliabilityAckMessage *) buf;
7671
7672 ac->task = NULL;
7674 "Sending ACK with %u components to %s\n",
7675 ac->num_acks,
7676 GNUNET_i2s (&ac->target));
7677 GNUNET_assert (0 < ac->num_acks);
7679 ack->header.size =
7680 htons (sizeof(*ack)
7681 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
7682 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
7683 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
7684 for (unsigned int i = 0; i < ac->num_acks; i++)
7685 {
7686 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
7689 }
7690 /*route_control_message_without_fc (
7691 &ac->target,
7692 &ack->header,
7693 RMO_DV_ALLOWED);*/
7694 vl = lookup_virtual_link (&ac->target);
7695 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7696 {
7698 vl,
7699 &ack->header,
7701 }
7702 else
7703 {
7704 /* Use route via neighbour */
7705 n = lookup_neighbour (&ac->target);
7706 if (NULL != n)
7708 n,
7709 &ack->header,
7710 RMO_NONE);
7711 }
7712 ac->num_acks = 0;
7713 /* The deadline belonged to the batch we just sent. #cummulative_ack()
7714 only ever lowers it (GNUNET_TIME_absolute_min), so leaving it behind
7715 means every later ACK is armed with GNUNET_SCHEDULER_add_at() on a time
7716 that has already passed: the task fires on the next scheduler pass and
7717 the batching this whole structure exists for is gone for good -- one
7718 ACK message per received message, for the rest of the process' life. */
7722 ac);
7723}
7724
7725
7734static void
7736 const struct AcknowledgementUUIDP *ack_uuid,
7737 struct GNUNET_TIME_Absolute max_delay)
7738{
7739 struct AcknowledgementCummulator *ac;
7740
7742 "Scheduling ACK %s for transmission to %s\n",
7743 GNUNET_uuid2s (&ack_uuid->value),
7744 GNUNET_i2s (pid));
7746 if (NULL == ac)
7747 {
7749 ac->target = *pid;
7750 ac->min_transmission_time = max_delay;
7754 &ac->target,
7755 ac,
7757 }
7758 else
7759 {
7760 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
7761 {
7762 /* Must run immediately, ack buffer full. Cancel the pending task
7763 FIRST: #transmit_cummulative_ack_cb() clears @e task without
7764 cancelling it, which would leave the old task armed with its
7765 handle lost. */
7767 ac->task = NULL;
7769 }
7773 }
7776 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
7777 ac->num_acks++;
7780 ac);
7781}
7782
7783
7799
7800
7810static int
7811find_by_message_uuid (void *cls, uint32_t key, void *value)
7812{
7813 struct FindByMessageUuidContext *fc = cls;
7814 struct ReassemblyContext *rc = value;
7815
7816 (void) key;
7817 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
7818 {
7819 fc->rc = rc;
7820 return GNUNET_NO;
7821 }
7822 return GNUNET_YES;
7823}
7824
7825
7833static void
7835{
7836 struct CommunicatorMessageContext *cmc = cls;
7837 struct VirtualLink *vl;
7838 struct ReassemblyContext *rc;
7839 const struct GNUNET_MessageHeader *msg;
7840 uint16_t msize;
7841 uint16_t fsize;
7842 uint16_t frag_off;
7843 char *target;
7844 struct GNUNET_TIME_Relative cdelay;
7845 struct FindByMessageUuidContext fc;
7846
7847 vl = lookup_virtual_link (&cmc->im.sender);
7848 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
7849 {
7850 /* Entirely normal: fragments of a message that was already in flight
7851 keep arriving for a while after a link goes down, and a peer that has
7852 validated us may start sending before we have validated it. This used
7853 to call #GNUNET_SERVICE_client_drop(), which disconnects the
7854 communicator *process* -- every queue it owns, hence every neighbour
7855 reachable through it, hence every CORE session. On a peer with many
7856 neighbours a single ill-timed fragment therefore dropped all
7857 connections at once, and since the fragment comes from the network,
7858 any peer could cause it at will. Drop the fragment, keep the
7859 communicator; see #demultiplex_with_cmc() for the same reasoning. */
7861 "No virtual link for %s to handle fragment\n",
7862 GNUNET_i2s (&cmc->im.sender));
7864 "# fragments dropped (virtual link down)",
7865 1,
7866 GNUNET_NO);
7867 finish_cmc_handling (cmc);
7868 return;
7869 }
7870 if (NULL == vl->reassembly_map)
7871 {
7873 vl->reassembly_heap =
7878 vl);
7879 }
7880 msize = ntohs (fb->msg_size);
7881 fc.message_uuid = fb->msg_uuid;
7882 fc.rc = NULL;
7884 fb->msg_uuid.uuid,
7886 &fc);
7887 fsize = ntohs (fb->header.size) - sizeof(*fb);
7888 if (NULL == (rc = fc.rc))
7889 {
7890 /* Bound the RAM a single sender can pin here: @e msg_size is chosen by
7891 the peer, not by us. */
7894 {
7895 struct ReassemblyContext *drop;
7896
7898 GNUNET_assert (NULL != drop);
7900 "# Reassembly contexts dropped (limit reached)",
7901 1,
7902 GNUNET_NO);
7904 }
7905 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
7906 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
7907 rc->msg_uuid = fb->msg_uuid;
7908 rc->virtual_link = vl;
7909 rc->msg_size = msize;
7910 rc->reassembly_timeout =
7914 rc,
7918 vl->reassembly_map,
7919 rc->msg_uuid.uuid,
7920 rc,
7922 target = (char *) &rc[1];
7923 rc->bitfield = (uint8_t *) (target + rc->msg_size);
7924 /* The bitfield loop below decrements @e msg_missing once per newly
7925 received byte, so this must always start at the full message size:
7926 initialising it to 0 for a single-fragment message made it
7927 underflow, and the message was then never delivered. */
7928 rc->msg_missing = rc->msg_size;
7930 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
7931 PRIu64 "\n",
7932 fsize,
7933 ntohs (fb->frag_off),
7934 msize,
7935 rc->msg_missing,
7936 GNUNET_i2s (&cmc->im.sender),
7937 fb->msg_uuid.uuid);
7938 }
7939 else
7940 {
7941 target = (char *) &rc[1];
7943 "Received fragment at offset %u/%u from %s for message %u\n",
7944 ntohs (fb->frag_off),
7945 msize,
7946 GNUNET_i2s (&cmc->im.sender),
7947 (unsigned int) fb->msg_uuid.uuid);
7948 }
7949 if (msize != rc->msg_size)
7950 {
7951 GNUNET_break (0);
7952 finish_cmc_handling (cmc);
7953 return;
7954 }
7955
7956 /* reassemble */
7957 if (0 == fsize)
7958 {
7959 GNUNET_break (0);
7960 finish_cmc_handling (cmc);
7961 return;
7962 }
7963 frag_off = ntohs (fb->frag_off);
7964 if (frag_off + fsize > msize)
7965 {
7966 /* Fragment (plus fragment size) exceeds message size! */
7967 GNUNET_break_op (0);
7968 finish_cmc_handling (cmc);
7969 return;
7970 }
7971 memcpy (&target[frag_off], &fb[1], fsize);
7972 /* update bitfield and msg_missing */
7973 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
7974 {
7975 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
7976 {
7977 rc->bitfield[i / 8] |= (1 << (i % 8));
7978 rc->msg_missing--;
7979 }
7980 }
7981
7982 /* Compute cumulative ACK */
7984 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
7985 if (0 == rc->msg_missing)
7986 cdelay = GNUNET_TIME_UNIT_ZERO;
7987 cummulative_ack (&cmc->im.sender,
7988 &fb->ack_uuid,
7991 /* is reassembly complete? */
7992 if (0 != rc->msg_missing)
7993 {
7994 finish_cmc_handling (cmc);
7995 return;
7996 }
7997 /* reassembly is complete, verify result */
7998 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7999 if (ntohs (msg->size) != rc->msg_size)
8000 {
8001 GNUNET_break (0);
8003 finish_cmc_handling (cmc);
8004 return;
8005 }
8006 /* successful reassembly */
8008 "Fragment reassembly complete for message %u\n",
8009 (unsigned int) fb->msg_uuid.uuid);
8010 /* FIXME: check that the resulting msg is NOT a
8011 DV Box or Reliability Box, as that is NOT allowed! */
8012 {
8013 uint16_t rsize = rc->msg_size;
8014 char rbuf[rsize] GNUNET_ALIGN;
8015
8016 /* Copy the reassembled message out and release `rc' BEFORE
8017 demultiplexing: the inner message may tear down the virtual link,
8018 which frees every reassembly context of that link -- the old code
8019 then used and freed `rc' a second time afterwards. */
8020 memcpy (rbuf, msg, rsize);
8022 cmc->mh = (const struct GNUNET_MessageHeader *) rbuf;
8024 }
8025}
8026
8027
8035static int
8037 const struct TransportReliabilityBoxMessage *rb)
8038{
8039 const struct GNUNET_MessageHeader *box = (const struct
8040 GNUNET_MessageHeader *) &rb[1];
8041 (void) cls;
8042
8044 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
8045 ntohs (rb->header.size),
8046 ntohs (box->type),
8047 ntohs (box->size),
8048 sizeof (struct TransportReliabilityBoxMessage),
8049 sizeof (struct GNUNET_MessageHeader));
8051 return GNUNET_YES;
8052}
8053
8054
8062static void
8064 const struct TransportReliabilityBoxMessage *rb)
8065{
8066 struct CommunicatorMessageContext *cmc = cls;
8067 const struct GNUNET_MessageHeader *inbox =
8068 (const struct GNUNET_MessageHeader *) &rb[1];
8069 struct GNUNET_TIME_Relative rtt;
8070
8072 "Received reliability box from %s with UUID %s of type %u\n",
8073 GNUNET_i2s (&cmc->im.sender),
8075 (unsigned int) ntohs (inbox->type));
8076 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
8077 do not really have an RTT for the
8078 * incoming* queue (should we have
8079 the sender add it to the rb message?) */
8081 &cmc->im.sender,
8082 &rb->ack_uuid,
8083 (0 == ntohl (rb->ack_countdown))
8086 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
8087 /* continue with inner message */
8088 /* FIXME: check that inbox is NOT a DV Box, fragment or another
8089 reliability box (not allowed!) */
8090 cmc->mh = inbox;
8092}
8093
8094
8103static void
8104update_pd_age (struct PerformanceData *pd, unsigned int age)
8105{
8106 unsigned int sage;
8107
8108 if (age == pd->last_age)
8109 return; /* nothing to do */
8110 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
8111 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
8112 {
8113 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
8114
8115 the->bytes_sent = 0;
8116 the->bytes_received = 0;
8117 }
8118 pd->last_age = age;
8119}
8120
8121
8130static void
8132 struct GNUNET_TIME_Relative rtt,
8133 uint16_t bytes_transmitted_ok)
8134{
8135 uint64_t nval = rtt.rel_value_us;
8136 uint64_t oval = pd->aged_rtt.rel_value_us;
8137 unsigned int age = get_age ();
8138 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
8139
8140 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
8141 pd->aged_rtt = rtt;
8142 else
8143 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
8144 update_pd_age (pd, age);
8145 the->bytes_received += bytes_transmitted_ok;
8146}
8147
8148
8156static void
8158 struct GNUNET_TIME_Relative rtt,
8159 uint16_t bytes_transmitted_ok)
8160{
8161 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
8162}
8163
8164
8172static void
8174 struct GNUNET_TIME_Relative rtt,
8175 uint16_t bytes_transmitted_ok)
8176{
8177 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
8178}
8179
8180
8188static void
8190{
8191 struct PendingMessage *pos;
8192
8194 "Complete transmission of message %" PRIu64 " %u\n",
8195 pm->logging_uuid,
8196 pm->pmt);
8197 switch (pm->pmt)
8198 {
8199 case PMT_CORE:
8201 /* Full message sent, we are done */
8203 return;
8204
8205 case PMT_FRAGMENT_BOX:
8206 /* Fragment sent over reliable channel */
8207 pos = pm->frag_parent;
8208 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
8211 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
8212 (unsigned long) pos->frag_off,
8213 (unsigned long) pos->bytes_msg,
8214 pos->pmt,
8215 NULL == pos->frag_parent ? 1 : 0);
8216 /* check if subtree is done */
8217 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
8218 - sizeof(struct
8220 &&
8221 (NULL != pos->frag_parent))
8222 {
8223 pm = pos;
8224 pos = pm->frag_parent;
8225 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
8226 {
8228 return;
8229 }
8230 else if (PMT_DV_BOX == pm->pmt)
8231 {
8233 return;
8234 }
8235 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
8237 }
8238
8239 /* Was this the last applicable fragment?
8240
8241 NOTE: @a pos may be a DV box here, and then it is NOT the message the
8242 client is waiting for -- its @e frag_parent is, and that parent's
8243 @e bpm points at @a pos. Answering the client directly (and thereby
8244 releasing @a pos through #free_pending_message()) left @e bpm of a
8245 message that is still queued pointing at freed memory, which
8246 #transmit_on_queue() reads and may free a second time. Hand it to
8247 ourselves instead: the #PMT_DV_BOX case below clears @e bpm and
8248 answers for the parent, and for every other @e pmt it does exactly
8249 what the direct call did. */
8250 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
8251 pos->pmt) &&
8252 (pos->frag_off == pos->bytes_msg))
8254 return;
8255
8256 case PMT_DV_BOX:
8258 "Completed transmission of message %" PRIu64 " (DV Box)\n",
8259 pm->logging_uuid);
8260 if (NULL != pm->frag_parent)
8261 {
8262 pos = pm->frag_parent;
8264 pos->bpm = NULL;
8266 }
8267 else
8269 return;
8270 }
8271}
8272
8273
8281static void
8283 struct GNUNET_TIME_Relative ack_delay)
8284{
8285 struct GNUNET_TIME_Relative delay;
8286 struct PendingMessage *pm = pa->pm;
8287
8289 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
8290 if (NULL != pa->queue && 1 == pa->num_send)
8292 if (NULL != pa->dvh && 1 == pa->num_send)
8293 update_dvh_performance (pa->dvh, delay, pa->message_size);
8294 /* Retire @a pa BEFORE handing its message on. completed_pending_message()
8295 ends in free_pending_message() for anything it finishes, and that now
8296 releases every acknowledgement still attached to the message -- this one
8297 included. Freeing it afterwards is a double free, and it aborts on the
8298 GNUNET_assert() over multiuuidmap_remove() in
8299 free_pending_acknowledgement(), the map entry having gone with the first
8300 release. Nothing below needs @a pa, only its message. */
8302 if (NULL != pm)
8304}
8305
8306
8314static int
8316 const struct TransportReliabilityAckMessage *ra)
8317{
8318 unsigned int n_acks;
8319
8320 (void) cls;
8321 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
8322 / sizeof(struct TransportCummulativeAckPayloadP);
8323 if (0 == n_acks)
8324 {
8325 GNUNET_break_op (0);
8326 return GNUNET_SYSERR;
8327 }
8328 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
8329 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
8330 {
8331 GNUNET_break_op (0);
8332 return GNUNET_SYSERR;
8333 }
8334 return GNUNET_OK;
8335}
8336
8337
8345static void
8347 const struct TransportReliabilityAckMessage *ra)
8348{
8349 struct CommunicatorMessageContext *cmc = cls;
8350 const struct TransportCummulativeAckPayloadP *ack;
8351 unsigned int n_acks;
8352 uint32_t ack_counter;
8353
8354 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
8355 / sizeof(struct TransportCummulativeAckPayloadP);
8356 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
8357 for (unsigned int i = 0; i < n_acks; i++)
8358 {
8359 struct PendingAcknowledgement *pa =
8361 if (NULL == pa)
8362 {
8364 "Received ACK from %s with UUID %s which is unknown to us!\n",
8365 GNUNET_i2s (&cmc->im.sender),
8366 GNUNET_uuid2s (&ack[i].ack_uuid.value));
8368 GST_stats,
8369 "# FRAGMENT_ACKS dropped, no matching pending message",
8370 1,
8371 GNUNET_NO);
8372 continue;
8373 }
8375 "Received ACK from %s with UUID %s\n",
8376 GNUNET_i2s (&cmc->im.sender),
8377 GNUNET_uuid2s (&ack[i].ack_uuid.value));
8378 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
8379 }
8380
8381 ack_counter = ntohl (ra->ack_counter);
8382 (void) ack_counter; /* silence compiler warning for now */
8383 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
8384 // (DV and/or Neighbour?)
8385 finish_cmc_handling (cmc);
8386}
8387
8388
8396static int
8398 void *cls,
8400{
8401 uint16_t size = ntohs (be->header.size) - sizeof(*be);
8402 const struct GNUNET_MessageHeader *inbox =
8403 (const struct GNUNET_MessageHeader *) &be[1];
8404 const char *is;
8405 uint16_t isize;
8406
8407 (void) cls;
8408 /* MUST bound the buffer before reading @a inbox: the size check below
8409 dereferences it, and a message consisting of nothing but the header
8410 leaves no bytes to read. */
8411 if (size <= sizeof(struct GNUNET_MessageHeader))
8412 {
8413 GNUNET_break_op (0);
8414 return GNUNET_SYSERR;
8415 }
8416 if (ntohs (inbox->size) >= size)
8417 {
8418 GNUNET_break_op (0);
8419 return GNUNET_SYSERR;
8420 }
8421 isize = ntohs (inbox->size);
8422 is = ((const char *) inbox) + isize;
8423 size -= isize;
8424 if ('\0' != is[size - 1])
8425 {
8426 GNUNET_break_op (0);
8427 return GNUNET_SYSERR;
8428 }
8429 return GNUNET_YES;
8430}
8431
8432
8441static void
8443 void *cls,
8445{
8446 const struct GNUNET_PeerIdentity *my_identity;
8447 struct CommunicatorMessageContext *cmc = cls;
8449 struct GNUNET_MQ_Envelope *env;
8450 struct TransportClient *tc;
8451 const struct GNUNET_MessageHeader *inbox =
8452 (const struct GNUNET_MessageHeader *) &be[1];
8453 uint16_t isize = ntohs (inbox->size);
8454 const char *target_communicator = ((const char *) inbox) + isize;
8455 char *sender;
8456 char *self;
8457
8460
8461 GNUNET_asprintf (&sender,
8462 "%s",
8463 GNUNET_i2s (&cmc->im.sender));
8464 GNUNET_asprintf (&self,
8465 "%s",
8467
8468 /* Find client providing this communicator */
8469 for (tc = clients_head; NULL != tc; tc = tc->next)
8470 if ((CT_COMMUNICATOR == tc->type) &&
8471 (NULL != tc->details.communicator.address_prefix) &&
8472 (0 ==
8473 strcmp (tc->details.communicator.address_prefix, target_communicator)))
8474 break;
8475 if (NULL == tc)
8476 {
8477 char *stastr;
8478
8480 &stastr,
8481 "# Backchannel message dropped: target communicator `%s' unknown",
8482 target_communicator);
8484 GNUNET_free (stastr);
8485 GNUNET_free (sender);
8486 GNUNET_free (self);
8487 finish_cmc_handling (cmc);
8488 return;
8489 }
8490 /* Finally, deliver backchannel message to communicator */
8492 "Delivering backchannel message from %s to %s of type %u to %s\n",
8493 sender,
8494 self,
8495 ntohs (inbox->type),
8496 target_communicator);
8498 cbi,
8499 isize,
8501 cbi->pid = cmc->im.sender;
8502 memcpy (&cbi[1], inbox, isize);
8503 GNUNET_MQ_send (tc->mq, env);
8504 GNUNET_free (sender);
8505 GNUNET_free (self);
8506 finish_cmc_handling (cmc);
8507}
8508
8509
8519static void
8521{
8522 struct DistanceVector *dv = cls;
8523 struct DistanceVectorHop *pos;
8524 struct GNUNET_TIME_Absolute next;
8525
8526 dv->timeout_task = NULL;
8527 /* @e dv_head is NOT sorted by @e timeout: learn_dv_path() inserts a new
8528 hop at the head, and moves a rediscovered one back to the head, so the
8529 list runs newest (i.e. latest deadline) first. Stopping at the first
8530 live entry therefore inspected exactly the youngest hop and re-armed
8531 for *its* deadline, which is the last one of the whole set: expired
8532 hops behind it were never collected, and check_vl_transmission() kept
8533 skipping them one by one for as long as the route lived. Sweep all of
8534 them and come back for the earliest survivor. */
8536 pos = dv->dv_head;
8537 while (NULL != pos)
8538 {
8539 struct DistanceVectorHop *next_pos = pos->next_dv;
8540
8541 GNUNET_assert (dv == pos->dv);
8544 else
8545 next = GNUNET_TIME_absolute_min (next, pos->timeout);
8546 pos = next_pos;
8547 }
8548 if (NULL == dv->dv_head)
8549 {
8550 free_dv_route (dv);
8551 return;
8552 }
8553 dv->timeout_task =
8555}
8556
8557
8558static void
8560{
8561
8562 const struct GNUNET_PeerIdentity target = vl->target;
8563
8564
8566 {
8567 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
8568 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
8569 0;
8570 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
8573 struct CommunicatorMessageContext *cmc;
8574 struct RingBufferEntry *rbe;
8575 struct GNUNET_MessageHeader *mh;
8576
8578 "Sending from ring buffer, which has %u items\n",
8579 head);
8580
8581 ring_buffer_head = 0;
8582 for (unsigned int i = 0; i < head; i++)
8583 {
8584 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
8585 cmc = rbe->cmc;
8586 mh = rbe->mh;
8587
8588 im = cmc->im;
8589 // mh = cmc->mh;
8591 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
8592 mh->type,
8593 GNUNET_i2s (&im.sender),
8594 GNUNET_i2s2 (&target),
8595 (i + tail) % RING_BUFFER_SIZE);
8596 if (0 == GNUNET_memcmp (&target, &im.sender))
8597 {
8599 "Finish handling message of type %u and size %u\n",
8600 (unsigned int) ntohs (mh->type),
8601 (unsigned int) ntohs (mh->size));
8603 GNUNET_free (mh);
8604 GNUNET_free (rbe->cmc);
8605 GNUNET_free (rbe);
8606 }
8607 else
8608 {
8609 ring_buffer_copy[ring_buffer_head] = rbe;
8611 }
8612 }
8613
8616 {
8618 }
8619
8620 for (unsigned int i = 0; i < ring_buffer_head; i++)
8621 {
8622 ring_buffer[i] = ring_buffer_copy[i];
8624 "ring_buffer[i]->mh->type for i %u %u\n",
8625 i,
8626 ring_buffer[i]->mh->type);
8627 }
8628 /* MUST clear the consumed slots, we freed those entries above */
8629 for (unsigned int i = ring_buffer_head; i < RING_BUFFER_SIZE; i++)
8630 ring_buffer[i] = NULL;
8631
8633 "%u items still in ring buffer\n",
8635 /* If we consumed nothing, compaction rewrote the buffer in place and
8636 left the write index one past the end. #handle_raw_message() would
8637 then read ring_buffer[RING_BUFFER_SIZE] and free whatever that is.
8638 The buffer is still full, and compaction moved the oldest entry to
8639 slot 0, so that is where the next write belongs. */
8641 ring_buffer_head = 0;
8642 }
8643
8645 {
8646 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
8647 struct PendingMessage *pm;
8648 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
8650 0;
8651 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
8654
8656 "Sending from ring buffer dv, which has %u items\n",
8657 head);
8658
8660 for (unsigned int i = 0; i < head; i++)
8661 {
8662 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
8663
8665 "Sending to ring buffer target %s using vl target %s\n",
8666 GNUNET_i2s (&pm->target),
8667 GNUNET_i2s2 (&target));
8668 if (0 == GNUNET_memcmp (&target, &pm->target))
8669 {
8671 "Adding PendingMessage to vl, checking transmission.\n");
8672 pm->vl = vl;
8676 pm);
8677
8679 }
8680 else
8681 {
8682 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
8684 }
8685 }
8686
8688 {
8690 }
8691
8692 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
8693 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
8694 /* MUST clear the consumed slots: entries we handed to a VirtualLink are
8695 now owned by that link, and #forward_dv_box() would GNUNET_free() them
8696 again once the ring buffer wraps around. */
8697 for (unsigned int i = ring_buffer_dv_head; i < RING_BUFFER_SIZE; i++)
8698 ring_buffer_dv[i] = NULL;
8699
8701 "%u items still in ring buffer dv.\n",
8703 /* Same one-past-the-end hazard as above: #forward_dv_box() reads
8704 ring_buffer_dv[ring_buffer_dv_head] and GNUNET_free()s it. */
8707 }
8708}
8709
8710
8718static void
8720{
8721 struct DistanceVector *dv = hop->dv;
8722 struct VirtualLink *vl;
8723
8724 vl = lookup_virtual_link (&dv->target);
8725 if (NULL == vl)
8726 {
8727
8728 vl = GNUNET_new (struct VirtualLink);
8730 "Creating new virtual link %p to %s using DV!\n",
8731 vl,
8732 GNUNET_i2s (&dv->target));
8733 vl->burst_addr = NULL;
8734 vl->confirmed = GNUNET_YES;
8735 vl->message_uuid_ctr =
8736 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
8737 vl->target = dv->target;
8741 /* What the peer will grant us in its very first FLOW_CONTROL anyway
8742 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
8743 Starting at zero instead means a link that is up, validated and
8744 working carries nothing at all until an FC round trip completes --
8745 and if the peer cannot answer, not ever. */
8749 links,
8750 &vl->target,
8751 vl,
8753 vl->dv = dv;
8754 dv->vl = vl;
8755 vl->visibility_task =
8758 /* We lacked a confirmed connection to the target
8759 before, so tell CORE about it (finally!) */
8762 }
8763 else
8764 {
8765 /* Link was already up, remember dv is also now available and we are done */
8766 vl->dv = dv;
8767 dv->vl = vl;
8768 if (GNUNET_NO == vl->confirmed)
8769 {
8770 vl->confirmed = GNUNET_YES;
8771 vl->visibility_task =
8774 /* We lacked a confirmed connection to the target
8775 before, so tell CORE about it (finally!) */
8778 }
8779 else
8781 "Virtual link to %s could now also use DV!\n",
8782 GNUNET_i2s (&dv->target));
8783 }
8784}
8785
8786
8812static int
8814 unsigned int path_len,
8815 struct GNUNET_TIME_Relative network_latency,
8816 struct GNUNET_TIME_Absolute path_valid_until)
8817{
8818 const struct GNUNET_PeerIdentity *my_identity;
8819 struct DistanceVectorHop *hop;
8820 struct DistanceVector *dv;
8821 struct Neighbour *next_hop;
8822 unsigned int shorter_distance;
8823
8824 if (path_len < 3)
8825 {
8826 /* what a boring path! not allowed! */
8827 GNUNET_break (0);
8828 return GNUNET_SYSERR;
8829 }
8830
8833
8834 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
8835 next_hop = lookup_neighbour (&path[1]);
8836 if (NULL == next_hop)
8837 {
8838 /* next hop must be a neighbour, otherwise this whole thing is useless! */
8839 GNUNET_break (0);
8840 return GNUNET_SYSERR;
8841 }
8842 for (unsigned int i = 2; i < path_len; i++)
8843 {
8844 struct Neighbour *n = lookup_neighbour (&path[i]);
8845 struct GNUNET_TIME_Absolute q_timeout;
8846
8847 if (NULL != n)
8848 {
8849 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
8850 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
8851 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
8853 "remaining %lu to %s\n",
8854 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
8855 .rel_value_us,
8856 GNUNET_i2s (&n->pid));
8857 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
8858 {
8859 /* Useless path: we have a direct active connection to some hop
8860 in the middle of the path, so this one is not even
8861 terribly useful for redundancy */
8863 "Path of %u hops useless: directly link to hop %u (%s)\n",
8864 path_len,
8865 i,
8866 GNUNET_i2s (&path[i]));
8868 "# Useless DV path ignored: hop is neighbour",
8869 1,
8870 GNUNET_NO);
8871 return GNUNET_SYSERR;
8872 }
8873 }
8874 }
8875 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
8876 if (NULL == dv)
8877 {
8878 dv = GNUNET_new (struct DistanceVector);
8879 dv->target = path[path_len - 1];
8882 dv);
8885 dv_routes,
8886 &dv->target,
8887 dv,
8889 }
8890 /* Check if we have this path already! */
8891 shorter_distance = 0;
8892 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
8893 pos = pos->next_dv)
8894 {
8895 if (pos->distance < path_len - 3)
8896 shorter_distance++;
8897 /* Note that the distances in 'pos' excludes us (path[0]),
8898 the next_hop (path[1]) and the target so we need to subtract three
8899 and check next_hop explicitly */
8900 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
8901 {
8902 int match = GNUNET_YES;
8903
8904 for (unsigned int i = 0; i < pos->distance; i++)
8905 {
8906 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
8907 {
8908 match = GNUNET_NO;
8909 break;
8910 }
8911 }
8912 if (GNUNET_YES == match)
8913 {
8914 struct GNUNET_TIME_Relative last_timeout;
8915
8916 /* Re-discovered known path, update timeout */
8918 "# Known DV path refreshed",
8919 1,
8920 GNUNET_NO);
8921 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
8922 pos->timeout =
8924 pos->path_valid_until =
8925 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
8926 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
8927 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
8928 if (0 <
8931 if (last_timeout.rel_value_us <
8934 .rel_value_us)
8935 {
8936 /* Some peer send DV learn messages too often, we are learning
8937 the same path faster than it would be useful; do not forward! */
8939 "Rediscovered path too quickly, not forwarding further\n")
8940 ;
8941 return GNUNET_NO;
8942 }
8944 "Refreshed known path to %s valid until %s, forwarding further\n",
8945 GNUNET_i2s (&dv->target),
8947 pos->path_valid_until));
8948 return GNUNET_YES;
8949 }
8950 }
8951 }
8952 /* Count how many shorter paths we have (incl. direct
8953 neighbours) before simply giving up on this one! */
8954 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
8955 {
8956 /* We have a shorter path already! */
8958 "Have many shorter DV paths %s, not forwarding further\n",
8959 GNUNET_i2s (&dv->target));
8960 return GNUNET_NO;
8961 }
8962 /* create new DV path entry */
8964 "Discovered new DV path to %s valid until %s\n",
8965 GNUNET_i2s (&dv->target),
8966 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
8967 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
8968 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
8969 hop->next_hop = next_hop;
8970 hop->dv = dv;
8971 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
8972 memcpy (&hop[1],
8973 &path[2],
8974 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
8976 hop->path_valid_until = path_valid_until;
8977 hop->distance = path_len - 3;
8978 hop->pd.aged_rtt = network_latency;
8979 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
8981 next_hop->dv_head,
8982 next_hop->dv_tail,
8983 hop);
8984 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
8986 return GNUNET_YES;
8987}
8988
8989
8997static int
8998check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8999{
9000 const struct GNUNET_PeerIdentity *my_identity;
9001 uint16_t size = ntohs (dvl->header.size);
9002 uint16_t num_hops = ntohs (dvl->num_hops);
9003 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
9004
9005 (void) cls;
9006 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
9007 {
9008 GNUNET_break_op (0);
9009 return GNUNET_SYSERR;
9010 }
9011 if (num_hops > MAX_DV_HOPS_ALLOWED)
9012 {
9013 GNUNET_break_op (0);
9014 return GNUNET_SYSERR;
9015 }
9016
9019
9020 for (unsigned int i = 0; i < num_hops; i++)
9021 {
9022 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
9023 {
9024 GNUNET_break_op (0);
9025 return GNUNET_SYSERR;
9026 }
9027 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
9028 {
9029 GNUNET_break_op (0);
9030 return GNUNET_SYSERR;
9031 }
9032 }
9033 return GNUNET_YES;
9034}
9035
9036
9048static void
9050 const struct TransportDVLearnMessage *msg,
9051 uint16_t bi_history,
9052 uint16_t nhops,
9053 const struct DVPathEntryP *hops,
9054 struct GNUNET_TIME_Absolute in_time)
9055{
9056 struct DVPathEntryP *dhops;
9057 size_t fwd_size = sizeof(struct TransportDVLearnMessage)
9058 + (nhops + 1) * sizeof(struct DVPathEntryP);
9059 /* Signing is synchronous and the routing calls below copy the message,
9060 so this never outlives the frame. Keeping it on the stack matters:
9061 a hub forwards a DV learn to every eligible neighbour, so this is one
9062 of the hottest allocation sites in the service. Size it by the hop
9063 limit rather than by @a nhops -- @a nhops is only asserted to be below
9064 that limit further down, and a VLA is sized before we get there. */
9065 char fwd_buf[sizeof(struct TransportDVLearnMessage)
9066 + (MAX_DV_HOPS_ALLOWED + 1)
9067 * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
9068 struct TransportDVLearnMessage *fwd
9069 = (struct TransportDVLearnMessage *) fwd_buf;
9070 struct GNUNET_TIME_Relative nnd;
9071 const struct GNUNET_PeerIdentity *my_identity;
9072 struct VirtualLink *vl;
9073 struct Neighbour *n;
9074
9076 memset (fwd_buf, 0, fwd_size);
9077
9078 /* compute message for forwarding */
9080 "Forwarding DV learn message originating from %s to %s\n",
9081 GNUNET_i2s (&msg->initiator),
9082 GNUNET_i2s2 (next_hop));
9085 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
9086 + (nhops + 1) * sizeof(struct DVPathEntryP));
9087 fwd->num_hops = htons (nhops + 1);
9088 fwd->bidirectional = htons (bi_history);
9091 msg->non_network_delay));
9093 fwd->init_sig = msg->init_sig;
9094 fwd->initiator = msg->initiator;
9095 fwd->challenge = msg->challenge;
9096 fwd->monotonic_time = msg->monotonic_time;
9097
9100
9101 dhops = (struct DVPathEntryP *) &fwd[1];
9102 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
9103 dhops[nhops].hop = *my_identity;
9104 {
9105 struct DvHopPS dhp = {
9107 .purpose.size = htonl (sizeof(dhp)),
9108 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
9109 .succ = *next_hop,
9110 .challenge = msg->challenge
9111 };
9112
9114 &dhops[nhops].hop_sig))
9115 return; /* nobody would accept the path without our hop signature */
9116 }
9117 vl = lookup_virtual_link (next_hop);
9118 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9119 {
9121 &fwd->header,
9123 return;
9124 }
9125 /* Use route via neighbour */
9126 n = lookup_neighbour (next_hop);
9127 if (NULL != n)
9129 &fwd->header,
9131}
9132
9133
9143static int
9145 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
9146 const struct GNUNET_PeerIdentity *init,
9148 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
9149{
9150 struct DvInitPS ip = { .purpose.purpose = htonl (
9152 .purpose.size = htonl (sizeof(ip)),
9153 .monotonic_time = sender_monotonic_time,
9154 .challenge = *challenge };
9155
9156 if (
9157 GNUNET_OK !=
9159 &ip,
9160 init_sig,
9161 &init->public_key))
9162 {
9163 GNUNET_break_op (0);
9164 return GNUNET_SYSERR;
9165 }
9166 return GNUNET_OK;
9167}
9168
9169
9174{
9179
9183 const struct DVPathEntryP *hops;
9184
9189
9194
9198 unsigned int num_eligible;
9199
9203 unsigned int num_selections;
9204
9208 uint16_t nhops;
9209
9213 uint16_t bi_history;
9214};
9215
9216
9225static int
9227 const struct GNUNET_PeerIdentity *pid,
9228 void *value)
9229{
9230 struct NeighbourSelectionContext *nsc = cls;
9231
9232 (void) value;
9233 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
9234 return GNUNET_YES; /* skip initiator */
9235 for (unsigned int i = 0; i < nsc->nhops; i++)
9236 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
9237 return GNUNET_YES;
9238 /* skip peers on path */
9239 nsc->num_eligible++;
9240 return GNUNET_YES;
9241}
9242
9243
9254static int
9256 const struct GNUNET_PeerIdentity *pid,
9257 void *value)
9258{
9259 struct NeighbourSelectionContext *nsc = cls;
9260
9262 "transmission %s\n",
9263 GNUNET_i2s (pid));
9264 (void) value;
9265 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
9266 return GNUNET_YES; /* skip initiator */
9267 for (unsigned int i = 0; i < nsc->nhops; i++)
9268 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
9269 return GNUNET_YES;
9270 /* skip peers on path */
9271 for (unsigned int i = 0; i < nsc->num_selections; i++)
9272 {
9273 if (nsc->selections[i] == nsc->num_eligible)
9274 {
9275 forward_dv_learn (pid,
9276 nsc->dvl,
9277 nsc->bi_history,
9278 nsc->nhops,
9279 nsc->hops,
9280 nsc->in_time);
9281 break;
9282 }
9283 }
9284 nsc->num_eligible++;
9285 return GNUNET_YES;
9286}
9287
9288
9332static unsigned int
9333calculate_fork_degree (unsigned int hops_taken,
9334 unsigned int neighbour_count,
9335 unsigned int eligible_count)
9336{
9337 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
9338 double eligible_ratio =
9339 ((double) eligible_count) / ((double) neighbour_count);
9340 double boost_factor = eligible_ratio * eligible_ratio;
9341 unsigned int rnd;
9342 double left;
9343
9344 if (hops_taken >= 64)
9345 {
9346 GNUNET_break (0);
9347 return 0; /* precaution given bitshift below */
9348 }
9349 for (unsigned int i = 1; i < hops_taken; i++)
9350 {
9351 /* For each hop, subtract the expected number of targets
9352 reached at distance d (so what remains divided by 2^d) */
9353 target_total -= (target_total * boost_factor / (1LLU << i));
9354 }
9355 {
9356 double degree = target_total * boost_factor / (1LLU << hops_taken);
9357
9358 rnd = (unsigned int) floor (degree);
9359 /* round up or down probabilistically depending on how close we were
9360 when floor()ing to rnd. NOTE: this must be the fractional part of
9361 @e degree; using `target_total - rnd' here made the condition below
9362 true essentially always, so we always rounded up. */
9363 left = degree - (double) rnd;
9364 }
9365 if (UINT32_MAX * left >
9366 GNUNET_CRYPTO_random_u64 (UINT32_MAX))
9367 rnd++; /* round up */
9369 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
9370 hops_taken,
9371 rnd,
9372 eligible_count,
9373 neighbour_count);
9374 return rnd;
9375}
9376
9377
9384static void
9385neighbour_store_dvmono_cb (void *cls, int success)
9386{
9387 struct Neighbour *n = cls;
9388
9389 n->sc = NULL;
9390 if (GNUNET_YES != success)
9392 "Failed to store other peer's monotonic time in peerstore!\n");
9393}
9394
9395
9396static struct GNUNET_TIME_Relative
9398{
9399 struct GNUNET_TIME_Relative host_latency_sum;
9400 struct GNUNET_TIME_Relative latency;
9401 struct GNUNET_TIME_Relative network_latency;
9402 uint16_t nhops = ntohs (dvl->num_hops);;
9403
9404 /* We initiated this, learn the forward path! */
9405 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
9406
9407 // Need also something to lookup initiation time
9408 // to compute RTT! -> add RTT argument here?
9410 dvl->monotonic_time));
9411 /* @e non_network_delay is fully attacker-controlled, and our clock may
9412 simply be behind the initiator's: never assert on this. */
9413 if (latency.rel_value_us < host_latency_sum.rel_value_us)
9414 {
9416 "# DV learn with implausible non-network delay",
9417 1,
9418 GNUNET_NO);
9420 }
9421 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
9422 // (based on dvl->challenge, we can identify time of origin!)
9423
9424 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
9425 /* assumption: latency on all links is the same */
9426 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
9427
9428 return network_latency;
9429}
9430
9431
9439static void
9440handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
9441{
9442 struct CommunicatorMessageContext *cmc = cls;
9444 int bi_hop;
9445 uint16_t nhops;
9446 uint16_t bi_history;
9447 const struct DVPathEntryP *hops;
9448 int do_fwd;
9449 int did_initiator;
9450 struct GNUNET_TIME_Absolute in_time;
9451 struct Neighbour *n;
9452 const struct GNUNET_PeerIdentity *my_identity;
9453
9454 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
9455 bi_history = ntohs (dvl->bidirectional);
9456 hops = (const struct DVPathEntryP *) &dvl[1];
9457 if (0 == nhops)
9458 {
9459 /* sanity check */
9460 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
9461 {
9462 GNUNET_break (0);
9463 finish_cmc_handling (cmc);
9464 return;
9465 }
9466 /* A zero-hop message we supposedly initiated ourselves would make the
9467 "we are the initiator" branch below read hops[0] and write past the
9468 end of its `path[nhops + 1]' array. */
9470 {
9471 GNUNET_break_op (0);
9472 finish_cmc_handling (cmc);
9473 return;
9474 }
9475 }
9476 else
9477 {
9479 "handle dv learn message last hop %s\n",
9480 GNUNET_i2s (&hops[nhops - 1].hop));
9481 /* sanity check */
9482 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
9483 {
9484 GNUNET_break (0);
9485 finish_cmc_handling (cmc);
9486 return;
9487 }
9488 }
9489
9491 cc = cmc->tc->details.communicator.cc;
9492 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
9493 cc); // FIXME: add bi-directional flag to cc?
9494 in_time = GNUNET_TIME_absolute_get ();
9495
9496 /* continue communicator here, everything else can happen asynchronous! */
9497 finish_cmc_handling (cmc);
9498
9499 n = lookup_neighbour (&dvl->initiator);
9500 if (NULL != n)
9501 {
9502 if ((n->dv_monotime_available == GNUNET_YES) &&
9505 {
9507 "DV learn from %s discarded due to time travel",
9508 GNUNET_i2s (&dvl->initiator));
9510 "# DV learn discarded due to time travel",
9511 1,
9512 GNUNET_NO);
9513 return;
9514 }
9516 &dvl->initiator,
9517 &dvl->challenge,
9518 &dvl->init_sig))
9519 {
9521 "DV learn signature from %s invalid\n",
9522 GNUNET_i2s (&dvl->initiator));
9523 GNUNET_break_op (0);
9524 return;
9525 }
9528 {
9529 if (NULL != n->sc)
9530 {
9532 "store cancel\n");
9534 }
9535 n->sc =
9537 "transport",
9538 &dvl->initiator,
9540 &dvl->monotonic_time,
9541 sizeof(dvl->monotonic_time),
9545 n);
9546 }
9547 }
9548
9551
9552 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
9553 If signature verification load too high, implement random drop strategy */
9554 for (unsigned int i = 0; i < nhops; i++)
9555 {
9556 struct DvHopPS dhp = { .purpose.purpose =
9558 .purpose.size = htonl (sizeof(dhp)),
9559 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
9560 .succ = (nhops == i + 1) ? *my_identity
9561 : hops[i + 1].hop,
9562 .challenge = dvl->challenge };
9563
9564 if (GNUNET_OK !=
9566 &dhp,
9567 &hops[i].hop_sig,
9568 &hops[i].hop.public_key))
9569 {
9571 "DV learn from %s signature of hop %u invalid\n",
9572 GNUNET_i2s (&dvl->initiator),
9573 i);
9575 "signature of hop %s invalid\n",
9576 GNUNET_i2s (&hops[i].hop));
9578 "pred %s\n",
9579 GNUNET_i2s (&dhp.pred));
9581 "succ %s\n",
9582 GNUNET_i2s (&dhp.succ));
9584 "hash %s\n",
9585 GNUNET_sh2s (&dhp.challenge.value));
9586 GNUNET_break_op (0);
9587 return;
9588 }
9589 }
9590 if (GNUNET_EXTRA_LOGGING > 0)
9591 {
9592 char *path;
9593
9594 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
9595 for (unsigned int i = 0; i < nhops; i++)
9596 {
9597 char *tmp;
9598
9599 GNUNET_asprintf (&tmp,
9600 "%s%s%s",
9601 path,
9602 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
9603 GNUNET_i2s (&hops[i].hop));
9604 GNUNET_free (path);
9605 path = tmp;
9606 }
9608 "Received DVInit via %s%s%s\n",
9609 path,
9610 bi_hop ? "<->" : "-->",
9612 GNUNET_free (path);
9613 }
9614 do_fwd = GNUNET_YES;
9615 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
9616 {
9617 struct GNUNET_PeerIdentity path[nhops + 1];
9618 struct GNUNET_TIME_Relative network_latency;
9619
9620 /* We initiated this, learn the forward path! */
9621 path[0] = *my_identity;
9622 path[1] = hops[0].hop;
9623
9624 network_latency = get_network_latency (dvl);
9625
9626 for (unsigned int i = 2; i <= nhops; i++)
9627 {
9628 struct GNUNET_TIME_Relative ilat;
9629
9630 /* assumption: linear latency increase per hop */
9631 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
9632 path[i] = hops[i - 1].hop;
9634 "Learned path with %u hops to %s with latency %s\n",
9635 i,
9636 GNUNET_i2s (&path[i]),
9638 learn_dv_path (path,
9639 i + 1,
9640 ilat,
9643 }
9644 /* as we initiated, do not forward again (would be circular!) */
9645 do_fwd = GNUNET_NO;
9646 return;
9647 }
9648 if (bi_hop)
9649 {
9650 /* last hop was bi-directional, we could learn something here! */
9651 struct GNUNET_PeerIdentity path[nhops + 2];
9652 struct GNUNET_TIME_Relative ilat;
9653 struct GNUNET_TIME_Relative network_latency;
9654
9655 path[0] = *my_identity;
9656 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
9657 for (unsigned int i = 0; i < nhops; i++)
9658 {
9659 int iret;
9660
9661 if (0 == (bi_history & (1 << i)))
9662 break; /* i-th hop not bi-directional, stop learning! */
9663 if (i == nhops - 1)
9664 {
9665 path[i + 2] = dvl->initiator;
9666 }
9667 else
9668 {
9669 path[i + 2] = hops[nhops - i - 2].hop;
9670 }
9671
9673 "Learned inverse path with %u hops to %s\n",
9674 i + 2,
9675 GNUNET_i2s (&path[i + 2]));
9676 network_latency = get_network_latency (dvl);
9677 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
9678 iret = learn_dv_path (path,
9679 i + 3,
9680 ilat,
9683 if (GNUNET_SYSERR == iret)
9684 {
9685 /* path invalid or too long to be interesting for US, thus should also
9686 not be interesting to our neighbours, cut path when forwarding to
9687 'i' hops, except of course for the one that goes back to the
9688 initiator */
9690 "# DV learn not forwarded due invalidity of path",
9691 1,
9692 GNUNET_NO);
9693 do_fwd = GNUNET_NO;
9694 break;
9695 }
9696 if ((GNUNET_NO == iret) && (nhops == i + 1))
9697 {
9698 /* we have better paths, and this is the longest target,
9699 so there cannot be anything interesting later */
9701 "# DV learn not forwarded, got better paths",
9702 1,
9703 GNUNET_NO);
9704 do_fwd = GNUNET_NO;
9705 break;
9706 }
9707 }
9708 }
9709 if (MAX_DV_HOPS_ALLOWED == nhops)
9710 {
9711 /* At limit, we're out of here! */
9712 return;
9713 }
9714
9715 /* Forward to initiator, if path non-trivial and possible */
9716 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
9717 did_initiator = GNUNET_NO;
9718 if ((1 <= nhops) &&
9719 (GNUNET_YES ==
9721 {
9722 /* send back to origin! */
9724 "Sending DVL back to initiator %s\n",
9725 GNUNET_i2s (&dvl->initiator));
9726 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
9727 did_initiator = GNUNET_YES;
9728 }
9729 /* We forward under two conditions: either we still learned something
9730 ourselves (do_fwd), or the path was darn short and thus the initiator is
9731 likely to still be very interested in this (and we did NOT already
9732 send it back to the initiator) */
9733 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
9734 (GNUNET_NO == did_initiator)))
9735 {
9736 /* Pick random neighbours that are not yet on the path */
9737 struct NeighbourSelectionContext nsc;
9738 unsigned int n_cnt;
9739 unsigned int n_eligible;
9740
9742 nsc.nhops = nhops;
9743 nsc.dvl = dvl;
9744 nsc.bi_history = bi_history;
9745 nsc.hops = hops;
9746 nsc.in_time = in_time;
9747 nsc.num_eligible = 0;
9750 &nsc);
9751 if (0 == nsc.num_eligible)
9752 return; /* done here, cannot forward to anyone else */
9753 n_eligible = nsc.num_eligible;
9754 nsc.num_selections = calculate_fork_degree (nhops, n_cnt, n_eligible);
9755 nsc.num_selections =
9758 "Forwarding DVL to %u other peers\n",
9759 nsc.num_selections);
9760 /* #dv_neighbour_transmission() counts ELIGIBLE peers only, so the
9761 offsets must be drawn from that range -- drawing from the total
9762 number of neighbours made us silently forward to fewer peers than
9763 #calculate_fork_degree() asked for. */
9764 for (unsigned int i = 0; i < nsc.num_selections; i++)
9765 nsc.selections[i] =
9766 (nsc.num_selections == n_eligible)
9767 ? i /* all were selected, avoid collisions by chance */
9768 : GNUNET_CRYPTO_random_u32 (n_eligible);
9769 nsc.num_eligible = 0;
9772 &nsc);
9773 }
9774}
9775
9776
9784static int
9785check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9786{
9787 uint16_t size = ntohs (dvb->header.size);
9788 uint16_t num_hops = ntohs (dvb->num_hops);
9789 uint16_t total_hops = ntohs (dvb->total_hops);
9790 uint16_t orig_size = ntohs (dvb->orig_size);
9791 const struct GNUNET_PeerIdentity *hops =
9792 (const struct GNUNET_PeerIdentity *) &dvb[1];
9793 const struct GNUNET_PeerIdentity *my_identity;
9794
9795 (void) cls;
9796 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
9797 + sizeof(struct GNUNET_MessageHeader))
9798 {
9799 GNUNET_break_op (0);
9800 return GNUNET_SYSERR;
9801 }
9802 if ((num_hops > MAX_DV_HOPS_ALLOWED) ||
9803 (total_hops > MAX_DV_HOPS_ALLOWED))
9804 {
9805 GNUNET_break_op (0);
9806 return GNUNET_SYSERR;
9807 }
9808 /* #decaps_dv_box_cb() derives a VLA size from
9809 orig_size - sizeof(*dvb) - total_hops * sizeof (struct
9810 GNUNET_PeerIdentity); make sure that cannot underflow and that the
9811 remainder can plausibly hold a payload header plus a message. */
9812 if ((orig_size < size) ||
9813 (orig_size < sizeof(*dvb)
9814 + total_hops * sizeof(struct GNUNET_PeerIdentity)
9815 + sizeof(struct TransportDVBoxPayloadP)
9816 + sizeof(struct GNUNET_MessageHeader)))
9817 {
9818 GNUNET_break_op (0);
9819 return GNUNET_SYSERR;
9820 }
9821
9824
9825 /* This peer must not be on the path */
9826 for (unsigned int i = 0; i < num_hops; i++)
9827 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9828 {
9829 GNUNET_break_op (0);
9830 return GNUNET_SYSERR;
9831 }
9832 return GNUNET_YES;
9833}
9834
9835
9848static void
9849forward_dv_box (struct Neighbour *next_hop,
9850 struct TransportDVBoxMessage *hdr,
9851 uint16_t total_hops,
9852 uint16_t num_hops,
9853 const struct GNUNET_PeerIdentity *hops,
9854 const void *enc_payload,
9855 uint16_t enc_payload_size)
9856{
9857 struct VirtualLink *vl = next_hop->vl;
9858 struct PendingMessage *pm;
9859 size_t msg_size = sizeof(struct TransportDVBoxMessage)
9860 + num_hops * sizeof(struct GNUNET_PeerIdentity)
9861 + enc_payload_size;
9862 char *buf;
9863 char msg_buf[msg_size] GNUNET_ALIGN;
9864 struct GNUNET_PeerIdentity *dhops;
9865
9866 hdr->num_hops = htons (num_hops);
9867 hdr->total_hops = htons (total_hops);
9868 hdr->header.size = htons (msg_size);
9869 memcpy (msg_buf, hdr, sizeof(*hdr));
9870 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
9872 ;
9873 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
9874 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
9875
9876 if (GNUNET_YES == ntohl (hdr->without_fc))
9877 {
9879 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
9880 enc_payload_size,
9881 GNUNET_i2s (&next_hop->pid),
9882 (unsigned int) num_hops,
9883 (unsigned int) total_hops);
9884 route_via_neighbour (next_hop, (const struct
9885 GNUNET_MessageHeader *) msg_buf,
9887 }
9888 else
9889 {
9890 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
9892 "2 created pm %p storing vl %p \n",
9893 pm,
9894 vl);
9895 pm->pmt = PMT_DV_BOX;
9896 pm->vl = vl;
9897 pm->target = next_hop->pid;
9901 pm->bytes_msg = msg_size;
9902 buf = (char *) &pm[1];
9903 memcpy (buf, msg_buf, msg_size);
9904
9906 "Created pending message %" PRIu64
9907 " for DV Box with next hop %s (%u/%u)\n",
9908 pm->logging_uuid,
9909 GNUNET_i2s (&next_hop->pid),
9910 (unsigned int) num_hops,
9911 (unsigned int) total_hops);
9912
9913 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9914 {
9916 vl->pending_msg_head,
9917 vl->pending_msg_tail,
9918 pm);
9919
9921 }
9922 else
9923 {
9925 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
9926
9928 {
9930
9931 GNUNET_free (pm_old);
9932 }
9935 {
9938 }
9939 else
9941
9943 "%u items stored in DV ring buffer\n",
9946 }
9947 }
9948}
9949
9950
9956static void
9958{
9959 if (NULL != b->get)
9960 {
9962 b->get = NULL;
9963 GNUNET_assert (NULL != b->cmc);
9965 b->cmc = NULL;
9966 }
9967 if (NULL != b->task)
9968 {
9970 b->task = NULL;
9971 }
9972 if (NULL != b->sc)
9973 {
9975 "store cancel\n");
9977 b->sc = NULL;
9978 }
9980 "Removing backtalker for %s\n",
9981 GNUNET_i2s (&b->pid));
9983 GNUNET_YES ==
9985 GNUNET_free (b);
9986}
9987
9988
9997static int
9999 const struct GNUNET_PeerIdentity *pid,
10000 void *value)
10001{
10002 struct Backtalker *b = value;
10003
10004 (void) cls;
10005 (void) pid;
10006 free_backtalker (b);
10007 return GNUNET_OK;
10008}
10009
10010
10016static void
10018{
10019 struct Backtalker *b = cls;
10020
10022 "backtalker timeout.\n");
10023 b->task = NULL;
10025 {
10027 return;
10028 }
10029 /* A monotime store may well still be in flight -- @e timeout is about how
10030 long the *peer* has been quiet, and says nothing about PEERSTORE. This
10031 used to `GNUNET_assert (NULL == b->sc)', which aborted the service in
10032 exactly that case. #free_backtalker() cancels the store. */
10033 free_backtalker (b);
10034}
10035
10036
10045static void
10047 const struct GNUNET_PEERSTORE_Record *record,
10048 const char *emsg)
10049{
10050 struct Backtalker *b = cls;
10051 struct GNUNET_TIME_AbsoluteNBO *mtbe;
10052 struct GNUNET_TIME_Absolute mt;
10053
10054 (void) emsg;
10055 if (NULL == record)
10056 {
10057 struct CommunicatorMessageContext *cmc;
10058
10059 /* we're done with #backtalker_monotime_cb() invocations,
10060 continue normal processing */
10061 b->get = NULL;
10062 GNUNET_assert (NULL != b->cmc);
10063 /* Take @e cmc out of @a b *before* dispatching: the dispatch runs
10064 arbitrary message handling, and writing `b->cmc = NULL' afterwards
10065 is a write to freed memory should anything on that path have
10066 released @a b. #free_backtalker() keys its "must finish the parked
10067 cmc" decision off @e get, which is already NULL here, so clearing
10068 @e cmc early cannot lose the message either. */
10069 cmc = b->cmc;
10070 b->cmc = NULL;
10071 cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
10072 if (0 != b->body_size)
10074 else
10075 finish_cmc_handling (cmc);
10076 return;
10077 }
10078 if (sizeof(*mtbe) != record->value_size)
10079 {
10081 GNUNET_break (0);
10082 return;
10083 }
10084 mtbe = record->value;
10085 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
10087 {
10089 "Backtalker message from %s dropped, monotime in the past\n",
10090 GNUNET_i2s (&b->pid));
10092 GST_stats,
10093 "# Backchannel messages dropped: monotonic time not increasing",
10094 1,
10095 GNUNET_NO);
10096 b->monotonic_time = mt;
10097 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
10098 */
10099 b->body_size = 0;
10100 }
10102}
10103
10104
10112static void
10113backtalker_monotime_store_cb (void *cls, int success)
10114{
10115 struct Backtalker *b = cls;
10116
10117 if (GNUNET_OK != success)
10118 {
10120 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
10121 }
10122 b->sc = NULL;
10123 /* @e task is armed for the whole life of @a b -- #backtalker_timeout_cb()
10124 re-arms itself whenever @e timeout has moved forward -- so there is
10125 nothing to do here beyond releasing the store. It used to cancel and
10126 re-add the task, which is what made the task's existence depend on this
10127 callback ever running. */
10128 GNUNET_assert (NULL != b->task);
10129}
10130
10131
10137static void
10139{
10140 struct GNUNET_TIME_AbsoluteNBO mtbe;
10141
10142 /* At most one store may be outstanding. The value we are about to write
10143 supersedes whatever the previous one carried, and leaving the old
10144 context alive means its completion clears @e sc while the newer store
10145 is still in flight -- after which the next update sees a NULL @e sc and
10146 starts a third one. Cancelling is also what keeps @e sc from being
10147 silently overwritten and leaked.
10148
10149 Note what this must NOT do: touch @e task. That task is the only thing
10150 that ever releases a `struct CommunicatorMessageContext' parked in
10151 @e cmc, and cancelling it here left its re-arming up to
10152 #backtalker_monotime_store_cb() -- i.e. up to PEERSTORE answering. A
10153 lost store completion then stalled the parked communicator client for
10154 the life of the process. #backtalker_timeout_cb() already re-arms
10155 itself against the current @e timeout, so the task needs no help. */
10156 if (NULL != b->sc)
10157 {
10159 "Superseding in-flight backtalker monotime store %p\n",
10160 b->sc);
10162 b->sc = NULL;
10163 }
10165 b->sc =
10167 "transport",
10168 &b->pid,
10170 &mtbe,
10171 sizeof(mtbe),
10175 b);
10176}
10177
10178
10187static void
10189 const struct TransportDVBoxMessage *dvb,
10190 const struct GNUNET_ShortHashCode *km)
10191{
10192 const unsigned char *hdr;
10193 size_t hdr_len;
10195
10196 key = (struct GNUNET_CRYPTO_AeadSecretKey*) km;
10197 /* We are the ultimate target, so #handle_dv_box() has established that no
10198 hop entries are left: the ciphertext directly follows the header, and
10199 its length is what we actually received. Deriving it from orig_size
10200 and total_hops instead would only be equivalent if every forwarder
10201 accounted its skipped hops exactly. */
10202 hdr = (const unsigned char *) &dvb[1];
10203 {
10204 uint16_t size = ntohs (dvb->header.size);
10205
10206 if (size < sizeof(*dvb)
10207 + sizeof(struct TransportDVBoxPayloadP)
10208 + sizeof(struct GNUNET_MessageHeader))
10209 {
10210 GNUNET_break_op (0);
10211 finish_cmc_handling (cmc);
10212 return;
10213 }
10214 hdr_len = size - sizeof(*dvb);
10215 }
10216
10217 /* begin actual decryption */
10218 {
10219 struct Backtalker *b;
10220 struct GNUNET_TIME_Absolute monotime;
10221 struct TransportDVBoxPayloadP *ppay;
10222 unsigned char pt[hdr_len + sizeof *ppay] GNUNET_ALIGN;
10223 unsigned char *body;
10224 const struct GNUNET_MessageHeader *mh;
10225
10226 ppay = (struct TransportDVBoxPayloadP *) pt;
10227 body = &pt[sizeof *ppay];
10228 GNUNET_assert (hdr_len >=
10229 sizeof(*ppay) + sizeof(struct GNUNET_MessageHeader));
10230 if (GNUNET_OK != GNUNET_CRYPTO_aead_decrypt (hdr_len,
10231 hdr,
10232 0,
10233 NULL,
10234 key,
10235 &dvb->iv,
10236 &dvb->mac,
10237 pt))
10238 {
10240 "Error decrypting DV payload header\n");
10241 GNUNET_break_op (0);
10242 finish_cmc_handling (cmc);
10243 return;
10244 }
10245 mh = (const struct GNUNET_MessageHeader *) body;
10246 /* NOTE: this used to compare against `sizeof (body)', i.e. the size of
10247 a pointer, which meant only 8-byte payloads were ever accepted. */
10248 if (ntohs (mh->size) != hdr_len - sizeof(*ppay))
10249 {
10250 GNUNET_break_op (0);
10251 finish_cmc_handling (cmc);
10252 return;
10253 }
10254 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
10255 switch (ntohs (mh->type))
10256 {
10258 GNUNET_break_op (0);
10259 finish_cmc_handling (cmc);
10260 return;
10261
10263 GNUNET_break_op (0);
10264 finish_cmc_handling (cmc);
10265 return;
10266
10267 default:
10268 /* permitted, continue */
10269 break;
10270 }
10271 monotime = GNUNET_TIME_absolute_ntoh (ppay->monotonic_time);
10273 "Decrypted backtalk from %s\n",
10274 GNUNET_i2s (&ppay->sender));
10276 &ppay->sender);
10277 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
10278 {
10280 GST_stats,
10281 "# Backchannel messages dropped: monotonic time not increasing",
10282 1,
10283 GNUNET_NO);
10284 finish_cmc_handling (cmc);
10285 return;
10286 }
10287 if ((NULL == b) ||
10288 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
10289 {
10290 /* Check signature */
10291 const struct GNUNET_PeerIdentity *my_identity;
10292 struct EphemeralConfirmationPS ec;
10293
10296
10298 ec.target = *my_identity;
10299 ec.ephemeral_key = dvb->ephemeral_key;
10300 ec.purpose.size = htonl (sizeof(ec));
10302 if (
10303 GNUNET_OK !=
10306 &ec,
10307 &ppay->sender_sig,
10308 &ppay->sender.public_key))
10309 {
10310 /* Signature invalid, discard! */
10311 GNUNET_break_op (0);
10312 finish_cmc_handling (cmc);
10313 return;
10314 }
10315 }
10316 /* Update sender, we now know the real origin! */
10318 "DVBox received for me from %s via %s\n",
10319 GNUNET_i2s2 (&ppay->sender),
10320 GNUNET_i2s (&cmc->im.sender));
10321 cmc->im.sender = ppay->sender;
10322
10323 if (NULL != b)
10324 {
10325 /* update key cache and mono time */
10326 b->last_ephemeral = dvb->ephemeral_key;
10327 b->monotonic_time = monotime;
10329 b->timeout =
10331 cmc->mh = mh;
10333 return;
10334 }
10335 /* setup data structure to cache signature AND check
10336 monotonic time with PEERSTORE before forwarding backchannel payload */
10337 b = GNUNET_malloc (sizeof(struct Backtalker) + (hdr_len - sizeof(*ppay)));
10338 b->pid = ppay->sender;
10339 b->body_size = hdr_len - sizeof(*ppay);
10340 memcpy (&b[1], body, hdr_len - sizeof(*ppay));
10344 &b->pid,
10345 b,
10347 b->monotonic_time = monotime; /* NOTE: to be checked still! */
10348 b->cmc = cmc;
10349 b->timeout =
10352 b->get =
10354 "transport",
10355 &b->pid,
10358 b);
10359 } /* end actual decryption */
10360}
10361
10362
10370static void
10371handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
10372{
10373 struct CommunicatorMessageContext *cmc = cls;
10374 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
10375 uint16_t num_hops = ntohs (dvb->num_hops);
10376 const struct GNUNET_PeerIdentity *hops =
10377 (const struct GNUNET_PeerIdentity *) &dvb[1];
10378 const char *enc_payload = (const char *) &hops[num_hops];
10379 uint16_t enc_payload_size =
10380 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
10381 const struct GNUNET_PeerIdentity *my_identity;
10382
10385
10386 if (GNUNET_EXTRA_LOGGING > 0)
10387 {
10388 char *path;
10389
10391 for (unsigned int i = 0; i < num_hops; i++)
10392 {
10393 char *tmp;
10394
10395 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
10396 GNUNET_free (path);
10397 path = tmp;
10398 }
10400 "Received DVBox with remaining path %s\n",
10401 path);
10402 GNUNET_free (path);
10403 }
10404
10405 if (num_hops > 0)
10406 {
10407 /* We're trying from the end of the hops array, as we may be
10408 able to find a shortcut unknown to the origin that way */
10409 for (int i = num_hops - 1; i >= 0; i--)
10410 {
10411 struct Neighbour *n;
10412
10413 if (0 == GNUNET_memcmp (&hops[i], my_identity))
10414 {
10415 GNUNET_break_op (0);
10416 finish_cmc_handling (cmc);
10417 return;
10418 }
10419 n = lookup_neighbour (&hops[i]);
10420 if (NULL == n)
10421 continue;
10423 "Skipping %u/%u hops ahead while routing DV Box\n",
10424 i,
10425 num_hops);
10426
10427 forward_dv_box (n,
10428 (struct TransportDVBoxMessage *) dvb,
10429 /* we strip i+1 entries, and the receiver reconstructs
10430 the ciphertext offset from total_hops */
10431 ntohs (dvb->total_hops) + i + 1,
10432 num_hops - i - 1, /* number of hops left */
10433 &hops[i + 1], /* remaining hops */
10434 enc_payload,
10435 enc_payload_size);
10437 "# DV hops skipped routing boxes",
10438 i,
10439 GNUNET_NO);
10441 "# DV boxes routed (total)",
10442 1,
10443 GNUNET_NO);
10444 finish_cmc_handling (cmc);
10445 return;
10446 }
10447 /* Woopsie, next hop not in neighbours, drop! */
10449 "# DV Boxes dropped: next hop unknown",
10450 1,
10451 GNUNET_NO);
10452 finish_cmc_handling (cmc);
10453 return;
10454 }
10455 /* We are the target. Unbox and handle message. */
10457 "# DV boxes opened (ultimate target)",
10458 1,
10459 GNUNET_NO);
10460 cmc->total_hops = ntohs (dvb->total_hops);
10461
10462 {
10463 // DH key derivation with received DV, could be garbage.
10465 struct GNUNET_ShortHashCode km;
10466
10468 if ( (NULL == my_private_key) ||
10469 (GNUNET_OK !=
10471 &dvb->ephemeral_key,
10472 &km)) )
10473 {
10474 GNUNET_break_op (0);
10475 finish_cmc_handling (cmc);
10476 return;
10477 }
10478 decaps_dv_box_cont (cmc,
10479 dvb,
10480 &km);
10481 }
10482}
10483
10484
10492static int
10494 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10495{
10496 struct TransportClient *tc = cls;
10497
10498 if (CT_COMMUNICATOR != tc->type)
10499 {
10500 GNUNET_break (0);
10501 return GNUNET_SYSERR;
10502 }
10504 return GNUNET_OK;
10505}
10506
10507
10512{
10516 const char *address;
10517
10522};
10523
10524
10534static int
10536 const struct GNUNET_PeerIdentity *pid,
10537 void *value)
10538{
10539 struct CheckKnownAddressContext *ckac = cls;
10540 struct ValidationState *vs = value;
10541
10542 (void) pid;
10543 if (0 != strcmp (vs->address, ckac->address))
10544 return GNUNET_OK;
10545 ckac->vs = vs;
10546 return GNUNET_NO;
10547}
10548
10549
10555static void
10556validation_start_cb (void *cls);
10557
10558
10566static void
10568 struct GNUNET_TIME_Absolute new_time)
10569{
10571 struct ValidationState *next;
10572
10573 /* NOTE: "be lazy" must not apply while #validation_task is unset. Our
10574 only caller that can leave it unset is #validation_start_cb(), which
10575 NULLs it on entry and relies on us to arm it again -- and nothing else
10576 ever does. Returning early there stops address (re)validation and the
10577 #suggest_to_connect() retries that go with it for *every* peer, for
10578 good. */
10579 if ((new_time.abs_value_us == vs->next_challenge.abs_value_us) &&
10580 (NULL != validation_task) &&
10581 (NULL != vs->hn))
10582 return; /* be lazy */
10583 vs->next_challenge = new_time;
10584 if (NULL == vs->hn)
10585 vs->hn =
10587 else
10590 (NULL != validation_task))
10591 return;
10592 if (NULL != validation_task)
10594 /* Arm for the earliest entry in the heap, which need NOT be @a vs:
10595 #validation_start_cb() calls us with @e validation_task unset and with
10596 @a vs already pushed out to its new @e challenge_backoff, which doubles
10597 up to #MAX_VALIDATION_CHALLENGE_FREQ (one day) while an address stays
10598 unanswered. Arming for @a vs there parks the single global validation
10599 task for that long, no matter how many other addresses are due right
10600 now -- and every address of a peer we cannot reach (NAT) is such an
10601 address. Everything that needs a validation then stops with it:
10602 bringing a lost link back up, and confirming the link to a peer that
10603 contacted us. */
10605 if (NULL == next)
10606 return;
10607 /* randomize a bit */
10612 delta),
10614 NULL);
10615}
10616
10617
10636static void
10638{
10639 vs->challenge_backoff = FAST_VALIDATION_CHALLENGE_FREQ;
10640}
10641
10642
10653static enum GNUNET_GenericReturnValue
10655 const struct GNUNET_PeerIdentity *pid,
10656 void *value)
10657{
10658 struct ValidationState *vs = value;
10659 const struct GNUNET_TIME_Absolute now =
10661
10662 (void) cls;
10663 (void) pid;
10664 /* What #start_address_validation() does for an address it hears about
10665 again, but without needing the address string. */
10666 speed_up_challenge (vs);
10667 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
10668 vs->first_challenge_use = now;
10671 vs->challenge_backoff));
10672 return GNUNET_OK;
10673}
10674
10675
10682static void
10684 const char *address)
10685{
10686 struct GNUNET_TIME_Absolute now;
10687 struct ValidationState *vs;
10688 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
10689
10691 pid,
10693 &ckac);
10695 if (NULL != (vs = ckac.vs))
10696 {
10697 const struct VirtualLink *vl = lookup_virtual_link (pid);
10698
10699 /* Speed up retrying the validation if 'vs' is not currently valid, or if
10700 * we have no confirmed virtual link to @a pid. In the latter case the
10701 * address may still be well inside its validity window -- but the link is
10702 * down, and #handle_validation_response() is the only thing that can
10703 * rebuild it and tell CORE about the peer again. Without this we would
10704 * wait for @e revalidation_task, which does not fire until
10705 * #ADDRESS_VALIDATION_LIFETIME is nearly over. */
10706 if ((vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us) ||
10707 (NULL == vl) ||
10708 (GNUNET_NO == vl->confirmed))
10709 {
10710 /* reduce backoff as we got a fresh advertisement */
10711 speed_up_challenge (vs);
10712 /* A successful validation parks @e first_challenge_use just before
10713 @e validated_until, so that the *next* challenge is not used before
10714 the current validation is about to expire. #validation_start_cb()
10715 refuses to run while that time is still in the future, so pulling
10716 @e next_challenge in without this would only make it reschedule
10717 itself four hours out. The challenge has not been used yet, so
10718 moving the start of its window to now stays truthful -- it is what
10719 the fresh-@a vs path below does as well. */
10720 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
10721 vs->first_challenge_use = now;
10724 vs->challenge_backoff));
10725 }
10726 return;
10727 }
10728 vs = GNUNET_new (struct ValidationState);
10729 vs->pid = *pid;
10730 vs->valid_until =
10732 vs->first_challenge_use = now;
10733 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
10734 GNUNET_CRYPTO_random_block (&vs->challenge,
10735 sizeof(vs->challenge));
10736 vs->address = GNUNET_strdup (address);
10737 {
10738 /* The peer identity MUST be part of @e hc: two peers behind the same NAT
10739 advertise the very same address string (`PROTO-IP:0'), and with an
10740 address-only key the second one's #revalidation_map entry would be
10741 rejected as a duplicate of the first one's. */
10742 struct GNUNET_HashContext *hsh;
10743
10745 GNUNET_CRYPTO_hash_context_read (hsh, vs->address, strlen (vs->address));
10746 GNUNET_CRYPTO_hash_context_read (hsh, &vs->pid, sizeof(vs->pid));
10747 GNUNET_CRYPTO_hash_context_finish (hsh, &vs->hc);
10748 }
10750 "Starting address validation `%s' of peer %s using challenge %s\n",
10751 address,
10752 GNUNET_i2s (pid),
10753 GNUNET_sh2s (&vs->challenge.value));
10757 &vs->pid,
10758 vs,
10761}
10762
10763
10764static struct Queue *
10765find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
10766
10767
10768static void
10769suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
10770
10771
10772static void
10774 const struct GNUNET_PeerIdentity *pid,
10775 const char *uri)
10776{
10777 struct Queue *q;
10778 int pfx_len;
10779 const char *eou;
10780 char *address;
10781 (void) cls;
10782
10783 eou = strstr (uri,
10784 "://");
10785 if ((NULL == eou) || (eou == uri))
10786 {
10787 /* @a uri comes from a HELLO some remote peer published. */
10788 GNUNET_break_op (0);
10789 return;
10790 }
10791 pfx_len = eou - uri;
10792 eou += 3;
10794 "%.*s-%s",
10795 pfx_len,
10796 uri,
10797 eou);
10798
10800 "helo for client %s\n",
10801 address);
10802 q = find_queue (pid, address);
10803 if (NULL == q)
10804 {
10806 }
10807 else
10810}
10811
10812
10835static const struct GNUNET_MessageHeader *
10837{
10838 const struct GNUNET_MessageHeader *hello;
10839
10840 if ((NULL == record) ||
10841 (NULL == record->value) ||
10842 (record->value_size < sizeof(*hello)))
10843 {
10844 GNUNET_break_op (0);
10845 return NULL;
10846 }
10847 hello = record->value;
10848 if (ntohs (hello->size) > record->value_size)
10849 {
10850 GNUNET_break_op (0);
10851 return NULL;
10852 }
10853 return hello;
10854}
10855
10856
10864static void
10866 const struct GNUNET_PEERSTORE_Record *record,
10867 const char *emsg)
10868{
10869 struct IncomingRequest *ir = cls;
10870 struct GNUNET_HELLO_Parser *parser;
10871 const struct GNUNET_MessageHeader *hello;
10872 const struct GNUNET_PeerIdentity *my_identity;
10873
10874 if (NULL != emsg)
10875 {
10877 "Got failure from PEERSTORE: %s\n",
10878 emsg);
10880 return;
10881 }
10882 if (NULL == record)
10883 {
10884 GNUNET_break (0);
10886 return;
10887 }
10888 hello = hello_from_record (record);
10889 if (NULL == hello)
10890 {
10891 /* MUST still ask for the next record: a bad one is not a reason to
10892 stall this monitor forever. */
10894 return;
10895 }
10897 if (NULL == my_identity)
10898 {
10900 return;
10901 }
10902 if (0 == GNUNET_memcmp (&record->peer, my_identity))
10903 {
10905 return;
10906 }
10907 if (0 != GNUNET_memcmp (&record->peer, &ir->pid))
10908 {
10909 /* Not the peer this request is about. */
10911 return;
10912 }
10913 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10914 if (NULL != parser)
10915 {
10918 NULL);
10919 GNUNET_HELLO_parser_free (parser);
10920 }
10921 /* MUST ask for the next record, or this monitor stalls after one HELLO */
10923}
10924
10925
10926static void
10928{
10930 "Error in PEERSTORE monitoring\n");
10931}
10932
10933
10934static void
10936{
10938 "Done with initial PEERSTORE iteration during monitoring\n");
10939}
10940
10941
10950static void
10952{
10953 struct Neighbour *n;
10954 struct IncomingRequest *ir;
10955
10956 if (GNUNET_YES == in_shutdown)
10957 return;
10958 /* (1) Addresses we already track. These outlive the queues, which is the
10959 point: once a link is down the queue that carried it is usually gone,
10960 so there is no address string left for #start_address_validation(). */
10962 pid,
10964 NULL);
10965 /* (2) Queues we still have; may cover an address with no validation state
10966 yet. After (1), because it may insert into #validation_map. */
10967 n = lookup_neighbour (pid);
10968 if (NULL != n)
10969 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
10970 start_address_validation (pid, q->address);
10971 /* (3) Failing that, look for an address in PEERSTORE. */
10972 for (ir = ir_head; NULL != ir; ir = ir->next)
10973 {
10974 if (0 == GNUNET_memcmp (&ir->pid, pid))
10975 return; /* we are already trying */
10976 }
10977 ir = GNUNET_new (struct IncomingRequest);
10978 ir->pid = *pid;
10980 /* Monitor only @a pid: with NULL every request sees every HELLO in
10981 PEERSTORE, so each of the up to #MAX_INCOMING_REQUEST requests started
10982 a connection attempt and an address validation for peers it was not
10983 created for. */
10985 GNUNET_YES,
10986 "peerstore",
10987 &ir->pid,
10990 NULL,
10992 NULL,
10994 ir);
10995 ir_total++;
10996 /* Bound attempts we do in parallel here, might otherwise get excessive.
10997 Drop the OLDEST request: #ir_head is the one we just inserted, so
10998 freeing that would immediately undo the work above. */
11001}
11002
11003
11011static void
11014{
11015 struct VirtualLink *vl;
11016 struct Neighbour *n;
11017 struct GNUNET_PeerIdentity sender;
11018
11019 sender = cmc->im.sender;
11020 vl = lookup_virtual_link (&sender);
11021 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
11022 {
11023 // route_control_message_without_fc (&cmc->im.sender,
11025 &tvr.header,
11027 }
11028 else
11029 {
11030 /* Use route via neighbour */
11031 n = lookup_neighbour (&sender);
11032 if (NULL != n)
11033 route_via_neighbour (n, &tvr.header,
11036 }
11037
11038 finish_cmc_handling (cmc);
11039 /* An *unconfirmed* link is not a link -- it carries nothing, and CORE has
11040 never been told about the peer. Bailing out on one merely because it
11041 exists is what deadlocks a pair of peers into permanent one-way state:
11042 the challenger validated us, so it believes the connection is up and
11043 starts sending us FLOW_CONTROL; #handle_flow_control() answers an
11044 unknown sender by allocating exactly such an unconfirmed link; and from
11045 then on every challenge it retransmits lands here, gets a response --
11046 which keeps *its* side confirmed and its RTT healthy -- and returns
11047 without ever validating an address of its own. The unconfirmed link
11048 reaps itself after #UNCONFIRMED_LINK_TIMEOUT, but the next FLOW_CONTROL
11049 recreates it, and the peer keeps sending those precisely because it
11050 thinks it is connected. Nothing ever breaks the tie, so CORE on this
11051 side never hears about the peer and never answers its handshake.
11052 Only a confirmed link means there is nothing left to do. */
11053 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
11054 return;
11055
11056 /* For us, the link is still down, but we need bi-directional
11057 connections (for flow-control and for this to be useful for
11058 CORE), so we must try to bring the link up! */
11059 try_to_bring_link_up (&sender);
11060}
11061
11062
11071static void
11073 void *cls,
11074 const struct TransportValidationChallengeMessage *tvc)
11075{
11076 struct CommunicatorMessageContext *cmc = cls;
11077 struct TransportValidationResponseMessage tvr = { 0 };
11078 struct GNUNET_TIME_RelativeNBO validity_duration;
11079
11080 /* DV-routed messages are not allowed for validation challenges */
11081 if (cmc->total_hops > 0)
11082 {
11083 GNUNET_break_op (0);
11084 finish_cmc_handling (cmc);
11085 return;
11086 }
11087 validity_duration = cmc->im.expected_address_validity;
11089 "Received address validation challenge %s\n",
11090 GNUNET_sh2s (&tvc->challenge.value));
11091 /* If we have a virtual link, we use this mechanism to signal the
11092 size of the flow control window, and to allow the sender
11093 to ask for increases. If for us the virtual link is still down,
11094 we will always give a window size of zero. */
11095 tvr.header.type =
11097 tvr.header.size = htons (sizeof(tvr));
11098 tvr.reserved = htonl (0);
11099 tvr.challenge = tvc->challenge;
11100 tvr.origin_time = tvc->sender_time;
11101 tvr.validity_duration = validity_duration;
11102 {
11103 /* create signature */
11104 struct TransportValidationPS tvp = {
11106 .purpose.size = htonl (sizeof(tvp)),
11107 .validity_duration = validity_duration,
11108 .challenge = tvc->challenge
11109 };
11110 if (GNUNET_OK != sign_by_my_identity (&tvp.purpose, &tvr.signature))
11111 {
11112 /* Not answering costs us this address validation; leaving @a cmc
11113 behind would cost us the communicator. */
11114 finish_cmc_handling (cmc);
11115 return;
11116 }
11117 }
11118 send_t_validation_response (cmc, tvr);
11119}
11120
11121
11137
11138
11148static int
11150 const struct GNUNET_PeerIdentity *pid,
11151 void *value)
11152{
11153 struct CheckKnownChallengeContext *ckac = cls;
11154 struct ValidationState *vs = value;
11155
11156 (void) pid;
11157 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
11158 return GNUNET_OK;
11159 ckac->vs = vs;
11160 return GNUNET_NO;
11161}
11162
11163
11171static void
11172peerstore_store_validation_cb (void *cls, int success)
11173{
11174 struct ValidationState *vs = cls;
11175
11176 vs->sc = NULL;
11177 if (GNUNET_YES == success)
11178 return;
11180 "# Peerstore failed to store foreign address",
11181 1,
11182 GNUNET_NO);
11183}
11184
11185
11193static struct Queue *
11194find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
11195{
11196 struct Neighbour *n;
11197
11198 n = lookup_neighbour (pid);
11199 if (NULL == n)
11200 return NULL;
11201 for (struct Queue *pos = n->queue_head; NULL != pos;
11202 pos = pos->next_neighbour)
11203 {
11204 if (0 == strcmp (pos->address, address))
11205 return pos;
11206 }
11207 return NULL;
11208}
11209
11210
11226static struct Queue *
11227find_queue_by_ip (const struct GNUNET_PeerIdentity *pid, const char *address)
11228{
11229 struct Neighbour *n;
11230 struct Queue *ret = NULL;
11231 char *prefix;
11232 char *ip;
11233
11234 n = lookup_neighbour (pid);
11235 if (NULL == n)
11236 return NULL;
11239 if ((NULL == prefix) || (NULL == ip))
11240 {
11242 GNUNET_free (ip);
11243 return NULL;
11244 }
11245 for (struct Queue *pos = n->queue_head; NULL != pos;
11246 pos = pos->next_neighbour)
11247 {
11248 char *q_prefix = GNUNET_HELLO_address_to_prefix (pos->address);
11249 char *q_ip = get_address_without_port (pos->address);
11250
11251 /* Same communicator and same host -- only the port may differ. */
11252 if ((NULL != q_prefix) && (NULL != q_ip) &&
11253 (0 == strcmp (q_prefix, prefix)) &&
11254 (0 == strcmp (q_ip, ip)))
11255 ret = pos;
11256 GNUNET_free (q_prefix);
11257 GNUNET_free (q_ip);
11258 if (NULL != ret)
11259 break;
11260 }
11262 GNUNET_free (ip);
11263 return ret;
11264}
11265
11266
11267static void
11269
11270static void
11272{
11273 struct ValidationState *vs = cls;
11274 struct Queue *q;
11275 struct GNUNET_TIME_Absolute now;
11276
11277 vs->revalidation_task = NULL;
11278 q = find_queue (&vs->pid, vs->address);
11279 if (NULL == q)
11280 {
11281 now = GNUNET_TIME_absolute_get ();
11282 vs->awaiting_queue = GNUNET_YES;
11283 suggest_to_connect (&vs->pid, vs->address);
11285 }
11286 else
11288}
11289
11290
11291static enum GNUNET_GenericReturnValue
11293 void *cls,
11294 const struct GNUNET_HashCode *key,
11295 void *value)
11296{
11297 (void) cls;
11299 "Key in revalidate map %s \n",
11300 GNUNET_h2s (key));
11301 return GNUNET_YES;
11302}
11303
11304
11313static void
11315 void *cls,
11316 const struct TransportValidationResponseMessage *tvr)
11317{
11318 struct CommunicatorMessageContext *cmc = cls;
11319 struct ValidationState *vs;
11320 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
11321 .vs = NULL};
11322 struct GNUNET_TIME_Absolute origin_time;
11323 struct Queue *q;
11324 struct Neighbour *n;
11325 struct VirtualLink *vl;
11327 GST_cfg);
11328
11329 /* check this is one of our challenges */
11331 &cmc->im.sender,
11333 &ckac);
11334 if (NULL == (vs = ckac.vs))
11335 {
11336 /* This can happen simply if we 'forgot' the challenge by now,
11337 i.e. because we received the validation response twice */
11339 "# Validations dropped, challenge unknown",
11340 1,
11341 GNUNET_NO);
11343 "Validation response %s dropped, challenge unknown\n",
11344 GNUNET_sh2s (&tvr->challenge.value));
11345 finish_cmc_handling (cmc);
11346 return;
11347 }
11348
11349 /* sanity check on origin time */
11350 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
11351 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
11352 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
11353 {
11355 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
11356 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
11357 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
11358 GNUNET_break_op (0);
11359 finish_cmc_handling (cmc);
11360 return;
11361 }
11362
11363 {
11364 /* check signature */
11365 struct TransportValidationPS tvp = {
11367 .purpose.size = htonl (sizeof(tvp)),
11368 .validity_duration = tvr->validity_duration,
11369 .challenge = tvr->challenge
11370 };
11371
11372 if (
11373 GNUNET_OK !=
11375 &tvp,
11376 &tvr->signature,
11377 &cmc->im.sender.public_key))
11378 {
11379 GNUNET_break_op (0);
11380 finish_cmc_handling (cmc);
11381 return;
11382 }
11383 }
11384
11385 /* validity is capped by our willingness to keep track of the
11386 validation entry and the maximum the other peer allows */
11389 tvr->validity_duration),
11391 vs->validated_until =
11395 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
11396 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
11397 GNUNET_CRYPTO_random_block (&vs->challenge,
11398 sizeof(vs->challenge));
11399 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
11400 vs->validated_until,
11401 GNUNET_TIME_relative_multiply (vs->validation_rtt,
11403 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
11404 {
11406 "First challenge use is now %" PRIu64 " %s \n",
11407 vs->first_challenge_use.abs_value_us,
11408 GNUNET_sh2s (&vs->challenge.value));
11409 vs->first_challenge_use = now;
11410 }
11411 else
11413 "First challenge use is later %" PRIu64 " %s \n",
11414 vs->first_challenge_use.abs_value_us,
11415 GNUNET_sh2s (&vs->challenge.value));
11416 vs->last_challenge_use =
11417 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
11418 update_next_challenge_time (vs, vs->first_challenge_use);
11420 "Validation response %s from %s accepted, address valid until %s\n",
11421 GNUNET_sh2s (&tvr->challenge.value),
11422 GNUNET_i2s (&cmc->im.sender),
11424 /*memcpy (&hkey,
11425 &hc,
11426 sizeof (hkey));*/
11428 "Key %s for address %s map size %u contains %u\n",
11429 GNUNET_h2s (&vs->hc),
11430 vs->address,
11433 &vs->hc));
11434 /* NOTE: @e hc hashes the address only, so two `struct ValidationState's
11435 for different peers can collide here. That must not abort us. */
11436 if (GNUNET_YES !=
11439 &vs->hc,
11440 vs,
11443 "Address `%s' already tracked for revalidation\n",
11444 vs->address);
11447 NULL);
11448 vs->revalidation_task =
11453 "transport",
11454 &cmc->im.sender,
11456 vs->address,
11457 strlen (vs->address) + 1,
11458 vs->valid_until,
11461 vs);
11462 finish_cmc_handling (cmc);
11463
11464 /* Finally, we now possibly have a confirmed (!) working queue,
11465 update queue status (if queue still is around) */
11466 q = find_queue (&vs->pid, vs->address);
11467 if (NULL == q)
11468 {
11469 /* The challenge may have gone out on a queue whose address is not
11470 literally @e address: #check_validation_request_pending() matches on
11471 the IP alone, precisely so that a validation waiting for the NAT
11472 address `PROTO-IP:0' can be answered over the queue that the peer
11473 actually established from `PROTO-IP:port'. Insisting on an exact
11474 match here would silently discard that (successful!) validation and
11475 never bring the virtual link up. */
11476 q = find_queue_by_ip (&vs->pid, vs->address);
11477 }
11478 if (NULL == q)
11479 {
11481 "# Queues lost at time of successful validation",
11482 1,
11483 GNUNET_NO);
11484 return;
11485 }
11486 q->validated_until = vs->validated_until;
11487 q->pd.aged_rtt = vs->validation_rtt;
11488 n = q->neighbour;
11489 vl = lookup_virtual_link (&vs->pid);
11490 if (NULL == vl)
11491 {
11492 vl = GNUNET_new (struct VirtualLink);
11494 "Creating new virtual link %p to %s using direct neighbour!\n",
11495 vl,
11496 GNUNET_i2s (&vs->pid));
11497 vl->burst_addr = NULL;
11498 vl->confirmed = GNUNET_YES;
11499 vl->message_uuid_ctr =
11500 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
11501 vl->target = n->pid;
11505 /* What the peer will grant us in its very first FLOW_CONTROL anyway
11506 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
11507 Starting at zero instead means a link that is up, validated and
11508 working carries nothing at all until an FC round trip completes --
11509 and if the peer cannot answer, not ever. */
11513 links,
11514 &vl->target,
11515 vl,
11517 vl->n = n;
11518 n->vl = vl;
11519 q->idle = GNUNET_YES;
11520 vl->visibility_task =
11521 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
11523 /* We lacked a confirmed connection to the target
11524 before, so tell CORE about it (finally!) */
11527 }
11528 else
11529 {
11530 /* Link was already up, remember n is also now available and we are done */
11531 if (NULL == vl->n)
11532 {
11533 vl->n = n;
11534 n->vl = vl;
11535 if (GNUNET_YES == vl->confirmed)
11537 "Virtual link to %s could now also use direct neighbour!\n",
11538 GNUNET_i2s (&vs->pid));
11539 }
11540 else
11541 {
11542 GNUNET_assert (n == vl->n);
11543 }
11544 if (GNUNET_NO == vl->confirmed)
11545 {
11546 vl->confirmed = GNUNET_YES;
11547 q->idle = GNUNET_YES;
11548 vl->visibility_task =
11549 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
11551 /* We lacked a confirmed connection to the target
11552 before, so tell CORE about it (finally!) */
11555 }
11556 }
11557}
11558
11559
11565static void
11567 const struct GNUNET_TRANSPORT_IncomingMessage *im)
11568{
11569 struct TransportClient *tc = cls;
11570 struct Neighbour *n;
11571 struct CommunicatorMessageContext *cmc =
11573
11574 cmc->tc = tc;
11575 cmc->im = *im;
11577 "Received message with size %u and flow control id %" PRIu64
11578 " via communicator from peer %s\n",
11579 ntohs (im->header.size),
11580 im->fc_id,
11581 GNUNET_i2s (&im->sender));
11582 cmc->im.neighbour_sender = cmc->im.sender;
11583 /* A communicator got this straight from @a im->sender, so the queues to
11584 that neighbour demonstrably still work. This is what #check_link_down()
11585 uses to bound how long a communicator that stopped working (without
11586 telling us) can keep a virtual link -- and CORE -- fooled. */
11587 if (NULL != (n = lookup_neighbour (&im->sender)))
11589 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
11591}
11592
11593
11602static int
11604{
11605 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
11606 uint16_t msize = ntohs (fc->header.size);
11607 const char *tgnas;
11608 size_t avail;
11609 size_t off;
11610
11611 (void) cls;
11613 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
11614 ntohs (fc->header.size),
11615 ntohl (fc->size_of_addresses),
11616 ntohl (fc->number_of_addresses),
11617 sizeof(struct TransportFlowControlMessage),
11618 sizeof (struct TransportGlobalNattedAddress));
11619 if (0 == number_of_addresses)
11620 return GNUNET_OK;
11621 if (msize < sizeof(struct TransportFlowControlMessage))
11622 {
11623 GNUNET_break_op (0);
11624 return GNUNET_SYSERR;
11625 }
11626 avail = msize - sizeof(struct TransportFlowControlMessage);
11627 tgnas = (const char *) &fc[1];
11628 off = 0;
11629 /* Validate EVERY entry: checking only the aggregate size lets a single
11630 entry claim a bogus address_length and send #handle_flow_control()
11631 out of bounds. */
11632 for (unsigned int i = 0; i < number_of_addresses; i++)
11633 {
11634 const struct TransportGlobalNattedAddress *tgna;
11635 size_t alen;
11636
11637 if (avail - off < sizeof(struct TransportGlobalNattedAddress))
11638 {
11639 GNUNET_break_op (0);
11640 return GNUNET_SYSERR;
11641 }
11642 tgna = (const struct TransportGlobalNattedAddress *) &tgnas[off];
11643 off += sizeof(struct TransportGlobalNattedAddress);
11644 alen = ntohl (tgna->address_length);
11645 if (avail - off < alen)
11646 {
11647 GNUNET_break_op (0);
11648 return GNUNET_SYSERR;
11649 }
11650 off += alen;
11651 }
11652 return GNUNET_OK;
11653}
11654
11655
11656static struct GNUNET_TIME_Relative
11658{
11660 unsigned int n_hops = 0;
11661
11663 "calculate_rtt\n");
11664 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
11665 pos = pos->next_dv)
11666 {
11668 "calculate_rtt %lu\n",
11669 (unsigned long) pos->pd.aged_rtt.rel_value_us);
11670 n_hops++;
11672 aged_rtt, pos
11673 ->distance
11674 + 2), ret);
11675 }
11676
11677 if (0 == n_hops)
11679 return ret;
11680}
11681
11682
11683static void
11685 const struct GNUNET_PeerIdentity *pid,
11686 const char *uri)
11687{
11688 struct VirtualLink *vl = cls;
11689 const char *slash;
11690 char *address_uri;
11691 char *prefix;
11692 char *uri_without_port;
11693
11694 slash = strrchr (uri, '/');
11695 if ((NULL == slash) || (slash - uri < 2))
11696 {
11697 GNUNET_break_op (0); /* @a uri comes from a remote HELLO */
11698 return;
11699 }
11700 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
11701 slash++;
11702 GNUNET_asprintf (&address_uri,
11703 "%s-%s",
11704 prefix,
11705 slash);
11706
11707 uri_without_port = get_address_without_port (address_uri);
11709 "iterate_address_start_burst %s %s %s %s\n",
11710 (NULL == uri_without_port) ? "<unparsable>" : uri_without_port,
11711 uri,
11712 address_uri,
11713 slash);
11714 GNUNET_free (vl->burst_addr);
11715 if ((NULL != uri_without_port) &&
11716 (0 == strcmp (uri_without_port, slash)))
11717 vl->burst_addr = GNUNET_strdup (uri_without_port);
11718
11720 GNUNET_free (address_uri);
11721 GNUNET_free (uri_without_port);
11722}
11723
11724
11725static void
11727 const struct GNUNET_PEERSTORE_Record *record,
11728 const char *emsg)
11729{
11730 struct GNUNET_StartBurstCls *sb_cls = cls;
11731 struct VirtualLink *vl = sb_cls->vl;
11732 const struct GNUNET_MessageHeader *hello;
11733 struct GNUNET_HELLO_Parser *parser;
11734
11735 if (NULL != emsg)
11736 {
11738 "Got failure from PEERSTORE: %s\n",
11739 emsg);
11740 /* @a emsg comes with a NULL record, which means the iteration is over
11741 and PEERSTORE is releasing the context itself -- stopping it here as
11742 well would free it twice. Just drop our handle. */
11743 vl->ic = NULL;
11744 free_burst_cls (sb_cls);
11745 return;
11746 }
11747 if (NULL == record)
11748 {
11750 "Hello iteration end for %s\n",
11751 GNUNET_i2s (&vl->target));
11752 /* PEERSTORE destroys the context itself once it signals the end. */
11753 vl->ic = NULL;
11754 free_burst_cls (sb_cls);
11755 return;
11756 }
11757
11759 "check_for_burst_address\n");
11760 /* @a hello was published by a remote peer, it may well be malformed. */
11761 hello = hello_from_record (record);
11762 if (NULL != hello)
11763 {
11764 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
11765 if (NULL != parser)
11766 {
11769 vl);
11770 GNUNET_HELLO_parser_free (parser);
11771 }
11772 }
11773
11774 /* MUST clear @e ic: #GNUNET_PEERSTORE_iteration_stop() frees it, and
11775 #free_virtual_link() would otherwise stop it a second time. */
11776 if (NULL != vl->ic)
11777 {
11779 vl->ic = NULL;
11780 }
11781 free_burst_cls (sb_cls);
11782}
11783
11784
11785static void
11786burst_timeout (void *cls)
11787{
11789}
11790
11791
11792static void
11793start_burst (void *cls)
11794{
11795 struct GNUNET_StartBurstCls *sb_cls = cls;
11796 struct VirtualLink *vl = sb_cls->vl;
11797 struct GNUNET_TRANSPORT_StartBurst *sb;
11798 struct GNUNET_MQ_Envelope *env;
11799 char *uri_without_port = vl->burst_addr;
11800
11801 burst_task = NULL;
11802 burst_task_cls = NULL;
11803 if (NULL == uri_without_port)
11804 {
11805 /* Lost the address in the meantime, nothing to burst to. */
11806 free_burst_cls (sb_cls);
11807 return;
11808 }
11809 /*char buf[strlen (uri_without_port) + 1];
11810
11811 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
11812 buf[strlen (uri_without_port)] = '\0';*/
11813 env =
11815 strlen (uri_without_port) + 1,
11817 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
11818 sb->pid = vl->target;
11819 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
11820 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11821 {
11822 if (CT_COMMUNICATOR != tc->type)
11823 continue; /* MUST come first: the log below reads the union! */
11825 "iterate_address_start_burst client tc prefix %s\n",
11826 tc->details.communicator.address_prefix);
11827 if (GNUNET_YES == tc->details.communicator.can_burst)
11828 {
11830 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
11831 uri_without_port,
11832 strlen (uri_without_port),
11833 ntohs (sb->header.size),
11834 (unsigned long) sb_cls->rtt.rel_value_us);
11835 GNUNET_MQ_send (tc->mq, env);
11836 env = NULL; /* MQ took ownership */
11840 60),
11842 NULL);
11843 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
11844 break;
11845 }
11846 }
11847 if (NULL != env)
11849 free_burst_cls (sb_cls);
11850}
11851
11852
11859static void
11861{
11862 struct VirtualLink *vl = sb_cls->vl;
11863
11864 if (burst_task_cls == sb_cls)
11865 {
11866 if (NULL != burst_task)
11867 {
11869 burst_task = NULL;
11870 }
11871 burst_task_cls = NULL;
11872 }
11873 if ((NULL != vl) && (vl->sb_cls == sb_cls))
11874 vl->sb_cls = NULL;
11876}
11877
11878
11879static void
11880queue_burst (void *cls)
11881{
11882 struct GNUNET_StartBurstCls *sb_cls = cls;
11883 struct VirtualLink *vl = sb_cls->vl;
11884
11885 if (GNUNET_YES != use_burst)
11886 {
11887 /* MUST release: nobody else owns @a sb_cls, and #handle_flow_control()
11888 allocates one for every FLOW_CONTROL message we receive. */
11890 return;
11891 }
11893 "burst_task %p ready %s burst addr %s (%p)\n",
11894 burst_task,
11895 sb_cls->sync_ready ? "yes" : "no",
11896 vl->burst_addr,
11897 vl->burst_addr);
11898 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
11899 {
11900 /* Cancel the pending burst. Both closures (the scheduled task's and
11901 ours) are ours to release. */
11903
11905 burst_task = NULL;
11906 burst_task_cls = NULL;
11907 if ((NULL != pending) && (pending != sb_cls))
11909 free_burst_cls (sb_cls);
11910 return;
11911 }
11912 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
11913 )
11914 {
11916 &start_burst,
11917 sb_cls);
11918 burst_task_cls = sb_cls;
11919 }
11920 else if (NULL == vl->burst_addr)
11921 {
11922 if (NULL != vl->ic)
11923 {
11924 /* An address lookup is already running for this link; starting a
11925 second one would leak the first. */
11926 free_burst_cls (sb_cls);
11927 return;
11928 }
11930 "peerstore",
11931 &vl->target,
11934 sb_cls);
11935 }
11936 else
11937 {
11938 /* A burst is already running or already scheduled; we have no use for
11939 this closure. */
11940 free_burst_cls (sb_cls);
11941 }
11942}
11943
11944
11951static void
11953{
11954 struct VirtualLink *vl = cls;
11955
11956 vl->unconfirmed_timeout_task = NULL;
11957 if ((GNUNET_YES == vl->confirmed) ||
11958 (NULL != vl->n) ||
11959 (NULL != vl->dv))
11960 return; /* got promoted in the meantime, its owner will clean up */
11962 "Discarding unconfirmed virtual link to %s\n",
11963 GNUNET_i2s (&vl->target));
11965 "# Unconfirmed virtual links timed out",
11966 1,
11967 GNUNET_NO);
11968 free_virtual_link (vl);
11969}
11970
11971
11980static void
11982{
11983 struct CommunicatorMessageContext *cmc = cls;
11984 struct VirtualLink *vl;
11986 uint32_t seq;
11987 struct GNUNET_TIME_Absolute st;
11988 uint64_t os;
11989 uint64_t wnd;
11990 uint32_t random;
11991
11993 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
11994 vl = lookup_virtual_link (&cmc->im.sender);
11995 if (NULL == vl)
11996 {
11997 vl = GNUNET_new (struct VirtualLink);
11999 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
12000 vl,
12001 GNUNET_i2s (&cmc->im.sender));
12002 vl->burst_addr = NULL;
12003 vl->confirmed = GNUNET_NO;
12004 vl->message_uuid_ctr =
12005 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
12006 vl->target = cmc->im.sender;
12010 /* What the peer will grant us in its very first FLOW_CONTROL anyway
12011 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
12012 Starting at zero instead means a link that is up, validated and
12013 working carries nothing at all until an FC round trip completes --
12014 and if the peer cannot answer, not ever. */
12018 links,
12019 &vl->target,
12020 vl,
12022 /* Nothing else owns this link yet, so it must reap itself if it never
12023 becomes confirmed -- otherwise any peer can make us allocate
12024 VirtualLinks without bound. */
12028 vl);
12029 }
12030 if (GNUNET_YES != vl->confirmed)
12031 {
12032 /* The peer flow-controls us, so it has a confirmed link to us -- but an
12033 unconfirmed link carries nothing and is never reported to CORE. Only
12034 #handle_validation_response() breaks that tie, and nothing here used
12035 to ask for one, so the pair could sit one-way until the peer's own
12036 four hour revalidation came round. */
12038 }
12039 if (NULL != vl->n)
12040 {
12041 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
12042 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
12043 }
12044
12046 "remaining %lu timeout for neighbour %p\n",
12047 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
12048 rel_value_us,
12049 vl->n);
12050 if (NULL == vl->n ||
12051 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
12052 {
12053 struct GNUNET_TIME_Relative rtt;
12054 struct GNUNET_BurstSync burst_sync;
12055 struct GNUNET_StartBurstCls *bcls;
12056
12057 if (NULL != vl->sb_cls)
12058 {
12059 /* A burst attempt for this link is already in flight. Allocating a
12060 second closure would orphan the first one: @e sb_cls is how
12061 #free_virtual_link() finds (and cancels) the pending #burst_task,
12062 and a peer that just keeps sending us FLOW_CONTROL messages would
12063 otherwise make us leak one closure per message. */
12065 "Burst attempt to %s already pending\n",
12066 GNUNET_i2s (&vl->target));
12067 }
12068 else
12069 {
12070 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
12071 bcls->vl = vl;
12072 vl->sb_cls = bcls;
12073 if (NULL != vl->dv)
12074 rtt = calculate_rtt (vl->dv);
12075 else
12077 burst_sync.rtt_average = fc->rtt;
12078 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
12079 /* @e sync_ready of `struct GNUNET_BurstSync' is a host-order enum. */
12080 burst_sync.sync_ready =
12081 (enum GNUNET_GenericReturnValue) ntohl (fc->sync_ready);
12082
12083 /* NOTE: #GNUNET_is_burst_ready() does NOT invoke the task unless both
12084 RTT estimates are known and close; #queue_burst() is thus not
12085 guaranteed to run, which is why @e sb_cls stays owned by @a vl. */
12087 &burst_sync,
12088 &queue_burst,
12089 bcls);
12090 }
12091 }
12092 if (0 != ntohl (fc->number_of_addresses))
12093 {
12094 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
12095 const char *tgnas;
12096 unsigned int off = 0;
12097
12098 tgnas = (const char *) &fc[1];
12099
12100 for (unsigned int i = 0; i < number_of_addresses; i++)
12101 {
12102 struct TransportGlobalNattedAddress *tgna;
12103 char *addr;
12104 uint32_t address_length;
12105
12106 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
12107 addr = (char *) &tgna[1];
12108 address_length = ntohl (tgna->address_length);
12109 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
12110
12111 /* NOTE: the address is NOT 0-terminated (it comes straight off the
12112 wire), it must be printed with an explicit precision. */
12114 "received address %.*s length %u\n",
12115 (int) address_length,
12116 addr,
12118
12119 if (NULL != nh)
12120 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
12121 }
12122 }
12124 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
12125 {
12127 "FC dropped: Message out of order\n");
12128 /* out of order, drop */
12130 "# FC dropped: message out of order",
12131 1,
12132 GNUNET_NO);
12133 finish_cmc_handling (cmc);
12134 return;
12135 }
12136 seq = ntohl (fc->seq);
12137 if (seq < vl->last_fc_seq)
12138 {
12139 /* Wrap-around/reset of other peer; start all counters from zero */
12141 }
12142 vl->last_fc_seq = seq;
12143 vl->last_fc_timestamp = st;
12144 /* The peer is answering, so the backoff in #consider_sending_fc() starts
12145 over: @e fc_retransmit_count counts *unanswered* rounds. */
12146 vl->fc_retransmit_count = 0;
12148 os = GNUNET_ntohll (fc->outbound_sent);
12150 (int64_t) (os - vl->incoming_fc_window_size_used);
12152 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
12153 GNUNET_i2s (&vl->target),
12154 (unsigned int) seq,
12155 (unsigned long long) vl->outbound_fc_window_size,
12156 (long long) vl->incoming_fc_window_size_loss);
12158 random = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
12159 /* NOTE: this must NOT be restricted to a confirmed link. @e
12160 outbound_fc_window_size starts at zero and is raised *only* here, from
12161 the peer's FC. So a peer whose link to us is confirmed while ours to it
12162 is not cannot send us a single byte until we answer -- and it is exactly
12163 that peer that keeps asking. Staying quiet deadlocks the pair: it shows
12164 an established virtual link with messages pending forever, we show none,
12165 and CORE never completes its handshake in either direction. */
12166 if ((wnd < vl->incoming_fc_window_size
12170 (0 == random % FC_NO_CHANGE_REPLY_PROBABILITY))
12171 {
12173 "Consider re-sending our FC message, as clearly the other peer's idea of the window is not up-to-date (%llu vs %llu) or %llu last received differs, or random reply %u\n",
12174 (unsigned long long) wnd,
12175 (unsigned long long) vl->incoming_fc_window_size,
12176 (unsigned long long) vl->last_outbound_window_size_received,
12179 }
12180 if ((wnd == vl->incoming_fc_window_size
12184 {
12186 "Slowing FC transmission to %s to keepalive rate: peer is current at window %llu\n",
12187 GNUNET_i2s (&vl->target),
12188 (unsigned long long) wnd);
12189 /* NOTE: this used to also require @e fc_retransmit_task to be non-NULL
12190 and did nothing at all otherwise -- so a link whose chain had ended
12191 (see #consider_sending_fc()) could never pick the keepalive back up,
12192 even though the peer was demonstrably still talking to us. */
12193 if (NULL != vl->fc_retransmit_task)
12195 vl->fc_retransmit_count = 0;
12196 /* Drop to the keepalive rate rather than stopping outright. There is
12197 nothing left to retransmit -- but if we go completely quiet, and the
12198 peer does the same for the same reason, then neither end sees any
12199 traffic and #check_link_down() tears down a perfectly healthy link
12200 after #NEIGHBOUR_LIVENESS_TIMEOUT. One tiny FC message every
12201 #FC_KEEPALIVE_INTERVAL is what keeps @e last_inbound moving on the
12202 other side (and, via their reply, on ours). */
12203 vl->fc_retransmit_task =
12206 vl);
12207 }
12209 /* FC window likely increased, check transmission possibilities! */
12211 finish_cmc_handling (cmc);
12212}
12213
12214
12222static void
12224{
12226 { GNUNET_MQ_hd_var_size (fragment_box,
12229 cmc),
12230 GNUNET_MQ_hd_var_size (reliability_box,
12233 cmc),
12234 GNUNET_MQ_hd_var_size (reliability_ack,
12237 cmc),
12238 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
12241 cmc),
12242 GNUNET_MQ_hd_var_size (dv_learn,
12245 cmc),
12246 GNUNET_MQ_hd_var_size (dv_box,
12248 struct TransportDVBoxMessage,
12249 cmc),
12250 GNUNET_MQ_hd_var_size (flow_control,
12253 cmc),
12255 validation_challenge,
12258 cmc),
12260 validation_response,
12263 cmc),
12265 int ret;
12266 const struct GNUNET_MessageHeader *msg = cmc->mh;
12267
12269 "Handling message of type %u with %u bytes\n",
12270 (unsigned int) ntohs (msg->type),
12271 (unsigned int) ntohs (msg->size));
12272 /* @a handlers only covers the encapsulations *we* add; anything else is a
12273 payload for CORE and leaves through #handle_raw_message() below. So
12274 #GNUNET_NO is the common case here -- one per delivered CORE message --
12275 and not something to log about, which is why this is the "try" variant. */
12277 if (GNUNET_SYSERR == ret)
12278 {
12279 /* @a msg is the message a *remote peer* sent us: #handle_incoming_msg()
12280 points @e mh into the payload of the
12281 #GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG the communicator
12282 delivered, and every other caller unwraps it from remote traffic as
12283 well. So failing a check here is that peer's protocol violation, and
12284 it says nothing at all about the communicator that carried it.
12285
12286 Dropping the client therefore punishes the wrong party, and it
12287 punishes it hard: #GNUNET_SERVICE_client_drop() disconnects the
12288 communicator *process*, which takes down every queue it owns and thus
12289 every neighbour reachable through it. One malformed DV box on a
12290 shared UDP communicator disconnects every peer we have on it, CORE
12291 tears the sessions down, and the key exchanges that would rebuild
12292 them have to wait for the communicator to come back and revalidate.
12293 Since the offending bytes arrive from the network, any peer can do
12294 this to us at will, repeatedly.
12295
12296 Drop the message and keep the communicator: resume it exactly as the
12297 success path does, so it still gets its flow-control ACK and its
12298 GNUNET_SERVICE_client_continue(). */
12299 GNUNET_break_op (0);
12301 "# malformed messages discarded",
12302 1,
12303 GNUNET_NO);
12305 return;
12306 }
12307 if (GNUNET_NO == ret)
12308 {
12309 /* unencapsulated 'raw' message */
12310 handle_raw_message (cmc, msg);
12311 }
12312}
12313
12314
12321static int
12323 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12324{
12325 struct TransportClient *tc = cls;
12326
12327 if (CT_COMMUNICATOR != tc->type)
12328 {
12329 GNUNET_break (0);
12330 return GNUNET_SYSERR;
12331 }
12333 return GNUNET_OK;
12334}
12335
12336
12342static void
12344{
12345 if (pm->msg_uuid_set)
12346 return;
12347 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
12349}
12350
12351
12360static struct PendingAcknowledgement *
12362 struct DistanceVectorHop *dvh,
12363 struct PendingMessage *pm)
12364{
12365 struct PendingAcknowledgement *pa;
12366
12367 pa = GNUNET_new (struct PendingAcknowledgement);
12368 pa->queue = queue;
12369 pa->dvh = dvh;
12370 pa->pm = pm;
12371 do
12372 {
12374 sizeof(pa->ack_uuid));
12375 }
12378 &pa->ack_uuid.value,
12379 pa,
12381 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
12383 if (NULL != dvh)
12386 pa->message_size = pm->bytes_msg;
12388 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
12390 pm->logging_uuid);
12391 return pa;
12392}
12393
12394
12406static struct PendingMessage *
12408 struct DistanceVectorHop *dvh,
12409 struct PendingMessage *pm)
12410{
12411 struct PendingAcknowledgement *pa;
12412 struct PendingMessage *ff;
12413 uint16_t mtu;
12414 uint16_t msize;
12415
12416 mtu = (UINT16_MAX == queue->mtu)
12417 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
12418 : queue->mtu;
12420 "Fragmenting message <%" PRIu64
12421 "> with size %u to %s for MTU %u\n",
12422 pm->logging_uuid,
12423 pm->bytes_msg,
12424 GNUNET_i2s (&pm->vl->target),
12425 (unsigned int) mtu);
12428 "Fragmenting message %" PRIu64 " <%" PRIu64
12429 "> with size %u to %s for MTU %u\n",
12430 pm->msg_uuid.uuid,
12431 pm->logging_uuid,
12432 pm->bytes_msg,
12433 GNUNET_i2s (&pm->vl->target),
12434 (unsigned int) mtu);
12435
12436 /* This invariant is established in #handle_add_queue_message() */
12437 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
12438
12439 /* select fragment for transmission, descending the tree if it has
12440 been expanded until we are at a leaf or at a fragment that is small
12441 enough
12442 */
12443 ff = pm;
12444 msize = ff->bytes_msg;
12445
12446 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
12447 (ff->frag_off == msize) && (NULL != ff->head_frag))
12448 {
12449 ff = ff->head_frag; /* descent into fragmented fragments */
12450 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
12451 }
12452
12453 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
12454 {
12455 /* Did not yet calculate all fragments, calculate next fragment */
12456 struct PendingMessage *frag;
12457 struct TransportFragmentBoxMessage tfb;
12458 const char *orig;
12459 char *msg;
12460 uint16_t fragmax;
12461 uint16_t fragsize;
12462 uint16_t msize_ff;
12463 uint16_t xoff = 0;
12464 pm->frag_count++;
12465
12466 orig = (const char *) &ff[1];
12467 msize_ff = ff->bytes_msg;
12468 if (pm != ff)
12469 {
12470 const struct TransportFragmentBoxMessage *tfbo;
12471
12472 tfbo = (const struct TransportFragmentBoxMessage *) orig;
12473 orig += sizeof(struct TransportFragmentBoxMessage);
12474 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
12475 xoff = ntohs (tfbo->frag_off);
12476 }
12477 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
12478 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
12479 frag =
12480 GNUNET_malloc (sizeof(struct PendingMessage)
12481 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
12483 "3 created pm %p from pm %p storing vl %p from pm %p\n",
12484 frag,
12485 ff,
12486 pm->vl,
12487 pm);
12489 frag->vl = pm->vl;
12490 frag->frag_parent = ff;
12491 frag->timeout = pm->timeout;
12492 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
12493 frag->pmt = PMT_FRAGMENT_BOX;
12494 msg = (char *) &frag[1];
12496 tfb.header.size =
12497 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
12498 pa = prepare_pending_acknowledgement (queue, dvh, frag);
12499 tfb.ack_uuid = pa->ack_uuid;
12500 tfb.msg_uuid = pm->msg_uuid;
12501 tfb.frag_off = htons (ff->frag_off + xoff);
12502 tfb.msg_size = htons (pm->bytes_msg);
12503 memcpy (msg, &tfb, sizeof(tfb));
12504 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
12506 ff->tail_frag, frag);
12507 ff->frag_off += fragsize;
12508 ff = frag;
12509 }
12510
12511 if (pm == ff)
12512 {
12513 /* Neither the descent nor the branch above moved us off @a pm, so there
12514 is no fragment to send: @e head_frag is empty *and* @e frag_off says
12515 everything was already cut. completed_pending_message() leaves
12516 exactly that state behind when the last outstanding fragment is
12517 acknowledged but its condition for finishing the root does not hold
12518 (@e frag_off having been advanced past the boxed payload size, or the
12519 root being a reliability box). The rotate below then dereferences
12520 @e frag_parent, which is NULL for the message on @e pending_msg_head.
12521
12522 Report "nothing to fragment" instead; the caller reschedules. */
12523 GNUNET_break (0);
12524 return NULL;
12525 }
12526 /* Move head to the tail and return it */
12530 ff);
12534 ff);
12535
12536 return ff;
12537}
12538
12539
12552static struct PendingMessage *
12554 struct DistanceVectorHop *dvh,
12555 struct PendingMessage *pm)
12556{
12558 struct PendingAcknowledgement *pa;
12559 struct PendingMessage *bpm;
12560 char *msg;
12561
12562 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
12563 return pm; /* already fragmented or reliability boxed, or control message:
12564 do nothing */
12565 if (NULL != pm->bpm)
12566 return pm->bpm; /* already computed earlier: do nothing */
12567 // TODO I guess we do not need this assertion. We might have a DLL with
12568 // fragments, because the MTU changed, and we do not need to fragment anymore.
12569 // But we should keep the fragments until message was completed, because
12570 // the MTU might change again.
12571 // GNUNET_assert (NULL == pm->head_frag);
12572 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
12573 {
12574 /* failed hard */
12575 GNUNET_break (0);
12577 return NULL;
12578 }
12579
12580 pa = prepare_pending_acknowledgement (queue, dvh, pm);
12581
12582 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
12583 + pm->bytes_msg);
12585 "4 created pm %p storing vl %p from pm %p\n",
12586 bpm,
12587 pm->vl,
12588 pm);
12590 bpm->vl = pm->vl;
12591 bpm->frag_parent = pm;
12592 // Why was this needed?
12593 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
12594 bpm->timeout = pm->timeout;
12596 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
12599 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
12600 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
12601
12602 rbox.ack_uuid = pa->ack_uuid;
12603 msg = (char *) &bpm[1];
12604 memcpy (msg, &rbox, sizeof(rbox));
12605 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
12606 pm->bpm = bpm;
12608 "Preparing reliability box for message <%" PRIu64
12609 "> of size %d (%d) to %s on queue %s\n",
12610 pm->logging_uuid,
12611 pm->bytes_msg,
12612 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
12613 GNUNET_i2s (&pm->vl->target),
12614 queue->address);
12615 return bpm;
12616}
12617
12618
12619static void
12622{
12623 struct VirtualLink *vl = pm->vl;
12624 struct PendingMessage *pos;
12625
12626 /* Only a message without a parent is on vl->pending_msg_head; anything
12627 else is not ours to reorder and MDLL_remove() would abort on it. */
12628 if ((NULL == vl) ||
12629 (NULL != pm->frag_parent) ||
12630 ((NULL == pm->prev_vl) && (vl->pending_msg_head != pm)))
12631 {
12632 GNUNET_break (0);
12633 return;
12634 }
12635 /* re-insert sort in neighbour list */
12639 pm);
12640 pos = vl->pending_msg_tail;
12641 while ((NULL != pos) &&
12643 pos = pos->prev_vl;
12647 pos,
12648 pm);
12649}
12650
12651
12652static unsigned int
12654{
12655 struct PendingMessage *pos;
12656 /* MUST be initialised: for a leaf the loop below never runs */
12658
12659 pos = pm->head_frag;
12660 while (NULL != pos)
12661 {
12663 GNUNET_NO == check_next_attempt_tree (pos, root))
12665 else
12666 {
12668 break;
12669 }
12670 pos = pos->next_frag;
12671 }
12672
12673 return frags_in_flight;
12674}
12675
12676
12677static void
12679{
12680 struct PendingMessage *pos;
12681
12682 pos = pm->head_frag;
12683 while (NULL != pos)
12684 {
12687 pos = pos->next_frag;
12688 }
12689}
12690
12691
12700static void
12703{
12704 if (NULL == pm->frag_parent)
12705 {
12708 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
12709 pm->logging_uuid,
12712 }
12713 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
12714 {
12715 struct PendingMessage *root = pm->frag_parent;
12716
12717 while (NULL != root->frag_parent)
12718 root = root->frag_parent;
12720 "Next attempt for root message <%" PRIu64 "> set to %s\n",
12721 root->logging_uuid,
12723 root->next_attempt = next_attempt;
12725 }
12726 else
12727 {
12728 struct PendingMessage *root = pm->frag_parent;
12729
12730 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
12731 root = root->frag_parent;
12732
12734 "frag_count next attempt %u\n",
12735 root->frag_count);
12736
12737 if (GNUNET_NO == root->frags_in_flight)
12738 {
12739 root->next_attempt = next_attempt;
12741 root->frags_in_flight_round++;
12743 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
12744 ">)set to %" PRIu64 "\n",
12745 pm->logging_uuid,
12746 root->logging_uuid,
12748 }
12749
12750 pm->next_attempt = root->next_attempt;
12753
12754 if (root->bytes_msg == root->frag_off)
12755 root->frags_in_flight = check_next_attempt_tree (root, root);
12756 else
12758
12759 if (GNUNET_NO == root->frags_in_flight)
12760 {
12761 /* `root' deliberately stops at a DV box, which is itself a child of
12762 the message on vl->pending_msg_head. Walk the rest of the way for
12763 the reorder: only the parentless message is on that list. */
12764 struct PendingMessage *vl_root = root;
12765
12766 while (NULL != vl_root->frag_parent)
12767 vl_root = vl_root->frag_parent;
12768 vl_root->next_attempt = root->next_attempt;
12770 "We have no fragments in flight for message %" PRIu64
12771 ", reorder root %" PRIu64 "! Next attempt is %" PRIu64 "\n",
12772 root->logging_uuid,
12773 vl_root->logging_uuid,
12774 vl_root->next_attempt.abs_value_us);
12775 reorder_root_pm (vl_root, vl_root->next_attempt);
12776 }
12777 else
12778 {
12779 double factor = ((double) root->frag_count - 1)
12780 / (double) root->frag_count;
12781 struct GNUNET_TIME_Relative s1;
12782 struct GNUNET_TIME_Relative s2;
12783 struct GNUNET_TIME_Relative plus_mean =
12786 next_attempt);
12787
12789 "frag_count %u after factor\n",
12790 root->frag_count);
12792 factor);
12793 s2 = GNUNET_TIME_relative_divide (plus,
12794 root->frag_count);
12795 plus_mean = GNUNET_TIME_relative_add (s1, s2);
12798 "We have fragments in flight for message %" PRIu64
12799 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
12800 root->logging_uuid,
12802 }
12803 }
12804}
12805
12806
12811{
12816
12821
12826
12831
12835 int frag;
12836
12840 int relb;
12841
12846
12850 unsigned int frags_in_flight;
12851
12856};
12857
12858
12870static void
12872 struct Queue *queue,
12873 struct VirtualLink *vl,
12874 struct DistanceVectorHop *dvh,
12875 size_t overhead)
12876{
12877 struct GNUNET_TIME_Absolute now;
12878
12879 now = GNUNET_TIME_absolute_get ();
12880 /* NOTE: @a sc accumulates across calls -- #transmit_on_queue() zeroes it
12881 once and then runs us for the direct link and for every DV hop in turn.
12882 Clearing the verdict here made each call discard what the previous ones
12883 found, so a message that was too early on the direct link was forgotten
12884 as soon as one DV hop had nothing to offer, and nothing rescheduled the
12885 queue at all. */
12886 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
12887 pos = pos->next_vl)
12888 {
12889 size_t real_overhead = overhead;
12890 int frag;
12891 int relb;
12892
12893 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
12894 {
12896 "DV messages must not be DV-routed to next hop!\n");
12897 continue; /* DV messages must not be DV-routed to next hop! */
12898 }
12899 if (pos->next_attempt.abs_value_us > now.abs_value_us)
12900 {
12901 if (GNUNET_YES == pos->frags_in_flight)
12902 {
12903 sc->frags_in_flight = GNUNET_YES;
12905 "Fragments in flight for message %" PRIu64 "\n",
12906 pos->logging_uuid);
12907 }
12908 else
12909 {
12911 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
12912 PRIu64 "\n",
12913 pos->logging_uuid);
12914 /* The *earliest* deadline is the one to come back for: @e
12915 pending_msg_head is sorted by @e next_attempt, so overwriting
12916 this on every iteration left the largest delay of the whole
12917 list -- the queue then slept past every message but the last
12918 one. Across the calls for the direct link and each DV hop the
12919 same argument applies, hence the min() rather than an
12920 assignment. */
12921 sc->to_early_retry_delay =
12922 (GNUNET_YES == sc->to_early)
12923 ? GNUNET_TIME_relative_min (sc->to_early_retry_delay,
12925 pos->next_attempt))
12926 : GNUNET_TIME_absolute_get_remaining (pos->next_attempt);
12927 sc->to_early = GNUNET_YES;
12928 continue;
12929 }
12930 // break; /* too early for all messages, they are sorted by next_attempt */
12931 }
12932 if (NULL != pos->qe)
12933 {
12935 "not eligible\n");
12936 continue; /* not eligible */
12937 }
12938 sc->consideration_counter++;
12939 /* determine if we have to fragment, if so add fragmentation
12940 overhead! */
12942 "check %" PRIu64 " for sc->best\n",
12943 pos->logging_uuid);
12944 frag = GNUNET_NO;
12945 if (((0 != queue->mtu) &&
12946 (pos->bytes_msg + real_overhead > queue->mtu)) ||
12947 (pos->bytes_msg > UINT16_MAX - sizeof(struct
12949 ||
12950 (NULL != pos->head_frag /* fragments already exist, should
12951 respect that even if MTU is UINT16_MAX for
12952 this queue */))
12953 {
12955 "fragment msg with size %u, realoverhead is %lu\n",
12956 pos->bytes_msg,
12957 real_overhead);
12958 frag = GNUNET_YES;
12959 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
12960 {
12961 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
12962 header without the ACK UUID when using a *reliable* channel! */
12963 }
12964 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
12965 }
12966 /* determine if we have to reliability-box, if so add reliability box
12967 overhead */
12968 relb = GNUNET_NO;
12969 if ((GNUNET_NO == frag) &&
12970 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
12971 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
12972 {
12973 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
12974
12975 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
12976 {
12977 frag = GNUNET_YES;
12978 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
12979 }
12980 else
12981 {
12982 relb = GNUNET_YES;
12983 }
12985 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
12986 pos->bytes_msg,
12987 real_overhead,
12988 queue->mtu,
12989 frag,
12990 relb);
12991 }
12992
12993 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
12994 message would beat it! */
12995 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
12996 {
12997 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
12998 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
12999 experimentally validated. There may be some huge potential for
13000 improvement here. Also, we right now only compare how well the
13001 given message fits _this_ queue, and do not consider how well other
13002 queues might suit the message. Taking other queues into consideration
13003 may further improve the result, but could also be expensive
13004 in terms of CPU time. */
13005 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
13006 long long pm_score = frag * 40 + relb * 20 + real_overhead;
13007 long long time_delta =
13008 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
13009 / 1000LL;
13010
13011 /* "time_delta" considers which message has been 'ready' for transmission
13012 for longer, if a message has a preference for low latency, increase
13013 the weight of the time_delta by 10x if it is favorable for that message */
13014 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
13015 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
13016 time_delta *= 10; /* increase weight (always, both are low latency) */
13017 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
13018 (time_delta > 0))
13019 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
13020 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
13021 (time_delta < 0))
13022 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
13023 if (0 != queue->mtu)
13024 {
13025 /* Grant bonus if we are below MTU, larger bonus the closer we will
13026 be to the MTU */
13027 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
13028 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
13029 if (queue->mtu > real_overhead + pos->bytes_msg)
13030 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
13031 }
13032 if (sc_score + time_delta > pm_score)
13033 {
13035 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
13036 "\n",
13037 pos->logging_uuid,
13038 sc->best->logging_uuid);
13039 continue; /* sc_score larger, keep sc->best */
13040 }
13041 }
13042 sc->best = pos;
13043 sc->dvh = dvh;
13044 sc->frag = frag;
13045 sc->relb = relb;
13046 sc->real_overhead = real_overhead;
13047 }
13048}
13049
13050
13061static void
13063 struct Neighbour *next_hop,
13064 const struct GNUNET_MessageHeader *hdr,
13066{
13067 struct PendingMessageScoreContext *sc = cls;
13068 struct PendingMessage *pm = sc->best;
13069 struct PendingMessage *bpm;
13070 uint16_t bsize = ntohs (hdr->size);
13071
13072 GNUNET_assert (NULL == pm->bpm);
13073 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
13075 "5 created pm %p storing vl %p from pm %p\n",
13076 bpm,
13077 pm->vl,
13078 pm);
13080 bpm->pmt = PMT_DV_BOX;
13081 bpm->vl = pm->vl;
13082 bpm->timeout = pm->timeout;
13083 bpm->bytes_msg = bsize;
13084 bpm->frag_parent = pm;
13087 "Creating DV Box %" PRIu64 " for original message %" PRIu64
13088 " (next hop is %s)\n",
13090 pm->logging_uuid,
13091 GNUNET_i2s (&next_hop->pid));
13092 memcpy (&bpm[1], hdr, bsize);
13093 pm->bpm = bpm;
13094}
13095
13096
13112static void
13114{
13115 struct Queue *queue = cls;
13116 struct Neighbour *n = queue->neighbour;
13118 struct PendingMessage *pm;
13119
13120 queue->transmit_task = NULL;
13121 if ((NULL == n->vl) && (NULL == n->dv_head))
13122 {
13124 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
13125 GNUNET_i2s (&n->pid),
13126 queue->address);
13127 queue->idle = GNUNET_YES;
13128 return;
13129 }
13130 memset (&sc, 0, sizeof(sc));
13131 /* @e n need not have a link of its own: it may serve only as the first
13132 hop of DV paths, and the traffic queued for those still has to go out. */
13133 if (NULL != n->vl)
13134 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
13135 if (NULL == sc.best)
13136 {
13137 /* Also look at DVH that have the n as first hop! */
13138 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
13139 dvh = dvh->next_neighbour)
13140 {
13141 if (NULL == dvh->dv->vl)
13142 continue; /* route not (yet) visible to CORE, no messages for it */
13144 queue,
13145 dvh->dv->vl,
13146 dvh,
13147 sizeof(struct GNUNET_PeerIdentity)
13148 * (1 + dvh->distance)
13149 + sizeof(struct TransportDVBoxMessage)
13150 + sizeof(struct TransportDVBoxPayloadP));
13151 }
13152 }
13153 if (NULL == sc.best)
13154 {
13155 /* no message pending, nothing to do here! */
13157 "No pending messages, queue `%s' to %s now idle\n",
13158 queue->address,
13159 GNUNET_i2s (&n->pid));
13160 if (GNUNET_YES == sc.to_early)
13161 schedule_transmit_on_queue (sc.to_early_retry_delay,
13162 queue,
13164 queue->idle = GNUNET_YES;
13165 return;
13166 }
13167 /* There is a message pending, we are certainly not idle */
13168 queue->idle = GNUNET_NO;
13169
13170 /* Given selection in `sc`, do transmission */
13171 pm = sc.best;
13173 "Selected message <%" PRIu64 ">\n",
13174 pm->logging_uuid);
13175 if (NULL != sc.dvh)
13176 {
13178 "Is this %u a DV box?\n",
13179 pm->pmt);
13180 GNUNET_assert (PMT_DV_BOX != pm->pmt);
13181 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
13182 {
13184 "Discard old box, because we have a new DV path.\n");
13185 free_pending_message (sc.best->bpm);
13186 sc.best->bpm = NULL;
13187 }
13188
13189 if (NULL == sc.best->bpm)
13190 {
13192 "encapsulate_for_dv 2\n");
13193 encapsulate_for_dv (sc.dvh->dv,
13194 1,
13195 &sc.dvh,
13196 (const struct GNUNET_MessageHeader *) &sc.best[1],
13198 &sc,
13199 RMO_NONE,
13200 GNUNET_NO);
13201 GNUNET_assert (NULL != sc.best->bpm);
13203 "%lu %lu %lu %lu %u\n",
13204 sizeof(struct GNUNET_PeerIdentity),
13205 sizeof(struct TransportDVBoxMessage),
13206 sizeof(struct TransportDVBoxPayloadP),
13207 sizeof(struct TransportFragmentBoxMessage),
13208 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
13209 sc.best->bpm->used_dvh = sc.dvh;
13210 }
13211 pm = sc.best->bpm;
13212 }
13213 if (GNUNET_YES == sc.frag)
13214 {
13215 pm = fragment_message (queue, sc.dvh, pm);
13216 if (NULL == pm)
13217 {
13219 "Fragmentation failed queue %s to %s for <%" PRIu64
13220 ">, trying again\n",
13221 queue->address,
13222 GNUNET_i2s (&n->pid),
13223 sc.best->logging_uuid);
13224 /* NOT with a zero delay: nothing about @a queue or about the message
13225 changed between here and the next pass, so "trying again" at once
13226 is a busy loop that reproduces the failure at scheduler speed. */
13228 queue,
13230 return;
13231 }
13232 }
13233 else if (GNUNET_YES == sc.relb)
13234 {
13235 pm = reliability_box_message (queue, sc.dvh, pm);
13236 if (NULL == pm)
13237 {
13238 /* Reliability boxing failed, try next message... */
13239 GNUNET_log (
13241 "Reliability boxing failed queue %s to %s for <%" PRIu64
13242 ">, trying again\n",
13243 queue->address,
13244 GNUNET_i2s (&n->pid),
13245 sc.best->logging_uuid);
13246 /* Same reasoning as for the fragmentation failure above. */
13248 queue,
13250 return;
13251 }
13252 }
13253
13254 /* Pass 'pm' for transission to the communicator */
13255 GNUNET_log (
13257 "Passing message <%" PRIu64
13258 "> to queue %s for peer %s (considered %u others)\n",
13259 pm->logging_uuid,
13260 queue->address,
13261 GNUNET_i2s (&n->pid),
13262 sc.consideration_counter);
13263
13264 /* Flow control: increment amount of traffic sent; if we are routing
13265 via DV (and thus the ultimate target of the pending message is for
13266 a different virtual link than the one of the queue), then we need
13267 to use up not only the window of the direct link but also the
13268 flow control window for the DV link! */
13270
13271 if (pm->vl != queue->neighbour->vl)
13272 {
13273 /* If the virtual link of the queue differs, this better be distance
13274 vector routing! */
13275 GNUNET_assert (NULL != sc.dvh);
13276 /* If we do distance vector routing, we better not do this for a
13277 message that was itself DV-routed */
13278 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
13279 /* We use the size of the unboxed message here, to avoid counting
13280 the DV-Box header which is eaten up on the way by intermediaries.
13281 The next hop need not have a link of its own, in which case there is
13282 no window of it to charge. */
13283 if (NULL != queue->neighbour->vl)
13284 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
13285 }
13286 else
13287 {
13288 GNUNET_assert (NULL == sc.dvh);
13289 }
13290
13291 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
13292
13293 /* The message is with the communicator now, so return the CORE send
13294 window credit for it -- see #credit_client().
13295
13296 It used to be returned here only for an unboxed message or a reliable
13297 communicator, and otherwise not until the *peer* acknowledged the
13298 message below. That makes a window into a delivery confirmation: over
13299 an unreliable communicator every reliability-boxed or fragmented
13300 message holds one of the client's #SEND_WINDOW_SIZE slots for as long
13301 as its ACK takes, and a lost ACK holds it for the whole retransmission
13302 chain. Four of those and CORE cannot send to that peer at all -- not
13303 payload, but also not its HEARTBEATs and not one message of its key
13304 exchange. So the session times out for want of a heartbeat that is
13305 sitting in a queue, and the handshake that would rebuild it cannot go
13306 out either; CORE only recovers when a reconnect resets the window
13307 wholesale. Acknowledgements still drive retransmission below, they
13308 just no longer gate the client. */
13309 credit_client (sc.best);
13310
13311 /* Check if this transmission somehow conclusively finished handing 'pm'
13312 even without any explicit ACKs */
13313 if ((PMT_CORE == pm->pmt) ||
13314 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
13315 {
13317 }
13318 else
13319 {
13320 struct GNUNET_TIME_Relative wait_duration;
13321 unsigned int wait_multiplier;
13322
13323 if (PMT_FRAGMENT_BOX == pm->pmt)
13324 {
13325 struct PendingMessage *root;
13326
13327 root = pm->frag_parent;
13328 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
13329 root = root->frag_parent;
13330
13331 if ((0 == root->frag_off) || (0 == root->frag_count))
13332 {
13333 wait_multiplier = 4;
13334 }
13335 else
13336 {
13337 double wm = ceil ((double) root->bytes_msg
13338 / ((double) root->frag_off
13339 / (double) root->frag_count)) * 4.0;
13340
13341 if ((! (wm >= 1.0)) || (wm > 1024.0))
13342 wm = 4.0; /* NaN, infinity or absurd: fall back to the default */
13343 wait_multiplier = (unsigned int) wm;
13344 }
13345 }
13346 else
13347 {
13348 // No fragments, we use 4 RTT before retransmitting.
13349 wait_multiplier = 4;
13350 }
13351
13352 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
13353 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
13354
13356 "Wait multiplier %u\n",
13357 wait_multiplier);
13358
13359 /* Message not finished, waiting for acknowledgement.
13360 Update time by which we might retransmit 's' based on queue
13361 characteristics (i.e. RTT); it takes one RTT for the message to
13362 arrive and the ACK to come back in the best case; but the other
13363 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
13364 retransmitting.
13365
13366 OPTIMIZE: Note that in the future this heuristic should likely
13367 be improved further (measure RTT stability, consider message
13368 urgency and size when delaying ACKs, etc.) */
13369
13370 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
13371 queue->pd.aged_rtt.rel_value_us)
13372 wait_duration = GNUNET_TIME_relative_max (queue->pd.aged_rtt,
13374 else
13375 {
13376 wait_duration = DEFAULT_ACK_WAIT_DURATION;
13377 wait_multiplier = 4;
13378 }
13379 {
13382 wait_duration, wait_multiplier));
13384 wait_duration, wait_multiplier);
13386 "Waiting %s for ACK until %s\n",
13391 GNUNET_TIME_relative_multiply (wait_duration,
13392 wait_multiplier))
13393 );
13394 }
13395 }
13396 /* finally, re-schedule queue transmission task itself */
13398 queue,
13400}
13401
13402
13409static void
13411 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
13412{
13413 struct TransportClient *tc = cls;
13414
13415 if (CT_COMMUNICATOR != tc->type)
13416 {
13417 GNUNET_break (0);
13419 return;
13420 }
13421 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
13422 queue = queue->next_client)
13423 {
13424 struct Neighbour *neighbour = queue->neighbour;
13425
13426 if ((ntohl (dqm->qid) != queue->qid) ||
13427 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
13428 continue;
13430 "Dropped queue %s to peer %s\n",
13431 queue->address,
13432 GNUNET_i2s (&neighbour->pid));
13433 free_queue (queue);
13435 return;
13436 }
13437 /* Not finding the queue is a race, not a protocol violation: we may have
13438 freed it ourselves already, or the communicator may be tearing down a
13439 queue we never fully learned about. Do NOT drop the client over it --
13440 that runs #client_disconnect_cb(), which frees *every* queue this
13441 communicator owns, so one stale QUEUE_TEARDOWN would disconnect us from
13442 every peer it serves at once. Compare #handle_send_message_ack(), which
13443 tolerates the same lookup miss. */
13445 "QUEUE_TEARDOWN for unknown queue QID %u to peer %s ignored\n",
13446 ntohl (dqm->qid),
13447 GNUNET_i2s (&dqm->receiver));
13449 "# QUEUE_TEARDOWN dropped: queue unknown",
13450 1,
13451 GNUNET_NO);
13453}
13454
13455
13456static void
13458 struct TransportClient *tc)
13459{
13460 struct PendingMessage *pm;
13461
13462 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
13463 qe->queue->queue_tail,
13464 qe);
13465 qe->queue->queue_length--;
13466 tc->details.communicator.total_queue_length--;
13468 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
13469 qe->queue->address,
13470 qe->queue->qid,
13471 GNUNET_i2s (&qe->queue->neighbour->pid),
13472 qe->queue->queue_length,
13473 tc->details.communicator.total_queue_length);
13474
13475 /* if applicable, resume transmissions that waited on ACK */
13477 tc->details.communicator.total_queue_length)
13478 {
13479 /* Communicator dropped below threshold, resume all queues
13480 incident with this client! */
13482 GST_stats,
13483 "# Transmission throttled due to communicator queue limit",
13484 -1,
13485 GNUNET_NO);
13486 for (struct Queue *queue = tc->details.communicator.queue_head;
13487 NULL != queue;
13488 queue = queue->next_client)
13489 {
13491 queue,
13493 }
13494 }
13495 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
13496 {
13497 /* queue dropped below threshold; only resume this one queue */
13499 "# Transmission throttled due to queue queue limit",
13500 -1,
13501 GNUNET_NO);
13503 qe->queue,
13505 }
13506 else if (1 == qe->queue->q_capacity)
13507 {
13508 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
13510 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
13511 PRIu64 ".\n",
13512 qe->queue->qid,
13513 qe->queue->q_capacity);
13514 /* message queue has capacity; only resume this one queue */
13515 /* queue dropped below threshold; only resume this one queue */
13517 "# Transmission throttled due to message queue capacity",
13518 -1,
13519 GNUNET_NO);
13521 qe->queue,
13523 }
13524
13525 if (NULL != (pm = qe->pm))
13526 {
13527 struct VirtualLink *vl;
13528
13529 // GNUNET_assert (qe == pm->qe);
13530 pm->qe = NULL;
13531 /* If waiting for this communicator may have blocked transmission
13532 of pm on other queues for this neighbour, force schedule
13533 transmit on queue for queues of the neighbour */
13534 if (NULL == pm->frag_parent)
13535 {
13536 vl = pm->vl;
13537 if ((NULL != vl) &&
13538 (NULL != vl->pending_msg_head) &&
13539 (vl->pending_msg_head == pm))
13541 }
13542 }
13543 GNUNET_free (qe);
13544}
13545
13546
13553static void
13555 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
13556{
13557 struct TransportClient *tc = cls;
13558 struct QueueEntry *qe;
13559 struct Queue *failed_queue = NULL;
13560
13561 if (CT_COMMUNICATOR != tc->type)
13562 {
13563 GNUNET_break (0);
13565 return;
13566 }
13567
13568 /* find our queue entry matching the ACK */
13569 qe = NULL;
13571 "Looking for queue for PID %s\n",
13572 GNUNET_i2s (&sma->receiver));
13573 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
13574 queue = queue->next_client)
13575 {
13576 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
13577 continue;
13579 "Found PID %s\n",
13580 GNUNET_i2s (&queue->neighbour->pid));
13581
13582
13583 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
13584 qep = qep->next)
13585 {
13586 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
13587 sma->qid))
13588 continue;
13590 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
13591 PRIu64 " Ack QID %u\n",
13592 qep->mid,
13593 queue->qid,
13594 GNUNET_ntohll (sma->mid),
13595 ntohl (sma->qid));
13596 qe = qep;
13597 if ((NULL != qe->pm) && (qe->pm->qe != qe))
13599 "For pending message %" PRIu64 " we had retransmissions.\n",
13600 qe->pm->logging_uuid);
13601 break;
13602 }
13603 }
13604 if (GNUNET_OK != (int) ntohl (sma->status))
13605 {
13606 /* The communicator could not hand the message to the peer. The only
13607 thing that produces this today is #handle_send_msg()'s "queue no
13608 longer exists" branch in `transport_api_communication.c', i.e. the
13609 communicator has already torn the queue down on its side and the
13610 QUEUE_TEARDOWN is merely still in flight (or was lost).
13611
13612 Ignoring the status, as we used to, makes this self-sustaining:
13613 #free_queue_entry() releases the pending message and immediately
13614 reschedules transmission, #transmit_on_queue() picks the very same
13615 queue again -- transport still has it -- and we get another failure.
13616 Every round adds an envelope to the client MQ that is already
13617 congested, which is what shows up at the other end as
13618
13619 communicator INFO Transmission failed, queue no longer exists.
13620
13621 repeating at scheduler speed, and (because the service is busy
13622 servicing that loop) as
13623
13624 communicator WARNING Dropping message: transport is too slow,
13625 queue length N exceeded
13626
13627 on every *other* communicator. Treat the failure as the queue
13628 teardown it is and stop selecting this queue. */
13630 "Communicator could not send MID %" PRIu64
13631 " on QID %u to %s; dropping that queue\n",
13632 GNUNET_ntohll (sma->mid),
13633 ntohl (sma->qid),
13634 GNUNET_i2s (&sma->receiver));
13636 "# queues dropped (communicator send failed)",
13637 1,
13638 GNUNET_NO);
13639 if (NULL != qe)
13640 failed_queue = qe->queue;
13641 else
13642 for (struct Queue *queue = tc->details.communicator.queue_head;
13643 NULL != queue;
13644 queue = queue->next_client)
13645 if ((ntohl (sma->qid) == queue->qid) &&
13646 (0 == GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver)))
13647 {
13648 failed_queue = queue;
13649 break;
13650 }
13651 if (NULL != failed_queue)
13652 {
13653 /* #free_queue() releases every `struct QueueEntry' still on it --
13654 including @a qe -- and detaches their pending messages, so they are
13655 retried on whatever other queue this neighbour has. */
13656 free_queue (failed_queue);
13658 return;
13659 }
13660 }
13661 if (NULL == qe)
13662 {
13664 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
13665 GNUNET_ntohll (sma->mid),
13666 ntohl (sma->qid));
13667 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
13668 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
13669 /* this should never happen */
13670 // GNUNET_break (0);
13671 // GNUNET_SERVICE_client_drop (tc->client);
13673 return;
13674 }
13677}
13678
13679
13685static void
13687 const struct GNUNET_TRANSPORT_BurstFinished *bf)
13688{
13689 struct TransportClient *tc = cls;
13690
13691 (void) bf;
13694}
13695
13696
13706static int
13708 const struct GNUNET_PeerIdentity *pid,
13709 void *value)
13710{
13711 struct TransportClient *tc = cls;
13712 struct Neighbour *neighbour = value;
13713
13714 GNUNET_assert (CT_MONITOR == tc->type);
13715 for (struct Queue *q = neighbour->queue_head; NULL != q;
13716 q = q->next_neighbour)
13717 {
13718 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
13719 .cs = q->cs,
13720 .num_msg_pending = q->num_msg_pending,
13721 .num_bytes_pending = q->num_bytes_pending };
13722
13723 notify_monitor (tc, pid, q->address, q->nt, &me);
13724 }
13725 return GNUNET_OK;
13726}
13727
13728
13735static void
13738{
13739 struct TransportClient *tc = cls;
13740
13741 if (CT_NONE != tc->type)
13742 {
13743 GNUNET_break (0);
13745 return;
13746 }
13747 tc->type = CT_MONITOR;
13748 tc->details.monitor.peer = start->peer;
13749 tc->details.monitor.one_shot = ntohl (start->one_shot);
13753}
13754
13755
13760{
13765
13770};
13771
13772
13781static char *
13783 unsigned int *num_queues)
13784{
13785 char *ret = GNUNET_strdup ("");
13786
13787 *num_queues = 0;
13788 if (NULL == n)
13789 return ret;
13790 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
13791 {
13792 const char *prefix = q->tc->details.communicator.address_prefix;
13793 size_t plen = strlen (prefix);
13794 const char *pos;
13795 char *tmp;
13796
13797 (*num_queues)++;
13798 if (0 == plen)
13799 continue;
13800 /* Several queues to one neighbour routinely share a communicator;
13801 name each one once. */
13802 for (pos = strstr (ret, prefix);
13803 NULL != pos;
13804 pos = strstr (pos + 1, prefix))
13805 if (((pos == ret) || (',' == pos[-1])) &&
13806 (('\0' == pos[plen]) || (',' == pos[plen])))
13807 break;
13808 if (NULL != pos)
13809 continue;
13810 GNUNET_asprintf (&tmp, "%s%s%s", ret, ('\0' == ret[0]) ? "" : ",", prefix);
13811 GNUNET_free (ret);
13812 ret = tmp;
13813 }
13814 return ret;
13815}
13816
13817
13826static enum GNUNET_GenericReturnValue
13827report_link (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
13828{
13829 struct LinkListContext *llc = cls;
13830 struct VirtualLink *vl = value;
13832 struct GNUNET_MQ_Envelope *env;
13833 unsigned int pending = 0;
13834 unsigned int num_queues = 0;
13835 unsigned int distance = 0;
13836 struct Neighbour *hop;
13837 char *ccs;
13838 size_t clen;
13839
13840 if ((GNUNET_YES != llc->include_unconfirmed) &&
13841 (GNUNET_YES != vl->confirmed))
13842 return GNUNET_OK;
13843 for (struct PendingMessage *pm = vl->pending_msg_head;
13844 NULL != pm;
13845 pm = pm->next_vl)
13846 pending++;
13847 if (NULL != vl->n)
13848 {
13849 hop = vl->n;
13850 }
13851 else
13852 {
13853 /* Report the best (shortest) of the paths we currently know, and the
13854 communicators that carry its first hop. */
13855 struct DistanceVectorHop *best = NULL;
13856
13857 distance = UINT_MAX;
13858 if (NULL != vl->dv)
13859 for (struct DistanceVectorHop *pos = vl->dv->dv_head;
13860 NULL != pos;
13861 pos = pos->next_dv)
13862 if (pos->distance < distance)
13863 {
13864 distance = pos->distance;
13865 best = pos;
13866 }
13867 if (NULL == best)
13868 distance = 0; /* no paths left; report the link as adjacent */
13869 hop = (NULL != best) ? best->next_hop : NULL;
13870 }
13871 ccs = communicator_list (hop, &num_queues);
13872 clen = strlen (ccs) + 1;
13873 env = GNUNET_MQ_msg_extra (resp,
13874 clen,
13876 memcpy (&resp[1], ccs, clen);
13877 GNUNET_free (ccs);
13878 resp->target = *pid;
13879 resp->confirmed = htonl ((uint32_t) vl->confirmed);
13880 resp->route = htonl ((uint32_t) ((NULL != vl->n)
13883 resp->distance = htonl ((uint32_t) distance);
13884 resp->num_queues = htonl ((uint32_t) num_queues);
13885 resp->core_recv_window = htonl ((int32_t) vl->core_recv_window);
13886 resp->stalled = htonl ((uint32_t) vl->cmc_count);
13887 resp->pending = htonl (pending);
13888 resp->fc_retransmit_count = htonl ((uint32_t) vl->fc_retransmit_count);
13907 GNUNET_MQ_send (llc->tc->mq, env);
13908 return GNUNET_OK;
13909}
13910
13911
13920static void
13922 void *cls,
13924{
13925 struct TransportClient *tc = cls;
13926 struct LinkListContext llc = {
13927 .tc = tc,
13928 .include_unconfirmed = (int) ntohl (lr->include_unconfirmed)
13929 };
13930 struct GNUNET_MQ_Envelope *env;
13931 struct GNUNET_MessageHeader *end;
13932
13933 if (CT_NONE != tc->type)
13934 {
13935 GNUNET_break (0);
13937 return;
13938 }
13939 if (GNUNET_YES == GNUNET_is_zero (&lr->peer))
13940 {
13942 }
13943 else
13944 {
13945 struct VirtualLink *vl = lookup_virtual_link (&lr->peer);
13946
13947 if (NULL != vl)
13948 report_link (&llc, &lr->peer, vl);
13949 }
13952 GNUNET_MQ_send (tc->mq, env);
13954}
13955
13956
13964static struct TransportClient *
13966{
13967 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13968 {
13969 if (CT_COMMUNICATOR != tc->type)
13970 continue;
13971 if (NULL == tc->details.communicator.address_prefix)
13972 continue; /* receive-only communicator */
13973 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
13974 return tc;
13975 }
13976 GNUNET_log (
13978 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
13979 prefix);
13980 return NULL;
13981}
13982
13983
13991static void
13992suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
13993{
13994 static uint32_t idgen = 0;
13995 struct TransportClient *tc;
13996 char *prefix;
13997 struct GNUNET_TRANSPORT_CreateQueue *cqm;
13998 struct GNUNET_MQ_Envelope *env;
13999 size_t alen;
14000
14002 if (NULL == prefix)
14003 {
14004 GNUNET_break (0); /* We got an invalid address!? */
14005 return;
14006 }
14008 if (NULL == tc)
14009 {
14011 "# Suggestions ignored due to missing communicator",
14012 1,
14013 GNUNET_NO);
14015 "Cannot connect to %s at `%s', no matching communicator present\n",
14016 GNUNET_i2s (pid),
14017 address);
14019 return;
14020 }
14021 /* forward suggestion for queue creation to communicator */
14023 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
14024 (unsigned int) idgen,
14025 prefix,
14026 GNUNET_i2s (pid),
14027 address);
14029 alen = strlen (address) + 1;
14030 env =
14032 cqm->request_id = htonl (idgen++);
14033 cqm->receiver = *pid;
14034 memcpy (&cqm[1], address, alen);
14035 GNUNET_MQ_send (tc->mq, env);
14036}
14037
14038
14046static void
14048{
14050 struct GNUNET_TIME_Absolute monotonic_time;
14051
14052 if (NULL != vs->revalidation_task)
14053 {
14054 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
14055 vs->revalidation_task = NULL;
14056 }
14057 /*memcpy (&hkey,
14058 &hc,
14059 sizeof (hkey));*/
14061 "Remove key %s for address %s map size %u contains %u\n",
14062 GNUNET_h2s (&vs->hc),
14063 vs->address,
14066 &vs->hc));
14068
14070 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
14071 vs->last_challenge_use.abs_value_us)
14072 {
14073 vs->first_challenge_use = monotonic_time;
14074 }
14075 vs->last_challenge_use = monotonic_time;
14076 tvc.header.type =
14078 tvc.header.size = htons (sizeof(tvc));
14079 tvc.reserved = htonl (0);
14080 tvc.challenge = vs->challenge;
14081 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
14083 "Sending address validation challenge %s to %s\n",
14085 GNUNET_i2s (&q->neighbour->pid));
14086 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
14087}
14088
14089
14101static struct GNUNET_TIME_Relative
14103{
14104 const struct VirtualLink *vl = lookup_virtual_link (pid);
14105
14106 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
14107 return MAX_VALIDATION_CHALLENGE_FREQ; /* we have what we want */
14108 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
14109 {
14110 if (CT_APPLICATION != tc->type)
14111 continue;
14113 tc->details.application.requests,
14114 pid))
14116 }
14118}
14119
14120
14126static void
14128{
14129 struct ValidationState *vs;
14130 struct Queue *q;
14132 GST_cfg);
14133
14134 (void) cls;
14135 validation_task = NULL;
14137 /* drop validations past their expiration */
14138 while (
14139 (NULL != vs) &&
14141 {
14143 "Validation response %s cleaned up\n",
14144 GNUNET_sh2s (&vs->challenge.value));
14147 }
14148 if (NULL == vs)
14149 {
14151 "Address validation task not scheduled anymore, nothing to do\n");
14152 return; /* woopsie, no more addresses known, should only
14153 happen if we're really a lonely peer */
14154 }
14155 q = find_queue (&vs->pid, vs->address);
14156 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
14157 {
14159 "To early to start next address validation for challenge %s\n",
14160 GNUNET_sh2s (&vs->challenge.value));
14161 /* Do NOT just return: @e validation_task was set to NULL above and
14162 nothing re-arms it by itself. #update_next_challenge_time() only
14163 schedules us again when it is called with a *changed* time for some
14164 validation state, so bailing out here leaves a non-empty
14165 #validation_heap with no task attached: address (re)validation and
14166 the #suggest_to_connect() retries that go with it stop for *every*
14167 peer until some unrelated event happens to come along. A peer that
14168 just lost its only connection has no such events left. */
14171 now,
14172 vs->first_challenge_use),
14174 NULL);
14175 return;
14176 }
14177 if (NULL == q)
14178 {
14179 vs->awaiting_queue = GNUNET_YES;
14180 suggest_to_connect (&vs->pid, vs->address);
14181 }
14182 else
14184 /* Finally, reschedule next attempt */
14185 vs->challenge_backoff =
14186 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
14189 "Address validation task will run again in %s\n",
14190 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
14191 GNUNET_YES));
14194 vs->challenge_backoff));
14195}
14196
14197
14202{
14206 struct Queue *q;
14207
14211 unsigned int quality_count;
14212
14216 unsigned int num_queues;
14217
14222 unsigned int k;
14223};
14224
14225
14237static int
14239 const struct GNUNET_PeerIdentity *pid,
14240 void *value)
14241{
14242 struct QueueQualityContext *ctx = cls;
14243 struct Neighbour *n = value;
14244 int do_inc;
14245
14246 (void) pid;
14247 do_inc = GNUNET_NO;
14248 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
14249 {
14250 ctx->num_queues++;
14251 if (0 == ctx->k--)
14252 ctx->q = q;
14253 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
14254 statistics and consider those as well here? */
14255 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
14256 do_inc = GNUNET_YES;
14257 }
14258 if (GNUNET_YES == do_inc)
14259 ctx->quality_count++;
14260 return GNUNET_OK;
14261}
14262
14263
14275static void
14276start_dv_learn (void *cls);
14277
14278
14286static void
14288 struct LearnLaunchEntry *lle,
14289 struct QueueQualityContext qqc)
14290{
14291 if (0 == qqc.num_queues)
14292 {
14294 "# DV learn aborted: no queue left",
14295 1,
14296 GNUNET_NO);
14297 return;
14298 }
14299 qqc.quality_count = 0;
14301 qqc.num_queues = 0;
14302 qqc.q = NULL;
14305 &qqc);
14306 if (NULL == qqc.q)
14307 {
14309 "# DV learn aborted: no queue left",
14310 1,
14311 GNUNET_NO);
14312 return;
14313 }
14314
14315 /* Do this as close to transmission time as possible! */
14317
14318 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
14319 /* reschedule this job, randomizing the time it runs (but no
14320 actual backoff!) */
14321 if (NULL != dvlearn_task)
14326 NULL);
14327}
14328
14329
14341static void
14343{
14344 struct LearnLaunchEntry *lle;
14345 struct QueueQualityContext qqc;
14346 struct TransportDVLearnMessage dvl;
14347 const struct GNUNET_PeerIdentity *my_identity;
14348
14349 (void) cls;
14350 dvlearn_task = NULL;
14351 if ((GNUNET_YES == in_shutdown) || (NULL == pils))
14352 return;
14354 return; /* lost all connectivity, cannot do learning */
14356 if (NULL == my_identity)
14357 {
14358 /* PILS has not handed us an identity yet. The first queue arriving
14359 schedules us with add_now(), which routinely wins that race; retry
14360 instead of taking the service down. */
14364 NULL);
14365 return;
14366 }
14368 qqc.quality_count = 0;
14369 qqc.num_queues = 0;
14373 &qqc);
14375 {
14376 struct GNUNET_TIME_Relative delay;
14377 unsigned int factor;
14378
14379 /* scale our retries by how far we are above the threshold */
14383 "At connection quality %u, will launch DV learn in %s\n",
14384 qqc.quality_count,
14387 return;
14388 }
14389 /* remove old entries in #dvlearn_map if it has grown too big */
14390 while (MAX_DV_LEARN_PENDING <=
14392 {
14393 lle = lle_tail;
14396 &lle->challenge.value,
14397 lle));
14399 GNUNET_free (lle);
14400 }
14401 /* setup data structure for learning */
14402 lle = GNUNET_new (struct LearnLaunchEntry);
14404 sizeof(lle->challenge));
14406 "Starting launch DV learn with challenge %s\n",
14407 GNUNET_sh2s (&lle->challenge.value));
14412 &lle->challenge.value,
14413 lle,
14416 dvl.header.size = htons (sizeof(dvl));
14417 dvl.num_hops = htons (0);
14418 dvl.bidirectional = htons (0);
14420 dvl.monotonic_time =
14422 // We will set the below again later
14423 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
14424 dvl.challenge = lle->challenge;
14425 dvl.initiator = *my_identity;
14426 {
14427 struct DvInitPS dvip = {
14428 .purpose.purpose = htonl (
14430 .purpose.size = htonl (sizeof(dvip)),
14431 .monotonic_time = dvl.monotonic_time,
14432 .challenge = lle->challenge
14433 };
14434
14435 if (GNUNET_OK != sign_by_my_identity (&dvip.purpose, &dvl.init_sig))
14436 return;
14437 }
14438 transmit_dv_init (dvl, lle, qqc);
14439}
14440
14441
14451static char *
14453{
14454 const char *dash;
14455 const char *colon;
14456
14457 if (NULL == address)
14458 return NULL;
14459 dash = strchr (address, '-');
14460 if (NULL == dash)
14461 return NULL;
14462 colon = strchr (dash, ':');
14463 if (NULL == colon)
14464 return NULL;
14465 return GNUNET_strndup (dash + 1,
14466 colon - (dash + 1));
14467}
14468
14469
14479static int
14481 const struct GNUNET_PeerIdentity *pid,
14482 void *value)
14483{
14484 struct Queue *q = cls;
14485 struct ValidationState *vs = value;
14486 char *address_without_port_vs;
14487 char *address_without_port_q;
14488 char *prefix_vs;
14489 char *prefix_q;
14490 int success = GNUNET_YES;
14491
14492 // TODO Check if this is really necessary.
14493 address_without_port_vs = get_address_without_port (vs->address);
14494 address_without_port_q = get_address_without_port (q->address);
14495 prefix_vs = GNUNET_HELLO_address_to_prefix (vs->address);
14496 prefix_q = GNUNET_HELLO_address_to_prefix (q->address);
14497
14499 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
14500 GNUNET_i2s (pid),
14501 (NULL == address_without_port_vs) ? "<unparsable>"
14502 : address_without_port_vs,
14503 (NULL == address_without_port_q) ? "<unparsable>"
14504 : address_without_port_q);
14505 (void) pid;
14506 /* Only the port may differ: the address we asked to connect to is
14507 `PROTO-IP:0' for a NATed peer, while the queue that then materializes
14508 sits at `PROTO-IP:port'. The communicator must match all the same --
14509 a challenge for a `tcp-' address is not answered by a `udp-' queue. */
14510 if ((GNUNET_YES == vs->awaiting_queue) &&
14511 (NULL != address_without_port_vs) &&
14512 (NULL != address_without_port_q) &&
14513 (NULL != prefix_vs) &&
14514 (NULL != prefix_q) &&
14515 (0 == strcmp (prefix_vs, prefix_q)) &&
14516 (0 == strcmp (address_without_port_vs, address_without_port_q)))
14517 {
14518
14519 vs->awaiting_queue = GNUNET_NO;
14521 success = GNUNET_NO;
14522 }
14523
14524 GNUNET_free (address_without_port_vs);
14525 GNUNET_free (address_without_port_q);
14526 GNUNET_free (prefix_vs);
14527 GNUNET_free (prefix_q);
14528 return success;
14529}
14530
14531
14540static void
14542 const struct GNUNET_PEERSTORE_Record *record,
14543 const char *emsg)
14544{
14545 struct Neighbour *n = cls;
14546 struct GNUNET_TIME_AbsoluteNBO *mtbe;
14547
14548 (void) emsg;
14549 if (NULL == record)
14550 {
14551 /* we're done with #neighbour_dv_monotime_cb() invocations,
14552 continue normal processing */
14553 n->get = NULL;
14555 return;
14556 }
14557 if (0 == record->value_size)
14558 {
14560 GNUNET_break (0);
14561 return;
14562 }
14563 mtbe = record->value;
14568}
14569
14570
14571static void
14573 const struct GNUNET_PeerIdentity *pid,
14574 const char *uri)
14575{
14576 struct Queue *queue = cls;
14577 struct sockaddr_in v4;
14578 const char *slash;
14579 char *address_uri;
14580 char *prefix;
14581 char *uri_without_port;
14582 char *address_uri_without_port;
14583
14584 slash = strrchr (uri, '/');
14585 if ((NULL == slash) || (slash - uri < 2))
14586 {
14587 GNUNET_break_op (0); /* @a uri comes from a remote HELLO */
14588 return;
14589 }
14590 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
14591 slash++;
14592 GNUNET_asprintf (&address_uri,
14593 "%s-%s",
14594 prefix,
14595 slash);
14596
14598 "1 not global natted_address %u %s %s %s\n",
14599 queue->is_global_natted,
14600 uri,
14601 queue->address,
14602 slash);
14603
14604 uri_without_port = get_address_without_port (address_uri);
14605 if ((NULL == uri_without_port) ||
14606 (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr)))
14607 {
14609 GNUNET_free (address_uri);
14610 GNUNET_free (uri_without_port);
14611 return;
14612 }
14613
14615 "2 not global natted_address %u %s %s\n",
14616 queue->is_global_natted,
14617 uri,
14618 queue->address);
14619
14620 if (GNUNET_NO == queue->is_global_natted)
14621 {
14623 GNUNET_free (address_uri);
14624 GNUNET_free (uri_without_port);
14625 return;
14626 }
14627
14629 "3 not global natted_address %u %s %s\n",
14630 queue->is_global_natted,
14631 uri,
14632 queue->address);
14633
14634 if (0 == strcmp (uri_without_port, address_uri))
14635 {
14637 GNUNET_free (address_uri);
14638 GNUNET_free (uri_without_port);
14639 return;
14640 }
14641
14643 "4 not global natted_address %u %s %s\n",
14644 queue->is_global_natted,
14645 uri,
14646 queue->address);
14647
14648 address_uri_without_port = get_address_without_port (queue->address);
14649 if ((NULL != address_uri_without_port) &&
14650 (0 == strcmp (uri_without_port, address_uri_without_port)))
14651 {
14652 queue->is_global_natted = GNUNET_NO;
14653 }
14654
14656 "not global natted_address %u %s %s %s %s %s %u\n",
14657 queue->is_global_natted,
14658 uri,
14659 queue->address,
14660 uri_without_port,
14661 address_uri_without_port,
14662 prefix,
14663 GNUNET_NO);
14665 GNUNET_free (address_uri);
14666 GNUNET_free (address_uri_without_port);
14667 GNUNET_free (uri_without_port);
14668}
14669
14670
14683
14684
14685static enum GNUNET_GenericReturnValue
14687 const struct GNUNET_PeerIdentity *pid,
14688 void *value)
14689{
14690 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
14691 struct TransportGlobalNattedAddress *tgna = value;
14692 char *addr = (char *) &tgna[1];
14693
14694 /* NOTE: @a addr is NOT 0-terminated. */
14696 "Checking tgna %p with addr %.*s and length %u compare length %lu\n",
14697 tgna,
14698 (int) ntohl (tgna->address_length),
14699 addr,
14700 ntohl (tgna->address_length),
14701 strlen (tgna_cls->addr));
14702 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
14703 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
14704 {
14705 tgna_cls->tgna = tgna;
14706 return GNUNET_NO;
14707 }
14708 return GNUNET_YES;
14709}
14710
14711
14712static void
14714{
14716 "Error in PEERSTORE monitoring for checking global natted\n");
14717}
14718
14719
14720static void
14722{
14724 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
14725}
14726
14727
14728static void
14730 const struct GNUNET_PEERSTORE_Record *record,
14731 const char *emsg)
14732{
14733 struct Queue *queue = cls;
14734 struct Neighbour *neighbour = queue->neighbour;
14735 struct GNUNET_HELLO_Parser *parser;
14736 const struct GNUNET_MessageHeader *hello;
14738 size_t address_len_without_port;
14739
14740 if (NULL != emsg)
14741 {
14743 "Got failure from PEERSTORE: %s\n",
14744 emsg);
14746 return;
14747 }
14748 if (NULL == record)
14749 {
14750 GNUNET_break (0);
14752 return;
14753 }
14754 /* @a hello was published by a remote peer and may be malformed. */
14755 hello = hello_from_record (record);
14756 if (NULL == hello)
14757 {
14759 return;
14760 }
14761 queue->is_global_natted = GNUNET_YES;
14762 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
14763 if (NULL == parser)
14764 {
14766 "HELLO cannot be parsed!\n");
14768 return;
14769 }
14771 "before not global natted %u\n",
14772 queue->is_global_natted);
14775 queue);
14777 "after not global natted %u\n",
14778 queue->is_global_natted);
14779 GNUNET_HELLO_parser_free (parser);
14780
14781 tgna_cls.addr = get_address_without_port (queue->address);
14782 if (NULL == tgna_cls.addr)
14783 {
14784 GNUNET_break (0);
14786 return;
14787 }
14788 address_len_without_port = strlen (tgna_cls.addr);
14789 /*{
14790 char buf[address_len_without_port + 1];
14791
14792 GNUNET_memcpy (&buf, addr, address_len_without_port);
14793 buf[address_len_without_port] = '\0';
14794 GNUNET_free (addr);
14795 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
14796 }*/
14797 tgna_cls.tgna = NULL;
14799 &neighbour->pid,
14801 &tgna_cls);
14802 if (NULL != tgna_cls.tgna)
14804 " tgna_cls.tgna tgna %p %lu %u %u\n",
14805 tgna_cls.tgna,
14806 neighbour->size_of_global_addresses,
14807 ntohl (tgna_cls.tgna->address_length),
14808 neighbour->number_of_addresses);
14809 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
14810 {
14811 struct TransportGlobalNattedAddress *tgna;
14812
14813 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
14814 + address_len_without_port);
14815 tgna->address_length = htonl (address_len_without_port);
14816 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
14818 &neighbour->pid,
14819 tgna,
14821 neighbour->number_of_addresses++;
14822 /* MUST match what is subtracted on removal (and what
14823 #add_global_addresses() actually copies), or the accounting drifts. */
14824 neighbour->size_of_global_addresses += address_len_without_port;
14826 "Created tgna %p with address %s and length %lu\n",
14827 tgna,
14828 tgna_cls.addr,
14829 address_len_without_port + 1);
14830 }
14831 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
14832 {
14834 &neighbour->pid,
14835 tgna_cls.tgna);
14836 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
14838 );
14839 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
14840 ;
14841 GNUNET_assert (0 < neighbour->number_of_addresses);
14842 neighbour->number_of_addresses--;
14844 "removed tgna %p\n",
14845 tgna_cls.tgna);
14846 GNUNET_free (tgna_cls.tgna);
14847 }
14849 GNUNET_free (tgna_cls.addr);
14850}
14851
14852
14859static void
14861 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
14862{
14863 struct TransportClient *tc = cls;
14864 struct Queue *queue;
14865 struct Neighbour *neighbour;
14866 const char *addr;
14867 uint16_t addr_len;
14868
14869 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
14870 {
14871 /* MTU so small as to be useless for transmissions,
14872 required for #fragment_message()! */
14873 GNUNET_break_op (0);
14875 return;
14876 }
14877 /* This may simply be a queue update. Match on the peer as well as the
14878 QID: the communicator's key for a queue is the pair, and
14879 #handle_send_msg() on its side looks both of them up. Matching on the
14880 QID alone let an ADD_QUEUE for a *different* peer be folded into an
14881 existing queue, leaving @e neighbour pointing at the old peer -- after
14882 which every SEND_MSG we put on it carries a receiver the communicator
14883 cannot match, and comes straight back as "queue no longer exists". */
14884 for (queue = tc->details.communicator.queue_head;
14885 NULL != queue;
14886 queue = queue->next_client)
14887 {
14888 if (queue->qid != ntohl (aqm->qid))
14889 continue;
14890 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &aqm->receiver))
14891 continue;
14892 break;
14893 }
14894
14895 if (NULL != queue)
14896 {
14897 neighbour = queue->neighbour;
14898 }
14899 else
14900 {
14901 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
14902
14903 neighbour = lookup_neighbour (&aqm->receiver);
14904 if (NULL == neighbour)
14905 {
14906 neighbour = GNUNET_new (struct Neighbour);
14908 GNUNET_YES);
14909 neighbour->pid = aqm->receiver;
14910 /* Give a fresh neighbour a full window to say something. */
14911 neighbour->last_inbound = GNUNET_TIME_absolute_get ();
14914 neighbours,
14915 &neighbour->pid,
14916 neighbour,
14918 neighbour->get =
14920 "transport",
14921 &neighbour->pid,
14924 neighbour);
14925 }
14926 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
14927 addr = (const char *) &aqm[1];
14929 "New queue %s to %s available with QID %u and q_len %" PRIu64
14930 " and mtu %u\n",
14931 addr,
14932 GNUNET_i2s (&aqm->receiver),
14933 ntohl (aqm->qid),
14934 GNUNET_ntohll (aqm->q_len),
14935 ntohl (aqm->mtu));
14936 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
14937 queue->tc = tc;
14938 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
14939 next_neighbour)
14940 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
14941 validated_until);
14942 /* Inherit the validity of the sibling queues, but only while it is
14943 still in the future -- copying an already expired timestamp is
14944 pointless (and the condition used to be inverted). */
14945 if (0 != GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
14946 {
14948 "New queue with QID %u inherit validated until\n",
14949 ntohl (aqm->qid));
14950 queue->validated_until = validated_until;
14951 }
14952 queue->address = (const char *) &queue[1];
14953 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
14954 queue->qid = ntohl (aqm->qid);
14955 queue->neighbour = neighbour;
14957 queue->unlimited_length = GNUNET_YES;
14958 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
14959 memcpy (&queue[1], addr, addr_len);
14960 /* notify monitors about new queue */
14961 {
14962 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
14963
14964 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
14965 }
14967 neighbour->queue_head,
14968 neighbour->queue_tail,
14969 queue);
14971 tc->details.communicator.queue_head,
14972 tc->details.communicator.queue_tail,
14973 queue);
14974
14975 }
14976 queue->mtu = ntohl (aqm->mtu);
14977 queue->nt = ntohl (aqm->nt);
14978 queue->cs = ntohl (aqm->cs);
14979 queue->idle = GNUNET_YES;
14980
14981 if (NULL == queue->mo)
14982 {
14983 /* Only for a NEW queue: on a queue update this used to start a second
14984 monitor and leak the first one. */
14985 struct sockaddr_in v4;
14986 char *addr_without = get_address_without_port (queue->address);
14987 if ((NULL != addr_without) &&
14988 (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr)))
14989 {
14991 "start not global natted\n");
14993 GNUNET_YES,
14994 "peerstore",
14995 &neighbour->pid,
14997 &
14999 NULL,
15000 &
15002 NULL,
15004 queue);
15005 }
15006 GNUNET_free (addr_without);
15007 }
15008 /* check if valdiations are waiting for the queue */
15010 &aqm->receiver))
15013 &aqm->receiver,
15015 queue);
15016 /* Always (also) validate the address of the queue itself. A pending
15017 validation served above may well be for a *different* address string:
15018 #check_validation_request_pending() matches on the IP only, so a
15019 validation state waiting for the NAT address `PROTO-IP:0' is happily
15020 satisfied by a queue at `PROTO-IP:12345'. If we stopped here,
15021 #handle_validation_response() would later look for a queue at
15022 `PROTO-IP:0' -- which never exists -- and drop the successful
15023 validation on the floor without ever creating the virtual link. That
15024 is exactly what happens to the second of two peers behind the same
15025 NAT, as both of them advertise the very same `PROTO-IP:0'. */
15026 start_address_validation (&aqm->receiver, queue->address);
15027 /* look for traffic for this queue */
15028 // TODO Check whether this makes any sense at all.
15029 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
15030 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
15031 /* might be our first queue, try launching DV learning */
15032 if (NULL == dvlearn_task)
15035}
15036
15037
15044static void
15046 const struct
15048{
15049 struct TransportClient *tc = cls;
15050 struct Queue *target_queue = NULL;
15051
15052 if (CT_COMMUNICATOR != tc->type)
15053 {
15054 /* Without this we walk `details.communicator.queue_head' for a client
15055 whose union holds something else entirely. */
15056 GNUNET_break (0);
15058 return;
15059 }
15061 "Received queue update message for %u with q_len %llu and mtu %u\n",
15062 ntohl (msg->qid),
15063 (unsigned long long) GNUNET_ntohll (msg->q_len),
15064 ntohl (msg->mtu));
15065 for (target_queue = tc->details.communicator.queue_head;
15066 NULL != target_queue;
15067 target_queue = target_queue->next_client)
15068 {
15069 if (ntohl (msg->qid) == target_queue->qid)
15070 break;
15071 }
15072 if (NULL == target_queue)
15073 {
15075 "Queue to update no longer exists! Discarding update.\n");
15077 return;
15078 }
15079
15080 target_queue->nt = ntohl (msg->nt);
15081 target_queue->mtu = ntohl (msg->mtu);
15082 target_queue->cs = ntohl (msg->cs);
15083 target_queue->priority = ntohl (msg->priority);
15084 /* The update message indicates how many messages
15085 * the queue should be able to handle.
15086 */
15088 target_queue->unlimited_length = GNUNET_YES;
15089 else
15090 target_queue->unlimited_length = GNUNET_NO;
15091 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
15092 if (0 < target_queue->q_capacity)
15094 target_queue,
15097}
15098
15099
15107static void
15109 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
15110{
15111 struct TransportClient *tc = cls;
15112
15113 if (CT_COMMUNICATOR != tc->type)
15114 {
15115 GNUNET_break (0);
15117 return;
15118 }
15120 "# Suggestions succeeded at communicator",
15121 1,
15122 GNUNET_NO);
15124 "Request #%u for communicator to create queue succeeded\n",
15125 (unsigned int) ntohs (cqr->request_id));
15127}
15128
15129
15138static void
15140 void *cls,
15141 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
15142{
15143 struct TransportClient *tc = cls;
15144
15145 if (CT_COMMUNICATOR != tc->type)
15146 {
15147 GNUNET_break (0);
15149 return;
15150 }
15152 "Request #%u for communicator to create queue failed\n",
15153 (unsigned int) ntohl (cqr->request_id));
15155 "# Suggestions failed in queue creation at communicator",
15156 1,
15157 GNUNET_NO);
15159}
15160
15161
15169static void
15171{
15172 struct TransportClient *tc = cls;
15173 struct PeerRequest *pr;
15174
15175 if (CT_APPLICATION != tc->type)
15176 {
15177 GNUNET_break (0);
15179 return;
15180 }
15181 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
15182 &msg->peer);
15183 if (NULL == pr)
15184 {
15185 GNUNET_break (0);
15187 return;
15188 }
15189 (void) stop_peer_request (tc, &pr->pid, pr);
15191}
15192
15193
15194static void
15196 const struct GNUNET_PeerIdentity *pid,
15197 const char *uri)
15198{
15199 struct Queue *q;
15200 int pfx_len;
15201 const char *eou;
15202 char *address;
15203 (void) cls;
15204
15205 eou = strstr (uri,
15206 "://");
15207 if ((NULL == eou) || (eou == uri))
15208 {
15209 /* @a uri comes from a HELLO some remote peer published. */
15210 GNUNET_break_op (0);
15211 return;
15212 }
15213 pfx_len = eou - uri;
15214 eou += 3;
15216 "%.*s-%s",
15217 pfx_len,
15218 uri,
15219 eou);
15220
15222 "hello for client %s\n",
15223 address);
15224
15225 q = find_queue (pid, address);
15226 if (NULL == q)
15227 {
15229 }
15230 else
15233}
15234
15235
15243static void
15245 const struct GNUNET_PEERSTORE_Record *record,
15246 const char *emsg)
15247{
15248 const struct GNUNET_PeerIdentity *my_identity;
15249 struct PeerRequest *pr = cls;
15250 struct GNUNET_HELLO_Parser *parser;
15251 const struct GNUNET_MessageHeader *hello;
15252
15253 if (NULL != emsg)
15254 {
15256 "Got failure from PEERSTORE: %s\n",
15257 emsg);
15259 return;
15260 }
15261 if (NULL == record)
15262 {
15263 GNUNET_break (0);
15265 return;
15266 }
15268 if (NULL == my_identity)
15269 {
15271 "No identity given yet!\n");
15273 return;
15274 }
15275 hello = hello_from_record (record);
15276 if (NULL == hello)
15277 {
15278 /* MUST still ask for the next record: a bad one is not a reason to
15279 stall this monitor forever. */
15281 return;
15282 }
15283 if (0 == GNUNET_memcmp (&record->peer, my_identity))
15284 {
15286 return;
15287 }
15288 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
15289 if (NULL == parser)
15290 {
15292 "HELLO cannot be parsed!\n");
15294 return;
15295 }
15297 "HELLO for `%s' could be parsed, iterating addresses...!\n",
15301 NULL);
15302 GNUNET_HELLO_parser_free (parser);
15303 /* MUST ask for the next record, or this monitor stalls after one HELLO */
15305}
15306
15307
15308static void
15310{
15312 "Error in PEERSTORE monitoring\n");
15313}
15314
15315
15316static void
15318{
15320 "Done with initial PEERSTORE iteration during monitoring\n");
15321}
15322
15323
15335static void
15337{
15338 if (NULL != pr->nc)
15340 /* Monitor only @e pid. With NULL every application request sees every
15341 HELLO in PEERSTORE, so a client asking for one peer made us suggest a
15342 connection to -- and start an address validation for -- every peer we
15343 have ever heard of, once per request. #try_to_bring_link_up() had the
15344 same bug and was already fixed the same way. */
15345 pr->nc =
15347 GNUNET_YES,
15348 "peerstore",
15349 &pr->pid,
15352 NULL,
15354 NULL,
15356 pr);
15357}
15358
15359
15369static void
15371{
15372 struct PeerRequest *pr = cls;
15373 struct VirtualLink *vl;
15374
15375 pr->retry_task = NULL;
15376 vl = lookup_virtual_link (&pr->pid);
15377 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
15378 {
15379 /* The client has what it asked for. Keep watching cheaply, and start
15380 over from the short interval when the link goes away again. */
15384 pr);
15385 return;
15386 }
15388 "Retrying to connect to %s, an application client wants it\n",
15389 GNUNET_i2s (&pr->pid));
15391 "# link setup retries for application clients",
15392 1,
15393 GNUNET_NO);
15394 /* Addresses we already track, queues we still have, and a fresh look in
15395 PEERSTORE. */
15397 /* ... plus a replay of what PEERSTORE has for this peer, which is the
15398 only way back once the validation state expired and the queues are
15399 gone. */
15405 pr);
15406}
15407
15408
15416static void
15418{
15419 struct TransportClient *tc = cls;
15420 const struct GNUNET_PeerIdentity *my_identity;
15421 struct PeerRequest *pr;
15422
15423 if (CT_NONE == tc->type)
15424 {
15425 tc->type = CT_APPLICATION;
15426 tc->details.application.requests =
15428 }
15429 if (CT_APPLICATION != tc->type)
15430 {
15431 GNUNET_break (0);
15433 return;
15434 }
15436 if (NULL == my_identity)
15437 {
15439 "Still waiting for own identity!\n");
15441 return;
15442 }
15444 "Client suggested we talk to %s with preference %d at rate %u\n",
15445 GNUNET_i2s (&msg->peer),
15446 (int) ntohl (msg->pk),
15447 (int) ntohl (msg->bw.value__));
15448 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
15449 {
15451 "Client suggested connection to ourselves, ignoring...\n");
15453 return;
15454 }
15455 pr = GNUNET_new (struct PeerRequest);
15456 pr->tc = tc;
15457 pr->pid = msg->peer;
15458 pr->bw = msg->bw;
15459 pr->pk = ntohl (msg->pk);
15461 tc->details.application.requests,
15462 &pr->pid,
15463 pr,
15465 {
15466 GNUNET_break (0);
15467 GNUNET_free (pr);
15469 return;
15470 }
15472 /* The monitor alone only ever fires again if the HELLO *changes*. Keep
15473 asking for the link ourselves for as long as the client wants it. */
15474 pr->retry_backoff = SUGGEST_RETRY_MIN;
15475 pr->retry_task = GNUNET_SCHEDULER_add_delayed (pr->retry_backoff,
15477 pr);
15479}
15480
15481
15490static int
15492 const struct RequestHelloValidationMessage *m)
15493{
15494 (void) cls;
15496 return GNUNET_OK;
15497}
15498
15499
15507static void
15509 const struct RequestHelloValidationMessage *m)
15510{
15511 struct TransportClient *tc = cls;
15512 struct Queue *q;
15513
15514 q = find_queue (&m->peer, (const char *) &m[1]);
15515 if (NULL == q)
15516 {
15517 suggest_to_connect (&m->peer, (const char *) &m[1]);
15518 }
15519 else
15520 start_address_validation (&m->peer, (const char *) &m[1]);
15522}
15523
15524
15533static int
15535 const struct GNUNET_PeerIdentity *pid,
15536 void *value)
15537{
15538 struct Neighbour *neighbour = value;
15539
15540 (void) cls;
15541 (void) pid;
15542 GNUNET_break (0); // should this ever happen?
15543 free_neighbour (neighbour, GNUNET_YES);
15544
15545 return GNUNET_OK;
15546}
15547
15548
15563static int
15565 const struct GNUNET_PeerIdentity *pid,
15566 void *value)
15567{
15568 struct VirtualLink *vl = value;
15569
15570 (void) cls;
15571 (void) pid;
15572 free_virtual_link (vl);
15573
15574 return GNUNET_OK;
15575}
15576
15577
15586static int
15588 const struct GNUNET_PeerIdentity *pid,
15589 void *value)
15590{
15591 struct DistanceVector *dv = value;
15592
15593 (void) cls;
15594 (void) pid;
15595 free_dv_route (dv);
15596
15597 return GNUNET_OK;
15598}
15599
15600
15609static int
15611 const struct GNUNET_PeerIdentity *pid,
15612 void *value)
15613{
15614 struct ValidationState *vs = value;
15615
15616 (void) cls;
15617 (void) pid;
15619 return GNUNET_OK;
15620}
15621
15622
15631static int
15632free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
15633{
15634 struct PendingAcknowledgement *pa = value;
15635
15636 (void) cls;
15637 (void) key;
15639 return GNUNET_OK;
15640}
15641
15642
15651static int
15653 const struct GNUNET_PeerIdentity *pid,
15654 void *value)
15655{
15656 struct AcknowledgementCummulator *ac = value;
15657
15658 (void) cls;
15659 (void) pid;
15660 /* @e task is armed for the whole life of @a ac -- but
15661 #transmit_cummulative_ack_cb() clears it before re-arming, and it
15662 routes a message while it is clear. #GNUNET_SCHEDULER_cancel()
15663 dereferences its argument unconditionally. */
15664 if (NULL != ac->task)
15665 {
15667 ac->task = NULL;
15668 }
15669 GNUNET_free (ac);
15670 return GNUNET_OK;
15671}
15672
15673
15680static void
15681do_shutdown (void *cls)
15682{
15683 static int shutdown_done;
15684 struct LearnLaunchEntry *lle;
15685 struct PilsRequest *pr;
15686 (void) cls;
15687
15689 "shutdown logic\n");
15690 if (GNUNET_YES == shutdown_done)
15691 return; /* reachable both from #shutdown_task() and #client_disconnect_cb() */
15692 shutdown_done = GNUNET_YES;
15693 if (NULL != client_grace_task)
15694 {
15696 client_grace_task = NULL;
15697 }
15698 if (NULL != nh)
15699 {
15701 nh = NULL;
15702 }
15704 &free_neighbour_cb, NULL);
15705 /* Freeing a neighbour takes its virtual link with it, so whatever is
15706 left here is ownerless: a link we created from an inbound FLOW_CONTROL
15707 message that never got confirmed, kept alive only by its @e
15708 unconfirmed_timeout_task. #GNUNET_SCHEDULER_shutdown() does not run
15709 that task, so leaving the link in place left the task armed against a
15710 map we destroy further down -- it fired afterwards and
15711 #free_virtual_link() called GNUNET_CONTAINER_multipeermap_remove() on
15712 NULL. Drop them here, while every structure they touch is still
15713 alive. */
15716 NULL);
15717 if (NULL != validation_task)
15718 {
15720 validation_task = NULL;
15721 }
15722 if (NULL != dvlearn_task)
15723 {
15725 dvlearn_task = NULL;
15726 }
15727 if (NULL != burst_task)
15728 {
15730 burst_task = NULL;
15731 }
15732 if (NULL != burst_timeout_task)
15733 {
15735 burst_timeout_task = NULL;
15736 }
15739 dvlearn_map = NULL;
15742 dv_routes = NULL;
15743 if (NULL != GST_stats)
15744 {
15746 GST_stats = NULL;
15747 }
15748 if (NULL != GST_my_hello)
15749 {
15751 GST_my_hello = NULL;
15752 }
15755 NULL);
15757 ack_cummulators = NULL;
15760 NULL);
15762 pending_acks = NULL;
15765 neighbours = NULL;
15768 links = NULL;
15771 NULL);
15773 backtalkers = NULL;
15776 NULL);
15778 validation_map = NULL;
15780 validation_heap = NULL;
15782 revalidation_map = NULL;
15783 while (NULL != ir_head)
15785 GNUNET_assert (0 == ir_total);
15786 while (NULL != (lle = lle_head))
15787 {
15789 GNUNET_free (lle);
15790 }
15791 while (NULL != (pr = pils_requests_head))
15792 {
15795 pr);
15796 if (NULL != pr->op)
15797 GNUNET_PILS_cancel (pr->op);
15798 GNUNET_free (pr);
15799 }
15800 if (NULL != pils_feed_task)
15801 {
15803 pils_feed_task = NULL;
15804 }
15805 if (NULL != pils)
15806 {
15808 pils = NULL;
15809 }
15810 if (NULL != peerstore)
15811 {
15813 "Disconnecting from PEERSTORE service\n");
15815 peerstore = NULL;
15816 }
15818}
15819
15820
15821static const char*
15823{
15824 switch (type)
15825 {
15826 case CT_CORE:
15827 return "CORE";
15828 case CT_MONITOR:
15829 return "MONITOR";
15830 case CT_COMMUNICATOR:
15831 return "COMMUNICATOR";
15832 case CT_APPLICATION:
15833 return "APPLICATION";
15834 default:
15835 return "UNKNOWN";
15836 }
15837}
15838
15839
15847static void
15849{
15850 client_grace_task = NULL;
15851 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
15852 {
15854 "Client did not disconnect within the shutdown grace period, "
15855 "dropping it: %s\n",
15856 get_client_type_name (tc->type));
15857 }
15858 /* We use #GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, so the service will NOT
15859 drop clients for us. Without this we would wait forever for them to
15860 leave on their own and never reach #do_shutdown(). */
15862 /* Dropping the clients ran #client_disconnect_cb() for each of them, so
15863 #do_shutdown() has normally run by now; it is idempotent, and this
15864 covers the case where there was nothing left to drop. */
15865 do_shutdown (cls);
15866}
15867
15868
15869static void
15870shutdown_task (void *cls)
15871{
15873
15875 "Shutdown task executed\n");
15876 if (NULL != clients_head)
15877 {
15878 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
15879 {
15881 "Waiting for client to disconnect: %s\n",
15882 get_client_type_name (tc->type));
15883 }
15884 /* Give them a chance to shut down cleanly; #client_disconnect_cb() calls
15885 #do_shutdown() once the last one is gone, and #do_shutdown() cancels
15886 this task. */
15890 cls);
15891 return;
15892 }
15893 do_shutdown (cls);
15894}
15895
15896
15901
15902static void
15903update_hello_from_pid_change_cb (void *cls, int success)
15904{
15905 struct UpdateHelloFromPidCtx *pc = cls;
15906
15907 /* NOTE: @a success is GNUNET_OK even when #hello_add_iter() decided not to
15908 store anything because PEERSTORE already holds a HELLO that expires
15909 later; the API reports the desired state, not whether it wrote. So this
15910 says "we have a current HELLO on record", not "we just wrote one". */
15911 if (GNUNET_OK != success)
15913 "Failed to store our new hello with peerstore\n");
15914 else
15916 "Our hello is current in peerstore\n");
15917 GNUNET_free (pc);
15918}
15919
15920
15921void
15923 const struct GNUNET_PeerIdentity *pid,
15924 const char *uri)
15925{
15927 "%s\n", uri);
15928}
15929
15930
15940static void
15942 const struct GNUNET_HELLO_Parser *parser,
15943 const struct GNUNET_HashCode *hash)
15944{
15945 const struct GNUNET_PeerIdentity *my_identity;
15946 struct GNUNET_MQ_Envelope *env;
15947 const struct GNUNET_MessageHeader *msg;
15948 struct UpdateHelloFromPidCtx *sc;
15949 struct GNUNET_HELLO_Builder *nbuilder;
15950 struct GNUNET_PeerIdentity npid;
15951
15954
15955 if (NULL == GST_my_hello)
15958 "My current identity is `%s'\n",
15970 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
15971 &npid);
15972 if (GNUNET_NO ==
15974 {
15976 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
15978 "Proposed address list:\n");
15981 "Current address list:\n");
15983 GNUNET_HELLO_builder_free (nbuilder);
15984 return;
15985 }
15987 GST_my_hello = nbuilder;
15989 "My new identity is `%s'\n",
15995 msg,
15997 sc);
15998 GNUNET_free (env);
15999}
16000
16001
16009static void
16010run (void *cls,
16011 const struct GNUNET_CONFIGURATION_Handle *c,
16013{
16014 (void) cls;
16015 /* setup globals */
16019 GST_cfg = c;
16027 GNUNET_YES);
16032 // TODO check for all uses of GST_my_hello that it is not used uninitialized
16034 "transport",
16035 "USE_BURST_NAT");
16036 if (GNUNET_SYSERR == use_burst)
16038 "Could not configure burst nat use. Default to no.\n");
16044 "transport",
16045 0,
16046 0,
16047 NULL,
16048 0,
16049 NULL,
16050 NULL,
16051 NULL);
16052 if (NULL == peerstore)
16053 {
16054 GNUNET_break (0);
16056 return;
16057 }
16060 NULL); // FIXME we need to wait for
16061 // our first peer id before
16062 // we can start the service
16063 // completely - PILS in turn
16064 // waits for the first
16065 // addresses from the
16066 // communicators in order to
16067 // be able to generate a
16068 // peer id
16069 if (NULL == pils)
16070 {
16071 GNUNET_break (0);
16073 return;
16074 }
16075 /* Decapsulate DV box ephemeral keys ourselves. #handle_dv_box() needs
16076 the key material while it still has the box, which points into the
16077 communicator's inbound message and is gone the moment the handler
16078 returns -- so the asynchronous answer arrived to a dangling @a dvb. */
16079 if (GNUNET_OK !=
16082 _ ("Failed to load our private key, "
16083 "cannot open DV boxes addressed to us\n"));
16084}
16085
16086
16092 "transport",
16094 &run,
16097 NULL,
16098 /* communication with applications */
16099 GNUNET_MQ_hd_fixed_size (suggest,
16102 NULL),
16103 GNUNET_MQ_hd_fixed_size (suggest_cancel,
16106 NULL),
16107 GNUNET_MQ_hd_var_size (request_hello_validation,
16110 NULL),
16111 /* communication with core */
16112 GNUNET_MQ_hd_fixed_size (client_start,
16114 struct StartMessage,
16115 NULL),
16116 GNUNET_MQ_hd_var_size (client_send,
16118 struct OutboundMessage,
16119 NULL),
16120 GNUNET_MQ_hd_fixed_size (client_recv_ok,
16122 struct RecvOkMessage,
16123 NULL),
16124 /* communication with communicators */
16125 GNUNET_MQ_hd_var_size (communicator_available,
16128 NULL),
16129 GNUNET_MQ_hd_var_size (communicator_backchannel,
16132 NULL),
16133 GNUNET_MQ_hd_var_size (add_address,
16136 NULL),
16137 GNUNET_MQ_hd_fixed_size (del_address,
16140 NULL),
16141 GNUNET_MQ_hd_var_size (incoming_msg,
16144 NULL),
16145 GNUNET_MQ_hd_fixed_size (queue_create_ok,
16148 NULL),
16149 GNUNET_MQ_hd_fixed_size (queue_create_fail,
16152 NULL),
16153 GNUNET_MQ_hd_var_size (add_queue_message,
16156 NULL),
16157 GNUNET_MQ_hd_fixed_size (update_queue_message,
16160 NULL),
16161 GNUNET_MQ_hd_fixed_size (del_queue_message,
16164 NULL),
16165 GNUNET_MQ_hd_fixed_size (send_message_ack,
16168 NULL),
16169 GNUNET_MQ_hd_fixed_size (burst_finished,
16172 NULL),
16173 /* communication with monitors */
16174 GNUNET_MQ_hd_fixed_size (monitor_start,
16177 NULL),
16178 GNUNET_MQ_hd_fixed_size (link_list_request,
16181 NULL),
16183
16184
16185/* end of file gnunet-service-transport.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition gnunet-arm.c:103
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static char * init
Set to the name of a service to start.
Definition gnunet-arm.c:73
static int end
Set if we are to shutdown all services (including ARM).
Definition gnunet-arm.c:33
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
static struct GNUNET_TESTING_Interpreter * is
static struct Queue * queue_head
Head of queue of messages to transmit.
static int prefix
If printing the value of PREFIX has been requested.
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct GNUNET_FS_Handle * ctx
static struct GNUNET_GNS_LookupWithTldRequest * lr
Handle to lookup request.
Definition gnunet-gns.c:98
struct GNUNET_SCHEDULER_Task * shutdown_task
static unsigned int pending
The number of DNS queries that are outstanding.
static void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
static int result
Global testing status.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static struct GNUNET_FS_SearchContext * sc
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static unsigned long long payload
How much data are we currently storing in the database?
struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
The current private key.
static unsigned int ring_buffer_dv_head
Head of the ring buffer.
static void peerstore_store_validation_cb(void *cls, int success)
Function called when peerstore is done storing a validated address.
static void handle_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
#define DV_PATH_DISCOVERY_FREQUENCY
How long before paths expire would we like to (re)discover DV paths? Should be below DV_PATH_VALIDITY...
static struct GNUNET_SERVICE_Handle * GST_service
Our service handle; needed to force-disconnect clients that did not go away within SHUTDOWN_CLIENT_GR...
static struct PendingMessage * ring_buffer_dv[RING_BUFFER_SIZE]
Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virt...
static int dv_neighbour_transmission(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void reassembly_cleanup_task(void *cls)
Task run to clean up reassembly context of a neighbour that have expired.
static enum GNUNET_GenericReturnValue remove_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void backtalker_timeout_cb(void *cls)
Function called when it is time to clean up a backtalker.
static void handle_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void send_cmc_ack(struct CommunicatorMessageContext *cmc)
Release the CORE flow control credit for cmc by acknowledging the message to the communicator that de...
static unsigned int calculate_fork_degree(unsigned int hops_taken, unsigned int neighbour_count, unsigned int eligible_count)
Computes the number of neighbours we should forward a DVInit message to given that it has so far take...
static enum GNUNET_GenericReturnValue detach_cmc_from_backtalker(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Detach the ‘struct CommunicatorMessageContext’ parked on value from the client in cls.
static struct GNUNET_SCHEDULER_Task * dvlearn_task
Task run to initiate DV learning.
static int check_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void handle_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
#define SUGGEST_RETRY_MAX
What is the slowest rate at which we retry bringing up a link that an application client explicitly a...
static int check_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment box.
static unsigned int get_age()
Get an offset into the transmission history buffer for struct PerformanceData.
static void free_validation_state(struct ValidationState *vs)
Free validation state.
static struct PendingAcknowledgement * prepare_pending_acknowledgement(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Setup data structure waiting for acknowledgements.
static int check_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
static void hello_for_incoming_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
#define MAX_DV_DISCOVERY_SELECTION
Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiato...
#define QUEUE_ENTRY_TIMEOUT
static struct LearnLaunchEntry * lle_tail
Tail of a DLL sorted by launch time.
static struct GNUNET_CONTAINER_Heap * validation_heap
MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware ...
static void core_send_connect_info(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void send_dv_to_neighbour(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
static void harmonize_flight_round(struct PendingMessage *pm)
#define ACK_CUMMULATOR_TIMEOUT
How long until we forget about historic accumulators and thus reset the ACK counter?...
void pils_sign_address(struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
Build address record by signing raw information with private key of the peer identity.
static struct GNUNET_SCHEDULER_Task * client_grace_task
Task run when SHUTDOWN_CLIENT_GRACE_PERIOD expired and clients are still connected,...
static void free_queue(struct Queue *queue)
Free queue.
static void handle_del_address(void *cls, const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
Address of our peer deleted.
static struct LearnLaunchEntry * lle_head
Head of a DLL sorted by launch time.
#define EPHEMERAL_VALIDITY
How long are ephemeral keys valid?
static void free_fragment_tree(struct PendingMessage *root)
Free fragment tree below root, excluding root itself.
static unsigned int is_ring_buffer_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static struct IncomingRequest * ir_tail
Tail of DLL starting at ir_head.
static void pils_pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
Callback called when pils service updates us with our new peer identity.
static int free_pending_ack_cb(void *cls, const struct GNUNET_Uuid *key, void *value)
Free pending acknowledgement.
static void credit_client(struct PendingMessage *pm)
Return the send window credit that pm's client is owed, at most once for pm.
static int check_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
static void completed_pending_message(struct PendingMessage *pm)
We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment...
static void update_dvh_performance(struct DistanceVectorHop *dvh, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via dvh, update metrics.
struct GNUNET_NAT_Handle * nh
Handle for connect to the NAT service.
static int check_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static struct GNUNET_SCHEDULER_Task * pils_feed_task
Task to feed addresses to PILS.
static void client_send_response(struct PendingMessage *pm)
Send a response to the pm that we have processed a "send" request.
static void start_dv_learn(void *cls)
Task run when we CONSIDER initiating a DV learn process.
static int dv_neighbour_selection(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static enum GNUNET_GenericReturnValue revalidate_now_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Pull value's next challenge forward: the link to that peer is not up.
static void start_address_validation(const struct GNUNET_PeerIdentity *pid, const char *address)
Start address validation.
static void handle_del_queue_message(void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
Queue to a peer went down.
static void drop_remaining_clients(void *cls)
The grace period we gave our clients to disconnect on their own expired.
#define QUEUE_LENGTH_LIMIT
How many messages can we have pending for a given queue (queue to a particular peer via a communicato...
static void update_backtalker_monotime(struct Backtalker *b)
The backtalker b monotonic time changed.
#define MAX_CUMMULATIVE_ACKS
Maximum number of messages we acknowledge together in one cumulative ACK.
#define MAX_DV_HOPS_ALLOWED
Maximum DV distance allowed ever.
static const char * get_client_type_name(enum ClientType type)
static void burst_timeout(void *cls)
#define BACKCHANNEL_INACTIVITY_TIMEOUT
How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
#define WANTED_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges to a peer that an application client explicitly ...
static struct GNUNET_TIME_Relative get_network_latency(const struct TransportDVLearnMessage *dvl)
static void hello_for_client_error_cb(void *cls)
static void check_for_global_natted(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
#define ADDRESS_VALIDATION_LIFETIME
How long do we consider an address valid if we just checked?
static void free_distance_vector_hop(struct DistanceVectorHop *dvh)
Free a dvh.
#define MAX_FC_RETRANSMIT_COUNT
Maximum number of FC retransmissions for a running retransmission task.
#define MIN_ACK_WAIT_DURATION
Lower bound on the RTT estimate we are willing to derive a retransmission deadline from.
static void handle_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment.
static enum GNUNET_GenericReturnValue report_link(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Send the state of the virtual link value to the requesting client.
static struct PendingMessage * fragment_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Fragment the given pm to the given mtu.
static void update_hello_from_pid_change_cb(void *cls, int success)
static struct GNUNET_SCHEDULER_Task * validation_task
Task to run address validation.
static void handle_suggest(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void handle_link_list_request(void *cls, const struct GNUNET_TRANSPORT_LinkListRequest *lr)
A client asks for the virtual links we currently have.
static void cores_send_connect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we gained a connection.
#define SUGGEST_RETRY_MIN
How soon after an application asked us for a peer do we retry bringing the link up for the first time...
static void cummulative_ack(const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
static void task_consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define DV_LEARN_QUALITY_THRESHOLD
How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiati...
static void free_neighbour(struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
Release memory used by neighbour.
PendingMessageType
Types of different pending messages.
@ PMT_FRAGMENT_BOX
Fragment box.
@ PMT_DV_BOX
Pending message created during forward_dv_box().
@ PMT_CORE
Ordinary message received from the CORE service.
@ PMT_RELIABILITY_BOX
Reliability box.
static struct GNUNET_TIME_Relative calculate_rtt(struct DistanceVector *dv)
static void arm_free_queue_entry_task(struct TransportClient *tc)
Make sure free_timedout_queue_entry() will run for tc, so that `struct QueueEntry's the communicator ...
static int check_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int stop_peer_request(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Stop the peer request in value.
static void handle_update_queue_message(void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
Handle updates to queues.
static void cores_send_disconnect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void handle_client_start(void *cls, const struct StartMessage *start)
Initialize a "CORE" client.
#define MAX_DV_PATHS_TO_TARGET
Maximum number of DV paths we keep simultaneously to the same target.
static void free_virtual_link(struct VirtualLink *vl)
Free virtual link.
static enum GNUNET_GenericReturnValue detach_cmcs_from_link(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Detach the `struct CommunicatorMessageContext's parked on value from the client in cls.
RouteMessageOptions
Which transmission options are allowable for transmission? Interpreted bit-wise!
@ RMO_UNCONFIRMED_ALLOWED
We are allowed to use unconfirmed queues or DV routes for this message.
@ RMO_DV_ALLOWED
We are allowed to use DV routing for this hdr.
@ RMO_REDUNDANT
If we have multiple choices, it is OK to send this message over multiple channels at the same time to...
@ RMO_NONE
Only confirmed, non-DV direct neighbours.
@ RMO_ANYTHING_GOES
Reliable and unreliable, DV and non-DV are all acceptable.
static int notify_client_queues(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new MONITOR client about all existing queues to peers.
static struct AddressListEntry * create_address_entry(struct TransportClient *tc, struct GNUNET_TIME_Relative expiration, enum GNUNET_NetworkType nt, const char *address, uint32_t aid, size_t slen)
static void extract_box_cb(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void backtalker_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a backtalker by PEERSTORE.
static void queue_burst(void *cls)
static void handle_monitor_start(void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
Initialize a monitor client.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static void finish_cmc_handling(struct CommunicatorMessageContext *cmc)
static int learn_dv_path(const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
We have learned a path through the network to some other peer, add it to our DV data structure (retur...
static void store_pi(void *cls)
Ask peerstore to store our address.
#define FC_NO_CHANGE_REPLY_PROBABILITY
What is the 1:n chance that we send a Flow control response when receiving a flow control message tha...
static void notify_monitors(const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Send information in me about a peer's status with respect to some address to all monitors that care.
static struct GNUNET_TIME_Relative route_via_neighbour(const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Pick a queue of n under constraints options and schedule transmission of hdr.
#define RECV_WINDOW_SIZE
Window size.
static int check_known_challenge(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the challenge from cls.
static void store_signed_address(struct PilsAddressSignContext *pc, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Turn the signed address into a HELLO URI and hand it to PEERSTORE.
static unsigned int check_for_queue_with_higher_prio(struct Queue *queue, struct Queue *queue_head)
Check if there is another queue to the same neighbour, over a different communicator,...
#define GOODPUT_AGING_SLOTS
Number of slots we keep of historic data for computation of goodput / message loss ratio.
static int free_validation_state_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free validation state.
static int free_neighbour_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free neighbour entry.
static void handle_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static void decaps_dv_box_cont(struct CommunicatorMessageContext *cmc, const struct TransportDVBoxMessage *dvb, const struct GNUNET_ShortHashCode *km)
Open the DV box dvb addressed to us, using the key material km decapsulated from its ephemeral key.
static enum GNUNET_GenericReturnValue burst_running
Is there a burst running?
struct GNUNET_HELLO_Builder * GST_my_hello
Our HELLO.
static void start_burst(void *cls)
#define DV_QUALITY_RTT_THRESHOLD
We only consider queues as "quality" connections when suppressing the generation of DV initiation mes...
static struct TransportClient * clients_head
Head of linked list of all clients to this service.
static void handle_validation_challenge(void *cls, const struct TransportValidationChallengeMessage *tvc)
Communicator gave us a transport address validation challenge.
static struct PilsRequest * pils_requests_head
PILS Operation DLL.
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT
How many messages can we have pending for a given communicator process before we start to throttle th...
static void free_reassembly_context(struct ReassemblyContext *rc)
Free rc.
static struct VirtualLink * lookup_virtual_link(const struct GNUNET_PeerIdentity *pid)
Lookup virtual link for peer pid.
static int check_connection_quality(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counte...
#define MAX_DV_PICK_TRIES
How often pick_random_dv_hops() may redraw before settling for the paths it has.
static void reorder_root_pm(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
static void core_env_sent_cb(void *cls)
Function called when we are done giving a message of a certain size to CORE and should thus decrement...
static unsigned int ir_total
Length of the DLL starting at ir_head.
static int in_shutdown
Indication if we have received a shutdown signal and are in the process of cleaning up.
static struct GNUNET_TIME_Relative validation_challenge_freq(const struct GNUNET_PeerIdentity *pid)
How slow are we allowed to get with challenges for pid?
static void select_best_pending_from_link(struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
Select the best pending message from vl for transmission via queue.
static void suggest_to_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Signature of a function called with a communicator address of a peer pid that an application wants us...
static void free_timedout_queue_entry(void *cls)
static void handle_send_message_ack(void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
Message was transmitted.
static void update_pd_age(struct PerformanceData *pd, unsigned int age)
Check if we have advanced to another age since the last time.
#define DV_LEARN_BASE_FREQUENCY
What is the non-randomized base frequency at which we would initiate DV learn messages?
struct GNUNET_SCHEDULER_Task * burst_timeout_task
static void free_pending_acknowledgement(struct PendingAcknowledgement *pa)
Release pa data structure.
static struct GNUNET_CONTAINER_MultiUuidmap * pending_acks
Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgemen...
static struct GNUNET_CONTAINER_MultiShortmap * dvlearn_map
Map from challenges to struct LearnLaunchEntry values.
#define DV_FORWARD_TIMEOUT
If a DVBox could not be forwarded after this number of seconds we drop it.
static void finish_handling_raw_message(struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
static void handle_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static void update_queue_performance(struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via q, update metrics.
static void schedule_transmit_on_queue(struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
Called whenever something changed that might effect when we try to do the next transmission on queue ...
static void set_pending_message_uuid(struct PendingMessage *pm)
If necessary, generates the UUID for a pm.
static void free_pending_message(struct PendingMessage *pm)
Release memory associated with pm and remove pm from associated data structures.
static void revalidation_start_cb(void *cls)
static void backtalker_monotime_store_cb(void *cls, int success)
Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
static int free_reassembly_cb(void *cls, uint32_t key, void *value)
function called to free_reassembly_context().
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Called whenever a client connects.
#define DV_PATH_VALIDITY_TIMEOUT
How long do we consider a DV path valid if we see no further updates on it? Note: the value chosen he...
static void speed_up_challenge(struct ValidationState *vs)
Speed the next challenge for vs up because we heard something about that address again – but never fa...
static enum GNUNET_GenericReturnValue sign_ephemeral(struct DistanceVector *dv)
Sign the ephemeral key in dv, and mark it current.
#define RING_BUFFER_SIZE
Size of ring buffer to cache CORE and forwarded DVBox messages.
static void check_vl_transmission(struct VirtualLink *vl)
There is a message at the head of the pending messages for vl which may be ready for transmission.
static int find_by_message_uuid(void *cls, uint32_t key, void *value)
Iterator called to find a reassembly context by the message UUID in the multihashmap32.
static struct TransportClient * lookup_communicator(const char *prefix)
Find transport client providing communication service for the protocol prefix.
static unsigned int ring_buffer_head
Head of the ring buffer.
#define MAX_ADDRESS_VALID_UNTIL
When do we forget an invalid address for sure?
static void handle_hello_for_client(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
#define SHUTDOWN_CLIENT_GRACE_PERIOD
How long do we wait during shutdown for our clients to disconnect on their own before we drop them?...
static void transmit_dv_init(struct TransportDVLearnMessage dvl, struct LearnLaunchEntry *lle, struct QueueQualityContext qqc)
Finish and transmit the DV learn message dvl we initiated.
static void handle_suggest_cancel(void *cls, const struct ExpressPreferenceMessage *msg)
An application client no longer wants us to connect to a peer it asked for earlier.
static void update_performance_data(struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully tran...
static void forward_dv_box(struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
Create a DV Box message and queue it for transmission to next_hop.
static void handle_validation_response(void *cls, const struct TransportValidationResponseMessage *tvr)
Communicator gave us a transport address validation response.
static void handle_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static int free_virtual_link_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free virtual link entry.
static void send_msg_from_cache(struct VirtualLink *vl)
static void free_address_list_entry(struct AddressListEntry *ale)
Free ale.
static void free_burst_cls(struct GNUNET_StartBurstCls *sb_cls)
Release a burst closure, detaching it from its virtual link and from the scheduled burst_task (if tha...
static unsigned int pick_random_dv_hops(const struct DistanceVector *dv, enum RouteMessageOptions options, struct DistanceVectorHop **hops_array, unsigned int hops_array_length)
Pick hops_array_length random DV paths satisfying options.
static void handle_burst_finished(void *cls, const struct GNUNET_TRANSPORT_BurstFinished *bf)
The burst finished.
static void hello_for_incoming_sync_cb(void *cls)
static enum GNUNET_GenericReturnValue resume_communicators(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define FC_KEEPALIVE_INTERVAL
How long may a confirmed virtual link go without us sending anything on it before we transmit an othe...
static struct PilsRequest * pils_requests_tail
PILS Operation DLL.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Map from PIDs to struct Neighbour entries.
static void release_stalled_cmc(struct VirtualLink *vl, struct CommunicatorMessageContext *cmc)
Take cmc off the list of messages waiting on vl's CORE receive window, release the flow control credi...
static void transmit_on_queue(void *cls)
We believe we are ready to transmit a message on a queue.
static void handle_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void iterate_address_start_burst(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void disconnect_and_free_virtual_link(struct VirtualLink *vl)
Tell CORE clients the link to vl is gone, then release it.
static struct Queue * find_queue(const struct GNUNET_PeerIdentity *pid, const char *address)
Find the queue matching pid and address.
static void activate_core_visible_dv_path(struct DistanceVectorHop *hop)
The hop is a validated path to the respective target peer and we should tell core about it – and sche...
static void free_dv_route(struct DistanceVector *dv)
Free entry in dv_routes.
static unsigned int is_ring_buffer_dv_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static int check_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
#define DEFAULT_WINDOW_SIZE
How big is the flow control window size by default; limits per-neighbour RAM utilization.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate transport service.
#define MAX_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges?
static void cancel_address_store(struct AddressListEntry *ale)
Abort the asynchronous sign-and-store chain (if any) that is currently running for ale and release it...
static void handle_queue_create_ok(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue "worked", that is setting up the queue is no...
static enum GNUNET_GenericReturnValue sign_by_my_identity(const struct GNUNET_CRYPTO_SignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
Sign purpose with the private key of our current peer identity.
static int notify_client_connect_info(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new CORE client about all existing connections to peers.
static void core_fc_stalled(void *cls)
CORE never returned the flow control credit for the messages we handed it for cls,...
static void shc_cont(void *cls, int success)
static void handle_raw_message(void *cls, const struct GNUNET_MessageHeader *mh)
Communicator gave us an unencapsulated message to pass as-is to CORE.
static void handle_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
static struct Queue * find_queue_by_ip(const struct GNUNET_PeerIdentity *pid, const char *address)
Find a queue to pid whose address has the same IP as address, but possibly a different port.
static unsigned long long logging_uuid_gen
Generator of logging_uuid in struct PendingMessage.
static int check_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Client notified us about transmission from a peer.
#define REASSEMBLY_EXPIRATION
How long do we keep partially reassembled messages around before giving up?
static void update_next_challenge_time(struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
Set the time for next_challenge of vs to new_time.
static struct Neighbour * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup neighbour for peer pid.
static void peerstore_store_own_cb(void *cls, int success)
Function called when peerstore is done storing our address.
static struct RingBufferEntry * ring_buffer[RING_BUFFER_SIZE]
Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
#define MIN_DELAY_ADDRESS_VALIDATION
What is the maximum frequency at which we do address validation? A random value between 0 and this va...
static void handle_acknowledged(struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
The pa was acknowledged, process the acknowledgement.
static struct GNUNET_CONTAINER_MultiPeerMap * backtalkers
Map from PIDs to struct Backtalker entries.
static struct GNUNET_TIME_Absolute hello_mono_time
Monotonic time we use for HELLOs generated at this time.
static int check_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static char * communicator_list(struct Neighbour *n, unsigned int *num_queues)
Build the 0-terminated, comma-separated list of address prefixes of the communicators that own the qu...
static void handle_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct GNUNET_CONTAINER_MultiHashMap * revalidation_map
Map from addresses to struct ValidationState entries describing addresses we are aware of and their v...
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
static enum GNUNET_GenericReturnValue revalidate_map_it(void *cls, const struct GNUNET_HashCode *key, void *value)
#define DEFAULT_ACK_WAIT_DURATION
Default value for how long we wait for reliability ack.
static struct PendingMessage * reliability_box_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Reliability-box the given pm.
static int free_backtalker_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Callback to free backtalker records.
static enum GNUNET_GenericReturnValue contains_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void path_cleanup_cb(void *cls)
Task called when we should check if any of the DV paths we have learned to a target are due for garba...
#define FAST_VALIDATION_CHALLENGE_FREQ
What is the fastest rate at which we send challenges if we keep learning an address (gossip,...
static int check_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void demultiplex_with_cmc(struct CommunicatorMessageContext *cmc)
Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the ri...
#define MAX_DV_LEARN_PENDING
Maximum number of DV learning activities we may have pending at the same time.
static void hello_for_client_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void validation_start_cb(void *cls)
Task run periodically to validate some address based on validation_heap.
#define VALIDATION_RTT_BUFFER_FACTOR
How many network RTTs before an address validation expires should we begin trying to revalidate?...
static void handle_client_recv_ok(void *cls, const struct RecvOkMessage *rom)
Client confirms that it is done handling message(s) to a particular peer.
static void feed_addresses_to_pils(void *cls)
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
static int check_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static int check_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct TransportClient * clients_tail
Tail of linked list of all clients to this service.
static struct GNUNET_CONTAINER_MultiPeerMap * ack_cummulators
Map from PIDs to struct AcknowledgementCummulators.
static void transmit_cummulative_ack_cb(void *cls)
Do the transmission of a cumulative acknowledgement now.
static int check_validation_request_pending(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
A new queue has been created, check if any address validation requests have been waiting for it.
static void resume_cmc_client(struct CommunicatorMessageContext *cmc)
Let the communicator that delivered cmc give us its next message.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static const struct GNUNET_MessageHeader * hello_from_record(const struct GNUNET_PEERSTORE_Record *record)
Obtain the HELLO message stored in record, if record actually carries one.
static struct GNUNET_SCHEDULER_Task * burst_task
The task to start the burst.
static void send_t_validation_response(struct CommunicatorMessageContext *cmc, struct TransportValidationResponseMessage tvr)
Route the signed validation response tvr back to the challenger and release cmc.
void print_address_list(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_TIME_Relative encapsulate_for_dv(struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
Pick a path of dv under constraints options and schedule transmission of hdr.
static void suggest_retry_cb(void *cls)
Task run for as long as an application client wants a link to pid that we do not have.
static void neighbour_store_dvmono_cb(void *cls, int success)
Function called when peerstore is done storing a DV monotonic time.
static void handle_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
A client encountered an address of another peer.
static void free_queue_entry(struct QueueEntry *qe, struct TransportClient *tc)
static void pils_sign_hello_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Get HELLO signature and create message to store in PEERSTORE.
static void check_for_global_natted_sync_cb(void *cls)
#define UNCONFIRMED_LINK_TIMEOUT
How long do we keep a virtual link that only exists because some peer sent us a FLOW_CONTROL message,...
static void handle_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void notify_monitor(struct TransportClient *tc, const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Notify monitor tc about an event.
static void check_for_burst_address(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
static unsigned int check_next_attempt_tree(struct PendingMessage *pm, struct PendingMessage *root)
static void hello_for_incoming_error_cb(void *cls)
static struct GNUNET_StartBurstCls * burst_task_cls
Closure of the currently scheduled burst_task, or NULL.
static void send_ok_to_client(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Return one unit of send window credit for pid to tc.
static void queue_send_msg(struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
Send the message payload on queue.
static void handle_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
#define MIN_ADDRESS_REFRESH_INTERVAL
How often are we willing to re-sign and re-store one of our own addresses in PEERSTORE,...
static int check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void handle_hello_for_incoming(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void try_to_bring_link_up(const struct GNUNET_PeerIdentity *pid)
Ask for everything that could give us a confirmed virtual link to pid: revalidate the addresses we al...
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static int check_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void iterate_address_and_compare_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validi...
static struct GNUNET_TIME_Relative dvlearn_pils_backoff
Backoff for start_dv_learn() while PILS still owes us an identity.
#define MIN_FC_RETRANSMIT_DELAY
Lower bound on the delay between two flow control transmissions on the same virtual link.
static int free_dv_routes_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free DV route entry.
static enum GNUNET_GenericReturnValue add_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR
Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope...
static void handle_queue_create_fail(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue failed.
static void check_link_down(void *cls)
Task run to check whether the hops of the cls still are validated, or if we need to core about discon...
static void check_for_global_natted_error_cb(void *cls)
static void finish_cmc_handling_with_continue(struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
Send ACK to communicator (if requested) and free cmc.
static void forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
Build and forward a DV learn message to next_hop.
static void handle_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Incoming message.
static void validation_transmit_on_queue(struct Queue *q, struct ValidationState *vs)
The queue q (which matches the peer and address in vs) is ready for queueing.
static int free_ack_cummulator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free acknowledgement cummulator.
static void update_pm_next_attempt(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission ...
#define PILS_FEED_ADDRESSES_DELAY
Delay between added/removed addresses and PILS feed call.
static int check_known_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the address from cls.
enum GNUNET_GenericReturnValue use_burst
static struct GNUNET_CONTAINER_MultiPeerMap * dv_routes
Map from PIDs to struct DistanceVector entries describing known paths to the peer.
static void detach_cmcs_from_client(const struct TransportClient *tc)
A communicator client is going away.
static struct GNUNET_TIME_Relative route_control_message_without_fc(struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
We need to transmit hdr to target.
static void free_incoming_request(struct IncomingRequest *ir)
Release ir data structure.
#define MAX_INCOMING_REQUEST
For how many incoming connections do we try to create a virtual link for (at the same time!...
static void neighbour_dv_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a DV initiator by PEERSTORE.
static struct GNUNET_PILS_Handle * pils
Service that manages our peer id.
static void start_peer_request_monitor(struct PeerRequest *pr)
(Re)start the PEERSTORE HELLO monitor of pr.
void(* DVMessageHandler)(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static char * get_address_without_port(const char *address)
Get the IP address without the communicator prefix and the port number.
ClientType
What type of client is the struct TransportClient about?
@ CT_APPLICATION
"Application" telling us where to connect (i.e.
@ CT_MONITOR
It is a monitor, forward monitor data.
@ CT_NONE
We do not know yet (client is fresh).
@ CT_CORE
Is the CORE service, we need to forward traffic to it.
@ CT_COMMUNICATOR
It is a communicator, use for communication.
#define NEIGHBOUR_LIVENESS_TIMEOUT
How long may a direct neighbour stay completely silent before we stop believing that its queues work,...
static int validate_dv_initiator_signature(struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, const struct GNUNET_PeerIdentity *init, const struct GNUNET_CRYPTO_ChallengeNonceP *challenge, const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
#define MAX_REASSEMBLY_CONTEXTS
Maximum number of messages we are willing to reassemble in parallel for a single virtual link.
static void unconfirmed_link_timeout(void *cls)
Discard a virtual link that only ever existed because some peer sent us a FLOW_CONTROL message and th...
static struct IncomingRequest * ir_head
List of incoming connections where we are trying to get a connection back established.
static void free_backtalker(struct Backtalker *b)
Free data structures associated with b.
static void hello_for_client_sync_cb(void *cls)
static void destroy_ack_cummulator(void *cls)
Clean up an idle cumulative acknowledgement data structure.
static void consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define CORE_FC_STALL_TIMEOUT
How long do we wait for CORE to return the flow control credit for the messages we handed it before w...
static unsigned int bsize
static struct GNUNET_TRANSPORT_LinkListContext * llc
Handle to the running listing, NULL once it completed.
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
static struct GNUNET_TIME_Relative duration
Option '-d': duration of the mapping.
Definition gnunet-vpn.c:90
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Helper library for handling HELLO URIs.
API to the peerstore service.
enum GNUNET_GenericReturnValue GNUNET_PILS_enable_private_key(struct GNUNET_PILS_Handle *handle)
Enable local access to the private key of the current peer identity.
Definition pils_api.c:896
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:624
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:647
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_hello(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *builder, struct GNUNET_TIME_Absolute et, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Create HELLO signature.
Definition pils_api.c:851
const struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_PILS_get_private_key(const struct GNUNET_PILS_Handle *handle)
Return the private key of the current peer identity.
Definition pils_api.c:943
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:776
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:875
void GNUNET_PILS_feed_addresses(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *addresses_builder)
Feed a set of addresses to pils so that it will generate a new peer id based on the given set of addr...
Definition pils_api.c:817
uint32_t dim
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE
Signature by a peer affirming that it received a challenge (and stating how long it expects the addre...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
Signature by a peer affirming that the given ephemeral key is currently in use by that peer's transpo...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
Signature by a peer affirming that it originated the DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
Signature by a peer affirming that it is on a DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS
Signature by a peer affirming that this is one of its addresses for the given time period.
API to create, modify and access statistics.
API of the transport service towards the communicator processes.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
GNUNET_TRANSPORT_CommunicatorCharacteristics
What characteristics does this communicator have?
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_LINK_ROUTE_DV
Over a distance vector path.
@ GNUNET_TRANSPORT_LINK_ROUTE_DIRECT
Over one or more queues to a directly connected neighbour.
@ GNUNET_TRANSPORT_CS_DOWN
Connection is down.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
uint64_t GNUNET_CRYPTO_random_u64(uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_decrypt(size_t ct_len, const unsigned char ct[ct_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, const struct GNUNET_CRYPTO_AeadMac *mac, void *pt)
Decrypt the given data using XChaCha20-Poly1305.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_SignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition crypto_ecc.c:646
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_encrypt(size_t pt_len, const unsigned char pt[pt_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, void *ct, struct GNUNET_CRYPTO_AeadMac *mac)
Encrypt the given data using XChaCha20-Poly1305.
void GNUNET_CRYPTO_random_block(void *buffer, size_t length)
Fill block with a random values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
uint32_t GNUNET_CRYPTO_random_u32(uint32_t i)
Produce a random value.
#define GNUNET_CONTAINER_MDLL_remove(mdll, head, tail, element)
Remove an element from a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_tail(mdll, head, tail, element)
Insert an element at the tail of a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_after(mdll, head, tail, other, element)
Insert an element into a MDLL after the given other element.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_MDLL_insert(mdll, head, tail, element)
Insert an element at the head of a MDLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
struct GNUNET_CONTAINER_MultiUuidmap * GNUNET_CONTAINER_multiuuidmap_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_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
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.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_remove(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from 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.
unsigned int GNUNET_CONTAINER_multihashmap32_size(const struct GNUNET_CONTAINER_MultiHashMap32 *map)
Get the number of key-value pairs 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.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_remove(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, const void *value)
Remove the given key-value pair from the map.
void GNUNET_CONTAINER_multiuuidmap_destroy(struct GNUNET_CONTAINER_MultiUuidmap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *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_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries 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_multiuuidmap_iterate(struct GNUNET_CONTAINER_MultiUuidmap *map, GNUNET_CONTAINER_MultiUuidmapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_put(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multiuuidmap_get(const struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key)
Given a key find a value in the map matching the key.
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_MULTIPLE
Allow multiple values with the same key.
@ 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_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
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 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.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:380
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:398
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:344
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition hello-uri.c:1033
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_parser(const struct GNUNET_HELLO_Parser *parser, struct GNUNET_PeerIdentity *pid)
Allocate builder from parser.
Definition hello-uri.c:361
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_iterate(const struct GNUNET_HELLO_Parser *parser, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a parser.
Definition hello-uri.c:1052
struct GNUNET_MQ_Envelope * GNUNET_HELLO_parser_to_env(const struct GNUNET_HELLO_Parser *parser)
Generate envelope with GNUnet HELLO message (including peer ID) from a parser.
Definition hello-uri.c:980
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_address_list_cmp(const struct GNUNET_HELLO_Builder *abuilder, const struct GNUNET_HELLO_Builder *bbuilder)
Compare address lists of two builders.
Definition hello-uri.c:1408
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_del_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Remove individual address from the builder.
Definition hello-uri.c:1009
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:354
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid)
Parse msg.
Definition hello-uri.c:416
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_add_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Add individual address to the builder.
Definition hello-uri.c:701
char * GNUNET_HELLO_address_to_prefix(const char *address)
Given an address as a string, extract the prefix that identifies the communicator offering transmissi...
Definition hello-uri.c:1139
struct GNUNET_MQ_Envelope * GNUNET_HELLO_builder_to_env(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration_time)
Generate envelope with GNUnet HELLO message (including peer ID) from a builder.
Definition hello-uri.c:1219
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
GNUNET_SCHEDULER_Priority
Valid task priorities.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
#define GNUNET_static_assert(cond)
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity 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).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_EXTRA_LOGGING
define GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source tree where gnunet_config....
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#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.
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:337
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition mq.c:317
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_check_boxed_message(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
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:687
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:928
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_try_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Same as GNUNET_MQ_handle_message(), except that a message for which no handler is registered is not l...
Definition mq.c:291
@ GNUNET_MQ_PRIO_BACKGROUND
Lowest priority, i.e.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
@ GNUNET_MQ_PREF_LOW_LATENCY
Flag to indicate that low latency is important.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition nat.c:89
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
void GNUNET_NAT_add_global_address(struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
Add global address to the list of addresses and notify clients.
Definition nat_api.c:460
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
#define GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME
Key used to store sender's monotonic time from backchannel messages.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
#define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME
Key used to store sender's monotonic time from DV learn messages.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
void GNUNET_PEERSTORE_hello_add_cancel(struct GNUNET_PEERSTORE_StoreHelloContext *huc)
Cancel the request to add a hello.
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY
Key used for storing HELLOs in the peerstore.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
struct GNUNET_PEERSTORE_StoreHelloContext * GNUNET_PEERSTORE_hello_add(struct GNUNET_PEERSTORE_Handle *h, const struct GNUNET_MessageHeader *msg, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Add hello to peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
P2P message: transport requests confirmation that an address works.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK
transport acknowledges processing an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_RESPONSE
Information about a single virtual link, in response to a GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_REQ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN
inform transport that a queue was torn down
#define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
Type of the 'struct RequestHelloValidationMessage' send by clients to TRANSPORT to trigger validation...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START
Message from the core saying that the transport server should start giving it messages.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA
Message sent to indicate to a monitor about events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_REQUEST
Request a one-shot listing of the virtual links transport currently has, with their flow control stat...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR
Message sent to indicate to the transport which address prefix is supported by a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
Message telling transport to limit its receive rate.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
Type of a fragment of a CORE message created by transport to adjust message length to a queue's MTU.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL
Response from communicator: address bogus, will not try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
Source-routed transport message based DV information gathered.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
Wrapper around non-fragmented CORE message used to measure RTT and ensure reliability.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to abandon bandwidth prefe...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
Message from TRANSPORT notifying about a message that was received.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION
Message type used between transport services when they internally forward communicator backchannel me...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE
transport tells communicator it wants a queue
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
Message sent for topology discovery at transport level.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
Tell transport that it should assist with exchanging a message between communicators.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
Message from TRANSPORT notifying about a client that disconnected from us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG
inform transport about an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK
Response from communicator: will try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_RESPONSE_END
End of the responses to a GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_REQUEST.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK
communicator tells transports that message was sent
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS
inform transport to add an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START
Message sent to indicate to the transport that a monitor wants to observe certain events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS
inform transport to delete an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
P2P message: transport proves that an address worked.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG
transport tells communicator it wants to transmit
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
Request to TRANSPORT to transmit a message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
Confirmation from TRANSPORT that message for transmission has been queued (and that the next message ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
Confirmation for a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP
inform transport that a queue was setup to talk to some peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to establish bandwidth pre...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE
inform transport that a queue was updated
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1260
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
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:1310
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:1283
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1213
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition service.c:2512
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2528
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition strings.c:1629
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition time.c:344
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition time.c:264
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition time.c:626
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition time.c:352
#define GNUNET_TIME_relative_cmp(t1, op, t2)
Compare two relative times.
#define GNUNET_TIME_UNIT_SECONDS
One second.
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:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition time.c:368
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:610
struct GNUNET_TIME_Relative GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIME_Relative threshold)
Randomized exponential back-off, starting at 1 ms and going up by a factor of 2+r,...
Definition time.c:830
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition time.c:601
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply_double(struct GNUNET_TIME_Relative rel, double factor)
Multiply relative time by a given factor.
Definition time.c:506
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition time.c:583
struct GNUNET_TIME_Relative GNUNET_TIME_randomize(struct GNUNET_TIME_Relative r)
Return a random time value between 0.5*r and 1.5*r.
Definition time.c:851
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition time.c:471
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition time.c:360
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition time.c:616
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition time.c:452
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:860
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition time.c:548
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:671
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
Data structure in which we track acknowledgements still to be sent to the.
struct GNUNET_SCHEDULER_Task * task
Task scheduled either to transmit the cumulative ACK message, or to clean up this data structure afte...
struct GNUNET_TIME_Absolute min_transmission_time
When is task run (only used if num_acks is non-zero)?
struct TransportCummulativeAckPayload ack_uuids[64]
ACK data being accumulated.
struct GNUNET_PeerIdentity target
Target peer for which we are accumulating ACKs here.
unsigned int num_acks
Number of entries used in ack_uuids.
uint32_t ack_counter
Counter to produce the ack_counter in the struct TransportReliabilityAckMessage.
Unique identifier to map an acknowledgement to a transmission.
struct GNUNET_Uuid value
The UUID value.
size_t size
Capacity of tgnas, so that a drift between the cached ‘number_of_addresses’ / ‘size_of_global_address...
One of the addresses of this peer.
struct GNUNET_TIME_Relative expiration
What is a typical lifetime the communicator expects this address to have? (Always from now....
uint32_t aid
Address identifier used by the communicator.
struct GNUNET_TIME_Relative pils_backoff
Backoff used while waiting for PILS to hand us our peer identity.
size_t signed_address_len
Signed address length.
enum GNUNET_NetworkType nt
Network type offered by this address.
struct AddressListEntry * prev
Kept in a DLL.
struct TransportClient * tc
Which communicator provides this address?
struct AddressListEntry * next
Kept in a DLL.
struct GNUNET_PEERSTORE_StoreHelloContext * shc
Store hello handle.
void * signed_address
Signed address.
struct PilsAddressSignContext * pc
Context of the sign-and-store chain currently running for this entry, or NULL.
const char * address
The actual address.
struct GNUNET_SCHEDULER_Task * st
Task to periodically do st operation.
struct GNUNET_PEERSTORE_StoreContext * sc
Current context for storing this address in the peerstore.
A Backtalker is a peer sending us backchannel messages.
struct GNUNET_TIME_Absolute timeout
When will this entry time out?
struct CommunicatorMessageContext * cmc
Communicator context waiting on this backchannel's get, or NULL.
struct GNUNET_CRYPTO_HpkeEncapsulation last_ephemeral
Last (valid) ephemeral key received from this sender.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation for this pid's monotonic_time.
struct GNUNET_SCHEDULER_Task * task
Task associated with this backtalker.
size_t body_size
Number of bytes of the original message body that follows after this struct.
struct GNUNET_TIME_Absolute monotonic_time
Last (valid) monotonic time received from this sender.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch monotonic_time information from the PEERSTORE, or NULL.
struct GNUNET_PeerIdentity pid
Peer this is about.
Closure for check_known_address.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const char * address
Set to the address we are looking for.
Closure for check_known_challenge.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const struct GNUNET_CRYPTO_ChallengeNonceP * challenge
Set to the challenge we are looking for.
Context from handle_incoming_msg().
unsigned int client_resumed
Did we already call GNUNET_SERVICE_client_continue()? That call is per client, not per message,...
struct CommunicatorMessageContext * next
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
uint16_t total_hops
Number of hops the message has travelled (if DV-routed).
struct GNUNET_TRANSPORT_IncomingMessage im
Additional information for flow control and about the sender.
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
unsigned int ack_sent
Did we already send the flow control ACK to the communicator? The ACK is per-message and expresses CO...
struct CommunicatorMessageContext * prev
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
struct TransportClient * tc
Which communicator provided us with the message.
Message from the transport service to the library informing about neighbors.
Definition transport.h:90
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition transport.h:113
Closure for core_env_sent_cb.
uint16_t isize
By how much should we increment vl's incoming_fc_window_size_used once we are done sending to CORE?...
struct CoreSentContext * next
Kept in a DLL to clear vl in case vl is lost.
struct VirtualLink * vl
Virtual link this is about.
struct CoreSentContext * prev
Kept in a DLL to clear vl in case vl is lost.
uint16_t size
How big was the message.
An entry describing a peer on a path in a struct TransportDVLearnMessage message.
struct GNUNET_CRYPTO_EddsaSignature hop_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity hop
Identity of a peer on the path.
Message from the transport service to the library informing about disconnects.
Definition transport.h:122
One possible hop towards a DV target.
struct PerformanceData pd
Performance data for this transmission possibility.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used our path.
unsigned int distance
Number of hops in total to the target (excluding next_hop and target itself).
struct DistanceVectorHop * next_neighbour
Kept in a MDLL.
struct Neighbour * next_hop
What would be the next hop to target?
struct GNUNET_TIME_Absolute timeout
At what time do we forget about this path unless we see it again while learning?
struct DistanceVector * dv
Distance vector entry this hop belongs with.
const struct GNUNET_PeerIdentity * path
Array of distance hops to the target, excluding next_hop.
struct DistanceVectorHop * next_dv
Kept in a MDLL, sorted by timeout.
struct GNUNET_TIME_Absolute path_valid_until
For how long is the validation of this path considered valid? Set to ZERO if the path is learned by s...
struct DistanceVectorHop * prev_dv
Kept in a MDLL, sorted by timeout.
struct DistanceVectorHop * prev_neighbour
Kept in a MDLL.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used our path.
Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer.
struct DistanceVectorHop * dv_head
Known paths to target.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct GNUNET_TIME_Absolute monotime
What time was sender_sig created.
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature affirming ephemeral_key of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct DistanceVectorHop * dv_tail
Known paths to target.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Our ephemeral key.
struct GNUNET_ShortHashCode * km
Master secret for the setup of the Key material for the backchannel.
struct GNUNET_PeerIdentity target
To which peer is this a route?
struct GNUNET_TIME_Absolute ephemeral_validity
How long is sender_sig valid.
struct GNUNET_SCHEDULER_Task * timeout_task
Task scheduled to purge expired paths from dv_head MDLL.
Content signed by each peer during DV learning.
struct GNUNET_PeerIdentity pred
Identity of the previous peer on the path.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
Body by which a peer confirms that it is using an ephemeral key.
struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time
How long is this signature over the ephemeral key valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_PeerIdentity target
Target's peer identity.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
Application client to TRANSPORT service: we would like to have address suggestions for this peer.
Definition transport.h:948
Closure for find_by_message_uuid.
struct ReassemblyContext * rc
Set to the reassembly context if found.
struct MessageUUIDP message_uuid
UUID to look for.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
Wrapper struct with the average RTT of message to some peer and if this peer und us is ready to sync.
enum GNUNET_GenericReturnValue sync_ready
Is this peer already ready to sync.
struct GNUNET_TIME_RelativeNBO rtt_average
The average RTT for the peer to communicate with.
Handle to a node in a heap.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
type for session keys
type for session keys
Type of a nonce used for challenges.
struct GNUNET_ShortHashCode value
The value of the nonce.
Private ECC key encoded for transmission.
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Context for building (or parsing) HELLO URIs.
Definition hello-uri.c:185
Context for parsing HELLOs.
Definition hello-uri.c:233
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Message handler for a specific message type.
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
Handle to the PEERSTORE service.
Context for a iterate request.
Context for a store request.
Context for a add hello uri request.
A handle for the PILS service.
Definition pils_api.c:86
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:141
Handle to a client that is connected to a service.
Definition service.c:249
Handle to a service.
Definition service.c:116
Handle for the service.
A 256-bit hashcode.
Struct wrapping information we use for starting the burst.
struct VirtualLink * vl
The VirtualLink of the peer to which we like to burst with.
struct GNUNET_TIME_Relative delay
The delay - calculate from the RTT and which peer was ready to sync first, after we will start the bu...
unsigned int sync_ready
We are ready to start the burst.
struct GNUNET_TIME_Relative rtt
The average RTT between the peers.
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 and in network byte order.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Add address to the list.
Definition transport.h:289
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
Definition transport.h:293
struct GNUNET_TIME_RelativeNBO expiration
When does the address expire?
Definition transport.h:303
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:308
uint32_t aid
Address identifier (used during deletion).
Definition transport.h:298
Add queue to the transport.
Definition transport.h:403
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:422
uint32_t mtu
Maximum transmission unit, in NBO.
Definition transport.h:427
uint64_t q_len
Queue length, in NBO.
Definition transport.h:433
uint32_t qid
Queue identifier (used to identify the queue).
Definition transport.h:412
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:417
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
Definition transport.h:407
uint32_t cs
An enum GNUNET_TRANSPORT_ConnectionStatus in NBO.
Definition transport.h:443
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
Definition transport.h:269
uint32_t cc
NBO encoding of enum GNUNET_TRANSPORT_CommunicatorCharacteristics
Definition transport.h:274
uint32_t can_burst
The communicator can do burst msgs.
Definition transport.h:279
Message from transport to communicator passing along a backchannel message from the given peer pid.
Definition transport.h:657
struct GNUNET_PeerIdentity pid
Origin peer.
Definition transport.h:672
Message from communicator to transport service asking for transmission of a backchannel message with ...
Definition transport.h:628
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL.
Definition transport.h:632
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:642
Communicator tells transport how queue creation went down.
Definition transport.h:547
uint32_t request_id
Unique ID for the request.
Definition transport.h:557
Transport tells communicator that it wants a new queue.
Definition transport.h:523
uint32_t request_id
Unique ID for the request.
Definition transport.h:532
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:537
Remove address from the list.
Definition transport.h:318
uint32_t aid
Address identifier.
Definition transport.h:327
Remove queue, it is no longer available.
Definition transport.h:501
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:515
uint32_t qid
Address identifier.
Definition transport.h:510
Transport informs us about being done with an incoming message.
Definition transport.h:376
struct GNUNET_PeerIdentity sender
Sender identifier of the original message.
Definition transport.h:395
uint64_t fc_id
Which message is being ACKed?
Definition transport.h:390
uint32_t reserved
Reserved (0)
Definition transport.h:385
Inform transport about an incoming message.
Definition transport.h:335
struct GNUNET_PeerIdentity neighbour_sender
Direct neighbour sender identifier.
Definition transport.h:365
struct GNUNET_TIME_RelativeNBO expected_address_validity
How long does the communicator believe the address on which the message was received to remain valid?
Definition transport.h:355
struct GNUNET_PeerIdentity sender
Sender identifier.
Definition transport.h:360
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
Definition transport.h:339
uint32_t fc_on
Do we use flow control or not?
Definition transport.h:344
uint64_t fc_id
64-bit number to identify the matching ACK.
Definition transport.h:349
struct GNUNET_MQ_Handle * mq
Queue to talk to the transport service.
Request a one-shot listing of our virtual links.
Definition transport.h:783
State of one virtual link.
Definition transport.h:805
uint32_t stalled
Number of messages whose flow control ACK we are withholding because core_recv_window is exhausted.
Definition transport.h:849
struct GNUNET_TIME_AbsoluteNBO last_fc_transmission
When did we last send a flow control message?
Definition transport.h:910
uint32_t fc_retransmit_count
Number of flow control retransmissions of the running task.
Definition transport.h:859
uint32_t num_queues
Number of queues to the neighbour, 0 if route is GNUNET_TRANSPORT_LINK_ROUTE_DV.
Definition transport.h:836
uint64_t incoming_fc_window_size_ram
RAM currently held for this link.
Definition transport.h:869
uint64_t incoming_fc_window_size_used
How much of incoming_fc_window_size the other peer used.
Definition transport.h:879
uint32_t pending
Number of messages queued for transmission to target.
Definition transport.h:854
int64_t incoming_fc_window_size_loss
Current estimate of the message loss rate for the sender.
Definition transport.h:885
struct GNUNET_TIME_RelativeNBO other_rtt
RTT over all DV paths, as calculated by the target.
Definition transport.h:905
uint64_t outbound_fc_window_size
Window the other peer granted us.
Definition transport.h:890
uint64_t outbound_fc_window_size_used
How much of outbound_fc_window_size we used.
Definition transport.h:895
uint64_t incoming_fc_window_size
Window we last granted the other peer.
Definition transport.h:874
uint32_t route
An ‘enum GNUNET_TRANSPORT_LinkRoute’ in NBO.
Definition transport.h:824
uint32_t distance
Distance of the DV path, 0 if route is GNUNET_TRANSPORT_LINK_ROUTE_DIRECT.
Definition transport.h:830
struct GNUNET_PeerIdentity target
Peer at the other end of the link.
Definition transport.h:814
struct GNUNET_TIME_RelativeNBO last_fc_rtt
RTT of the last flow control exchange.
Definition transport.h:900
uint32_t confirmed
GNUNET_YES if the link is confirmed, i.e.
Definition transport.h:819
int32_t core_recv_window
How many more messages we may hand to CORE before it must acknowledge them.
Definition transport.h:843
uint64_t available_fc_window_size
RAM we are willing to spend on this link.
Definition transport.h:864
uint32_t num_msg_pending
Messages pending (in NBO).
Definition transport.h:768
struct GNUNET_PeerIdentity peer
Target identifier.
Definition transport.h:746
struct GNUNET_TIME_AbsoluteNBO valid_until
Definition transport.h:752
struct GNUNET_TIME_AbsoluteNBO last_validation
Definition transport.h:751
uint32_t num_bytes_pending
Bytes pending (in NBO).
Definition transport.h:773
struct GNUNET_TIME_AbsoluteNBO next_validation
Definition transport.h:753
uint32_t nt
Network type (an enum GNUNET_NetworkType in NBO).
Definition transport.h:741
struct GNUNET_TIME_RelativeNBO rtt
Current round-trip time estimate.
Definition transport.h:758
uint32_t cs
Connection status (in NBO).
Definition transport.h:763
Request to start monitoring.
Definition transport.h:710
Inform transport that message was sent.
Definition transport.h:594
uint32_t status
Success (GNUNET_OK), failure (GNUNET_SYSERR).
Definition transport.h:603
uint64_t mid
Message ID of the original message.
Definition transport.h:608
uint32_t qid
Queue ID for the queue which was used to send the message.
Definition transport.h:613
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:618
Inform communicator about transport's desire to send a message.
Definition transport.h:565
uint32_t qid
Which queue should we use?
Definition transport.h:574
uint64_t mid
Message ID, used for flow control.
Definition transport.h:579
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
Definition transport.h:569
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:584
Message from transport to communicator to start a burst.
Definition transport.h:682
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST.
Definition transport.h:686
struct GNUNET_TIME_RelativeNBO rtt
Definition transport.h:693
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:691
A UUID, a 128 bit "random" value.
Message used to notify the transport API about a message received from the network.
Definition transport.h:145
struct GNUNET_PeerIdentity peer
Which peer sent the message?
Definition transport.h:154
Another peer attempted to talk to us, we should try to establish a connection in the other direction.
struct IncomingRequest * next
Kept in a DLL.
struct IncomingRequest * prev
Kept in a DLL.
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
When did we launch this DV learning activity?
struct LearnLaunchEntry * next
Kept (also) in a DLL sorted by launch time.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge that uniquely identifies this activity.
struct LearnLaunchEntry * prev
Kept (also) in a DLL sorted by launch time.
struct GNUNET_TIME_Absolute launch_time
When did we transmit the DV learn message (used to calculate RTT) and determine freshness of paths le...
Closure for report_link().
int include_unconfirmed
Also report links that are not confirmed?
struct TransportClient * tc
Client asking for the listing.
Unique identifier we attach to a message.
uint64_t uuid
Unique value, generated by incrementing the message_uuid_ctr of struct Neighbour.
Details about what to notify monitors about.
enum GNUNET_TRANSPORT_ConnectionStatus cs
Connection status.
struct GNUNET_TIME_Absolute last_validation
struct GNUNET_TIME_Absolute next_validation
struct GNUNET_TIME_Absolute valid_until
struct GNUNET_TIME_Relative rtt
Current round-trip time estimate.
uint32_t num_msg_pending
Messages pending.
uint32_t num_bytes_pending
Bytes pending.
Closure for dv_neighbour_selection and dv_neighbour_transmission.
const struct TransportDVLearnMessage * dvl
Original message we received.
struct GNUNET_TIME_Absolute in_time
Time we received the message.
const struct DVPathEntryP * hops
The hops taken.
uint16_t bi_history
Bitmap of bidirectional connections encountered.
unsigned int num_eligible
Number of peers eligible for selection.
unsigned int num_selections
Number of peers that were selected for forwarding.
uint32_t selections[MAX_DV_DISCOVERY_SELECTION]
Offsets of the selected peers.
uint16_t nhops
Number of hops in hops.
A neighbour that at least one communicator is connected to.
size_t size_of_global_addresses
Size of all global natted addresses for this neighbour.
struct DistanceVectorHop * dv_tail
Tail of MDLL of DV hops that have this neighbour as next hop.
struct GNUNET_CONTAINER_MultiPeerMap * natted_addresses
Map of struct TransportGlobalNattedAddress for this neighbour.
struct GNUNET_TIME_Absolute last_dv_learn_monotime
Latest DVLearn monotonic time seen from this peer.
int dv_monotime_available
Do we have the latest value for last_dv_learn_monotime from PEERSTORE yet, or are we still waiting fo...
unsigned int number_of_addresses
Number of global natted addresses for this neighbour.
struct Queue * queue_tail
Tail of DLL of queues to this peer.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation to store this pid's last_dv_learn_monotime.
struct DistanceVectorHop * dv_head
Head of MDLL of DV hops that have this neighbour as next hop.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct Queue * queue_head
Head of DLL of queues to this peer.
struct GNUNET_TIME_Absolute last_inbound
When did a communicator last hand us a message that this peer sent us directly (i....
struct GNUNET_PeerIdentity pid
Which peer is this about?
enum GNUNET_GenericReturnValue is_global_natted
A queue of this neighbour has a global natted address.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch last_dv_learn_monotime information from the PEERSTORE,...
Message used to notify the transport service about a message to be transmitted to another peer.
Definition transport.h:231
uint32_t priority
An enum GNUNET_MQ_PriorityPreferences in NBO.
Definition transport.h:240
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND.
Definition transport.h:235
struct GNUNET_PeerIdentity peer
Which peer should receive the message?
Definition transport.h:254
Information per peer and request.
struct GNUNET_BANDWIDTH_Value32NBO bw
How much bandwidth would this tc like to see?
struct TransportClient * tc
Client responsible for the request.
struct GNUNET_SCHEDULER_Task * retry_task
Task that keeps trying to bring the link to pid up for as long as this request exists.
enum GNUNET_MQ_PriorityPreferences pk
What kind of performance preference does this tc have?
struct GSF_PendingRequest * pr
Handle to generic request (generic: from peer or local client).
struct GNUNET_TIME_Relative retry_backoff
Current delay between two runs of retry_task, growing from SUGGEST_RETRY_MIN to SUGGEST_RETRY_MAX.
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
Data structure kept when we are waiting for an acknowledgement.
struct AcknowledgementUUIDP ack_uuid
Unique identifier for this transmission operation.
unsigned int num_send
How often the PendingMessage was send via the Queue of this PendingAcknowledgement.
struct PendingAcknowledgement * next_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingMessage * pm
Message that was transmitted, may be NULL if the message was ACKed via another channel.
struct PendingAcknowledgement * next_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
struct PendingAcknowledgement * next_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct GNUNET_TIME_Absolute transmission_time
Time of the transmission, for RTT calculation.
struct Queue * queue
Queue used for transmission, NULL if the queue has been destroyed (which may happen before we get an ...
struct DistanceVectorHop * dvh
Distance vector path chosen for this transmission, NULL if transmission was to a direct neighbour OR ...
uint16_t message_size
Number of bytes of the original message (to calculate bandwidth).
struct PendingAcknowledgement * prev_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct PendingAcknowledgement * prev_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingAcknowledgement * prev_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
Context for select_best_pending_from_link().
struct GNUNET_TIME_Relative to_early_retry_delay
When will we try to transmit the message again for which it was to early to retry.
struct PendingMessage * best
Set to the best message that was found, NULL for none.
int to_early
There are pending messages, but it was to early to send one of them.
unsigned int consideration_counter
Number of pending messages we seriously considered this time.
struct DistanceVectorHop * dvh
DVH that best should take, or NULL for direct transmission.
size_t real_overhead
What is the estimated total overhead for this message?
unsigned int frags_in_flight
There is a pending messages we are sending fragments at the moment.
int frag
Did we have to fragment?
int relb
Did we have to reliability box?
List containing all messages that are yet to be send.
struct PendingMessage * tail_frag
Tail of a MDLL of fragments created for this core message.
struct PendingMessage * frag_parent
Our parent in the fragmentation tree.
enum GNUNET_MQ_PriorityPreferences prefs
Preferences for this message.
struct TransportClient * client
Client that issued the transmission request, if pmt is PMT_CORE.
struct QueueEntry * qe
Set to non-NULL value if this message is currently being given to a communicator and we are awaiting ...
struct MessageUUIDP msg_uuid
UUID to use for this message (used for reassembly of fragments, only initialized if msg_uuid_set is G...
struct PendingMessage * head_frag
Head of a MDLL of fragments created for this core message.
uint16_t bytes_msg
Size of the original message.
enum PendingMessageType pmt
Type of the pending message.
struct PendingMessage * prev_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
struct PendingMessage * prev_vl
Kept in a MDLL of messages for this vl.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs for this pending message.
struct PendingMessage * next_vl
Kept in a MDLL of messages for this vl.
struct VirtualLink * vl
Target of the request (always the ultimate destination!).
struct PendingAcknowledgement * pa_head
Head of DLL of PAs for this pending message.
struct DistanceVectorHop * used_dvh
If pmt is of type PMT_DV_BOX we store the used path here.
int16_t msg_uuid_set
GNUNET_YES once msg_uuid was initialized
uint32_t frags_in_flight_round
The round we are (re)-sending fragments.
struct PendingMessage * next_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
uint32_t frags_in_flight
Are we sending fragments at the moment?
uint16_t frag_off
Offset at which we should generate the next fragment.
struct PendingMessage * next_frag
Kept in a MDLL of messages from this cpm (if pmt is #PMT_FRAGMENT_BOx)
uint64_t logging_uuid
UUID we use to identify this message in our logs.
uint16_t frag_count
How many fragments do we have?
struct PendingMessage * prev_frag
Kept in a MDLL of messages from this cpm (if pmt is PMT_FRAGMENT_BOX)
struct PendingMessage * bpm
This message, reliability or DV-boxed.
int16_t client_credited
GNUNET_YES once the CORE send window credit for this message has been returned to client.
struct GNUNET_TIME_Absolute next_attempt
What is the earliest time for us to retry transmission of this message?
struct GNUNET_TIME_Absolute timeout
At what time should we give up on the transmission (and no longer retry)?
struct GNUNET_PeerIdentity target
In case of a not validated neighbour, we store the target peer.
Performance data for a transmission possibility.
struct GNUNET_TIME_Relative aged_rtt
Weighted average for the RTT.
struct TransmissionHistoryEntry the[4]
Historic performance data, using a ring buffer of::GOODPUT_AGING_SLOTS entries.
unsigned int last_age
What was the last age when we wrote to the? Used to clear old entries when the age advances.
Helper context struct for HELLO update.
struct GNUNET_TIME_Absolute et
Signature expiration.
struct AddressListEntry * ale
The ale to update.
struct PilsRequest * req
Any pending PILS requests.
struct GNUNET_PILS_Operation * op
The pils operation.
struct PilsRequest * next
DLL.
struct PilsRequest * prev
DLL.
Entry identifying transmission in one of our struct Queue which still awaits an ACK.
struct QueueEntry * next
Kept as a DLL.
struct QueueEntry * prev
Kept as a DLL.
struct GNUNET_TIME_Absolute creation_timestamp
Timestamp this QueueEntry was created.
uint64_t mid
Message ID used for this message with the queue used for transmission.
struct PendingMessage * pm
Pending message this entry is for, or NULL for none.
struct Queue * queue
Queue this entry is queued with.
Closure for check_connection_quality.
unsigned int k
Decremented for each queue, for selection of the k-th queue in q.
struct Queue * q
Set to the k'th queue encountered.
unsigned int num_queues
Set to the total number of queues encountered.
unsigned int quality_count
Set to the number of quality queues encountered.
Handle for a queue.
uint32_t qid
Unique identifier of this queue with the communicator.
struct QueueEntry * queue_tail
End of DLL of unacked transmission requests.
struct Queue * prev_client
Kept in a MDLL.
unsigned int queue_length
Length of the DLL starting at queue_head.
uint32_t num_msg_pending
Messages pending.
struct GNUNET_PEERSTORE_Monitor * mo
Handle for an operation to iterate through all hellos to compare the hello addresses with address whi...
uint64_t q_capacity
Capacity of the queue.
struct Queue * next_neighbour
Kept in a MDLL.
uint32_t num_bytes_pending
Bytes pending.
uint32_t priority
Queue priority.
struct Neighbour * neighbour
Which neighbour is this queue for?
int idle
Set to GNUNET_YES if this queue is idle waiting for some virtual link to give it a pending message.
struct Queue * prev_neighbour
Kept in a MDLL.
struct PerformanceData pd
Performance data for this queue.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_SCHEDULER_Task * transmit_task
Task scheduled for the time when this queue can (likely) transmit the next message.
struct QueueEntry * queue_head
Head of DLL of unacked transmission requests.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used this queue.
struct TransportClient * tc
Which communicator offers this queue?
struct Queue * next_client
Kept in a MDLL.
enum GNUNET_GenericReturnValue is_global_natted
Set to GNUNET_YES, if this queues address is a global natted one.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
uint32_t mtu
Maximum transmission unit supported by this queue.
unsigned int unlimited_length
Is this queue of unlimited length.
enum GNUNET_TRANSPORT_ConnectionStatus cs
The connection status of this queue.
uint64_t mid_gen
Message ID generator for transmissions on this queue to the communicator.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used this queue.
const char * address
Address served by the queue.
Information we keep for a message that we are reassembling.
struct GNUNET_CONTAINER_HeapNode * hn
Entry in the reassembly heap (sorted by expiration).
struct GNUNET_TIME_Absolute last_frag
Time we received the last fragment.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct VirtualLink * virtual_link
Which neighbour is this context for?
uint8_t * bitfield
Bitfield with msg_size bits representing the positions where we have received fragments.
uint16_t msg_size
How big is the message we are reassembling in total?
struct GNUNET_TIME_Absolute reassembly_timeout
At what time will we give up reassembly of this message?
uint16_t msg_missing
How many bytes of the message are still missing? Defragmentation is complete when msg_missing == 0.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:207
struct GNUNET_PeerIdentity peer
Which peer can CORE handle more from now?
Definition transport.h:222
uint32_t increase_window_delta
Number of messages by which to increase the window, greater or equal to one.
Definition transport.h:217
We got an address of another peer, TRANSPORT service should validate it.
Definition transport.h:979
Entry for the ring buffer caching messages send to core, when virtual link is available.
struct CommunicatorMessageContext * cmc
Communicator context for this ring buffer entry.
struct GNUNET_MessageHeader * mh
The message in this entry.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:163
struct GNUNET_PeerIdentity peer
Which peer can send more now?
Definition transport.h:197
Binary block we sign when we sign an address.
struct GNUNET_TIME_AbsoluteNBO mono_time
When was the address generated.
struct GNUNET_HashCode addr_hash GNUNET_PACKED
Hash of the address.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS.
Message from the transport service to the library asking to check if both processes agree about this ...
Definition transport.h:63
Information we keep per GOODPUT_AGING_SLOTS about historic (or current) transmission performance.
uint64_t bytes_received
Number of bytes received and acknowledged by the other peer in the interval.
uint64_t bytes_sent
Number of bytes actually sent in the interval.
Outer layer of an encapsulated backchannel message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
Client connected to the transport service.
enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc
Characteristics of this communicator.
struct PendingMessage * pending_msg_head
Head of list of messages pending for this client, sorted by transmission time ("next_attempt" + possi...
enum ClientType type
What type of client is this?
struct AddressListEntry * addr_tail
Tail of list of the addresses of this peer offered by this communicator.
union TransportClient::@68 details
struct TransportClient * next
Kept in a DLL.
struct GNUNET_MQ_Handle * mq
Message queue to the client.
struct GNUNET_SCHEDULER_Task * free_queue_entry_task
Task to check for timed out QueueEntry.
struct PendingMessage * pending_msg_tail
Tail of list of messages pending for this client.
struct TransportClient::@68::@72 application
Information for type CT_APPLICATION.
struct TransportClient::@68::@70 monitor
Information for type CT_MONITOR.
struct Queue * queue_head
Head of DLL of queues offered by this communicator.
struct AddressListEntry * addr_head
Head of list of the addresses of this peer offered by this communicator.
struct TransportClient::@68::@69 core
Information for type CT_CORE.
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of requests for peers the given client application would like to see connections for.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct TransportClient * prev
Kept in a DLL.
struct TransportClient::@68::@71 communicator
Information for type CT_COMMUNICATOR.
char * address_prefix
If type is CT_COMMUNICATOR, this communicator supports communicating using these addresses.
struct Queue * queue_tail
Tail of DLL of queues offered by this communicator.
unsigned int total_queue_length
Number of queue entries in all queues to this communicator.
int one_shot
Is this a one-shot monitor?
struct GNUNET_PeerIdentity peer
Peer identity to monitor the addresses of.
enum GNUNET_GenericReturnValue can_burst
Can be used for burst messages.
struct GNUNET_TIME_RelativeNBO ack_delay
How long was the ACK delayed for generating cumulative ACKs? Used to calculate the correct network RT...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
struct GNUNET_TIME_Absolute receive_time
When did we receive the message we are ACKing? Used to calculate the delay we introduced by cummulati...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
Outer layer of an encapsulated message send over multiple hops.
struct GNUNET_CRYPTO_AeadNonce iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX.
uint16_t num_hops
Number of hops this messages includes.
uint16_t orig_size
Size this msg had initially.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
struct GNUNET_CRYPTO_AeadMac mac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
uint16_t total_hops
Number of total hops this messages travelled.
uint32_t without_fc
Flag if the payload is a control message.
Plaintext of the variable-size payload that is encrypted within a struct TransportBackchannelEncapsul...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature of the sender over an GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Current monotonic time of the sending transport service.
struct GNUNET_PeerIdentity sender
Sender's peer identity.
Internal message used by transport for distance vector learning.
struct GNUNET_PeerIdentity initiator
Identity of the peer that started this learning activity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN.
struct GNUNET_TIME_RelativeNBO non_network_delay
Peers receiving this message and delaying forwarding to other peers for any reason should increment t...
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EddsaSignature init_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
uint16_t num_hops
Number of hops this messages has travelled, in NBO.
uint16_t bidirectional
Bitmask of the last 16 hops indicating whether they are confirmed available (without DV) in both dire...
Message for Transport-to-Transport Flow control.
uint64_t outbound_window_size
Latest flow control window size we learned from the other peer, in bytes, in NBO.
uint32_t number_of_addresses
Number of TransportGlobalNattedAddress following the struct.
uint64_t inbound_window_size
Flow control window size in bytes, in NBO.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender.
uint32_t seq
Sequence number of the flow control message.
uint32_t size_of_addresses
Size of all the addresses attached to all TransportGlobalNattedAddress.
uint64_t outbound_sent
How many bytes has the sender sent that count for flow control at this time.
struct GNUNET_TIME_RelativeNBO rtt
Average RTT for the DistanceVector of the VirtualLink we tell the target.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL.
uint32_t sync_ready
We tell the target, if we are ready to start the burst.
Outer layer of an encapsulated fragmented application message.
uint16_t frag_off
Offset of this fragment in the overall message.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct AcknowledgementUUIDP ack_uuid
Unique ID of this fragment (and fragment transmission!).
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT.
uint16_t msg_size
Total size of the message that is being fragmented.
struct TransportGlobalNattedAddress * tgna
The struct TransportGlobalNattedAddress to set.
uint32_t address_length
Length of the address following the struct in NBO.
Confirmation that the receiver got a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
uint32_t ack_counter
Counter of ACKs transmitted by the sender to us.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK.
Outer layer of an encapsulated unfragmented application message sent over an unreliable channel.
uint32_t ack_countdown
Number of messages still to be sent before a commulative ACK is requested.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
struct AcknowledgementUUIDP ack_uuid
Unique ID of the message used for signalling receipt of messages sent over possibly unreliable channe...
Message send to another peer to validate that it can indeed receive messages at a particular address.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge to be signed by the receiving peer.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender, to be copied into the reply to allow sender to calculate RTT.
Message signed by a peer to confirm that it can indeed receive messages at a particular address.
struct GNUNET_TIME_RelativeNBO validity_duration
How long does the sender believe the address on which the challenge was received to remain valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge signed by the receiving peer.
Message send to a peer to respond to a #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
The challenge that was signed by the receiving peer.
struct GNUNET_CRYPTO_EddsaSignature signature
The peer's signature matching the GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
struct GNUNET_PEERSTORE_StoreHelloContext * sc
State we keep for validation activities.
struct GNUNET_TIME_Absolute valid_until
How long did the peer claim this address to be valid? Capped at minimum of MAX_ADDRESS_VALID_UNTIL re...
struct GNUNET_PeerIdentity pid
For which peer is address to be validated (or possibly valid)? Serves as key in the validation_map.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
common internal definitions for transport service