GNUnet 0.28.1-dev.4-8-g14b9efcb0
 
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
224#define MAX_DV_LEARN_PENDING 64
225
229#define MAX_DV_PATHS_TO_TARGET 3
230
237#define PILS_FEED_ADDRESSES_DELAY \
238 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
239
245#define DELAY_WARN_THRESHOLD \
246 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
247
252#define DV_FORWARD_TIMEOUT \
253 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
254
258#define DEFAULT_ACK_WAIT_DURATION \
259 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
260
266#define DV_QUALITY_RTT_THRESHOLD \
267 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
268
273#define DV_PATH_VALIDITY_TIMEOUT \
274 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
275
280#define BACKCHANNEL_INACTIVITY_TIMEOUT \
281 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
282
287#define DV_PATH_DISCOVERY_FREQUENCY \
288 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
289
293#define EPHEMERAL_VALIDITY \
294 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
295
299#define REASSEMBLY_EXPIRATION \
300 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
301
308#define MAX_REASSEMBLY_CONTEXTS 32
309
314#define FAST_VALIDATION_CHALLENGE_FREQ \
315 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
316
320#define MAX_VALIDATION_CHALLENGE_FREQ \
321 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
322
328#define ACK_CUMMULATOR_TIMEOUT \
329 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
330
335#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
336
341#define DV_LEARN_QUALITY_THRESHOLD 100
342
346#define MAX_ADDRESS_VALID_UNTIL \
347 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
348
352#define ADDRESS_VALIDATION_LIFETIME \
353 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
354
371#define NEIGHBOUR_LIVENESS_TIMEOUT \
372 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
373
402#define FC_KEEPALIVE_INTERVAL \
403 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, \
404 2)
405
412#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
413
420#define VALIDATION_RTT_BUFFER_FACTOR 3
421
428#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
429
435#define QUEUE_LENGTH_LIMIT 32
436
440#define QUEUE_ENTRY_TIMEOUT \
441 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
442
447#define RTT_DIFF \
448 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
449
456#define SHUTDOWN_CLIENT_GRACE_PERIOD \
457 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
458
460
465{
471};
472
473
484
489{
494
495 /* Followed by *another* message header which is the message to
496 the communicator */
497
498 /* Followed by a 0-terminated name of the communicator */
499};
500
501
539
540
546{
551
557
569
570 /* Followed by a `struct GNUNET_MessageHeader` with a message
571 for the target peer */
572};
573
574
601
602
621
622
631{
636
642
643 /* followed by any number of `struct TransportCummulativeAckPayloadP`
644 messages providing ACKs */
645};
646
647
683
684
728
729
768
769
787
788
803{
808
814
824
831
845
851
856
861
862 /* Followed by @e num_hops `struct DVPathEntryP` values,
863 excluding the initiator of the DV trace; the last entry is the
864 current sender; the current peer must not be included. */
865};
866
867
891{
896
901
909
916
922
929
936
943
944 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
945 excluding the @e origin and the current peer, the last must be
946 the ultimate target; if @e num_hops is zero, the receiver of this
947 message is the ultimate target. */
948
949 /* Followed by encrypted, variable-size payload, which
950 must begin with a `struct TransportDVBoxPayloadP` */
951
952 /* Followed by the actual message, which itself must not be a
953 a DV_LEARN or DV_BOX message! */
954};
955
956
984
985
1008
1009
1049
1051{
1056
1057 /* Followed by @e address_length bytes of the address. */
1058};
1059
1069{
1074
1083
1089
1096
1106
1116
1121
1126
1131
1137
1138 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1139};
1140
1142
1143/* GNUNET_NETWORK_STRUCT_BEGIN/_END expand to nothing; only the per-member
1144 GNUNET_PACKED keeps these layouts free of compiler padding. Pin the sizes
1145 so that adding an unpacked or non-fixed-width member cannot silently put
1146 padding bytes -- i.e. uninitialised stack -- on the wire again. */
1148
1157
1158
1163{
1168
1173
1178
1183
1187 CT_APPLICATION = 4
1189
1190
1224
1225
1252
1253
1259{
1263 uint64_t bytes_sent;
1264
1270};
1271
1272
1295
1296
1300struct TransportClient;
1301
1305struct Neighbour;
1306
1311struct DistanceVector;
1312
1317struct Queue;
1318
1322struct PendingMessage;
1323
1327struct DistanceVectorHop;
1328
1337struct VirtualLink;
1338
1339
1394
1395
1411
1412
1417{
1422
1427
1432
1436 uint16_t size;
1437
1444 uint16_t isize;
1445};
1446
1447
1452{
1458
1463
1468
1476 uint8_t *bitfield;
1477
1482
1488
1492 uint16_t msg_size;
1493
1498 uint16_t msg_missing;
1499
1500 /* Followed by @e msg_size bytes of the (partially) defragmented original
1501 * message */
1502
1503 /* Followed by @e bitfield data */
1504};
1505
1506
1516{
1521
1528
1535
1540
1546
1552
1557 unsigned int cmc_count;
1558
1565
1570
1575
1580
1585
1593
1599
1605
1610
1615
1620
1625 unsigned int confirmed;
1626
1630 struct Neighbour *n;
1631
1636
1643
1650
1659
1665
1671
1676
1682
1691
1699
1706
1715
1728
1734
1741
1752
1757 uint32_t fc_seq_gen;
1758
1764 uint32_t last_fc_seq;
1765
1778
1783};
1784
1785
1883
1884
1964
1965
2024
2025
2036{
2041
2046
2050 struct Queue *queue;
2051
2056
2060 uint64_t mid;
2061
2066};
2067
2068
2073struct Queue
2074{
2079
2084
2089
2094
2099
2104
2109
2114
2119
2124
2128 const char *address;
2129
2133 unsigned int unlimited_length;
2134
2140
2149
2154
2160
2165 uint64_t mid_gen;
2166
2170 uint32_t qid;
2171
2175 uint32_t mtu;
2176
2181
2186
2190 unsigned int queue_length;
2191
2195 uint64_t q_capacity;
2196
2200 uint32_t priority;
2201
2206
2211
2216 int idle;
2217
2222};
2223
2224
2315
2316
2343
2344
2348struct PeerRequest
2349{
2354
2359
2364
2371
2376};
2377
2378
2404
2405
2432struct PendingMessage
2433{
2438
2443
2448
2453
2459
2465
2470
2475
2481
2487
2492
2502
2507
2512
2517
2522
2527
2532
2538
2544
2549
2555
2560
2564 uint16_t bytes_msg;
2565
2569 uint16_t frag_off;
2570
2575
2580
2584 uint16_t frag_count;
2585
2590
2599
2600 /* Followed by @e bytes_msg to transmit */
2601};
2602
2603
2620
2621
2662
2663
2669
2670
2750
2751
2756{
2761
2766
2771
2776
2781
2782 union
2783 {
2787 struct
2788 {
2794
2800
2804 struct
2805 {
2812
2818
2819
2823 struct
2824 {
2830
2835
2840
2846
2852
2859
2864
2869
2874
2876
2880 struct
2881 {
2889};
2890
2891
2897{
2903
2911
2917
2924 struct GNUNET_TIME_Absolute first_challenge_use;
2925
2932 struct GNUNET_TIME_Absolute last_challenge_use;
2933
2941 struct GNUNET_TIME_Absolute next_challenge;
2942
2951 struct GNUNET_TIME_Relative challenge_backoff;
2952
2957 struct GNUNET_TIME_Relative validation_rtt;
2958
2966 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2967
2971 struct GNUNET_HashCode hc;
2972
2976 struct GNUNET_SCHEDULER_Task *revalidation_task;
2977
2981 char *address;
2982
2988 struct GNUNET_CONTAINER_HeapNode *hn;
2989
2995
3001 uint32_t last_window_consum_limit;
3002
3007 int awaiting_queue;
3008};
3009
3010
3068
3073
3077static unsigned int ring_buffer_head;
3078
3082static unsigned int is_ring_buffer_full;
3083
3088
3092static unsigned int ring_buffer_dv_head;
3093
3097static unsigned int is_ring_buffer_dv_full;
3098
3103
3108
3113
3118
3125
3131
3136
3142
3148
3154
3160
3166
3172
3178
3184
3189
3193static struct LearnLaunchEntry *lle_head = NULL;
3194
3198static struct LearnLaunchEntry *lle_tail = NULL;
3199
3206
3211
3216
3221
3225struct PilsRequest
3226{
3230 struct PilsRequest *prev;
3231
3235 struct PilsRequest *next;
3236
3240 struct GNUNET_PILS_Operation *op;
3241};
3242
3247
3252
3277static enum GNUNET_GenericReturnValue
3279 struct GNUNET_CRYPTO_EddsaSignature *sig)
3280{
3282
3284 if (NULL == my_private_key)
3285 {
3286 /* #run() enables local key access, so this means the key on disk does
3287 not match the identity PILS announced, or no identity is known yet. */
3289 "No private key for our peer identity, cannot sign\n");
3291 "# signatures failed (no private key)",
3292 1,
3293 GNUNET_NO);
3294 return GNUNET_SYSERR;
3295 }
3296 return GNUNET_CRYPTO_eddsa_sign_ (my_private_key, purpose, sig);
3297}
3298
3299
3304
3309
3314
3319
3326
3331
3335static unsigned int ir_total;
3336
3340static unsigned long long logging_uuid_gen;
3341
3346
3356
3361static int in_shutdown;
3362
3367
3374
3376
3378
3389static unsigned int
3391{
3392 struct GNUNET_TIME_Absolute now;
3393
3394 now = GNUNET_TIME_absolute_get ();
3395 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3396}
3397
3398
3404static void
3406{
3408 GNUNET_assert (ir_total > 0);
3409 ir_total--;
3410 if (NULL != ir->nc)
3412 ir->nc = NULL;
3413 GNUNET_free (ir);
3414}
3415
3416
3422static void
3424{
3425 struct Queue *q = pa->queue;
3426 struct PendingMessage *pm = pa->pm;
3427 struct DistanceVectorHop *dvh = pa->dvh;
3428
3430 "free_pending_acknowledgement\n");
3431 if (NULL != q)
3432 {
3433 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3434 pa->queue = NULL;
3435 }
3436 if (NULL != pm)
3437 {
3439 "remove pa from message\n");
3441 "remove pa from message %" PRIu64 "\n",
3442 pm->logging_uuid);
3444 "remove pa from message %u\n",
3445 pm->pmt);
3447 "remove pa from message %s\n",
3449 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3450 pa->pm = NULL;
3451 }
3452 if (NULL != dvh)
3453 {
3454 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3455 pa->dvh = NULL;
3456 }
3459 &pa->ack_uuid.value,
3460 pa));
3461 GNUNET_free (pa);
3462}
3463
3464
3473static void
3475{
3476 struct PendingMessage *frag;
3477
3478 while (NULL != (frag = root->head_frag))
3479 {
3480 struct PendingAcknowledgement *pa;
3481
3482 free_fragment_tree (frag);
3483 while (NULL != (pa = frag->pa_head))
3484 {
3485 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3486 pa->pm = NULL;
3487 }
3488 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3489 if (NULL != frag->qe)
3490 {
3491 GNUNET_assert (frag == frag->qe->pm);
3492 frag->qe->pm = NULL;
3493 }
3495 "Free frag %p\n",
3496 frag);
3497 GNUNET_free (frag);
3498 }
3499}
3500
3501
3509static void
3511{
3512 struct TransportClient *tc = pm->client;
3513 struct VirtualLink *vl = pm->vl;
3514 struct PendingAcknowledgement *pa;
3515
3517 "Freeing pm %p\n",
3518 pm);
3519 if (NULL != tc)
3520 {
3522 tc->details.core.pending_msg_head,
3523 tc->details.core.pending_msg_tail,
3524 pm);
3525 }
3526 if ((NULL != vl) && (NULL == pm->frag_parent))
3527 {
3529 "Removing pm %" PRIu64 "\n",
3530 pm->logging_uuid);
3532 vl->pending_msg_head,
3533 vl->pending_msg_tail,
3534 pm);
3535 }
3536 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3537 {
3538 struct PendingMessage *root = pm->frag_parent;
3539
3540 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3541 root = root->frag_parent;
3542
3543 root->frag_count--;
3544 }
3545 while (NULL != (pa = pm->pa_head))
3546 {
3547 if (NULL == pa)
3549 "free pending pa null\n");
3550 if (NULL == pm->pa_tail)
3552 "free pending pa_tail null\n");
3553 if (NULL == pa->prev_pa)
3555 "free pending pa prev null\n");
3556 if (NULL == pa->next_pa)
3558 "free pending pa next null\n");
3559 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3560 pa->pm = NULL;
3561 }
3562
3563 free_fragment_tree (pm);
3564 if (NULL != pm->qe)
3565 {
3566 GNUNET_assert (pm == pm->qe->pm);
3567 pm->qe->pm = NULL;
3568 }
3569 if (NULL != pm->bpm)
3570 {
3571 free_fragment_tree (pm->bpm);
3572 if (NULL != pm->bpm->qe)
3573 {
3574 struct QueueEntry *qe = pm->bpm->qe;
3575
3576 qe->pm = NULL;
3577 }
3578 GNUNET_free (pm->bpm);
3579 }
3580
3581 GNUNET_free (pm);
3583 "Freeing pm done\n");
3584}
3585
3586
3592static void
3604
3605
3611static void
3613{
3614 struct VirtualLink *vl = cls;
3615 struct ReassemblyContext *rc;
3616
3617 vl->reassembly_timeout_task = NULL;
3618 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3619 {
3621 .rel_value_us)
3622 {
3624 continue;
3625 }
3630 vl);
3631 return;
3632 }
3633}
3634
3635
3644static int
3645free_reassembly_cb (void *cls, uint32_t key, void *value)
3646{
3647 struct ReassemblyContext *rc = value;
3648
3649 (void) cls;
3650 (void) key;
3652 return GNUNET_OK;
3653}
3654
3655
3662static void
3664 unsigned int free_cmc);
3665
3666
3674static void
3676 struct CommunicatorMessageContext *cmc);
3677
3678
3685static void
3686free_burst_cls (struct GNUNET_StartBurstCls *sb_cls);
3687
3688
3706static void
3708 const struct GNUNET_PeerIdentity *pid)
3709{
3710 struct GNUNET_MQ_Envelope *env;
3711 struct SendOkMessage *so_msg;
3712
3713 if (NULL == tc)
3714 return;
3716 so_msg->peer = *pid;
3717 GNUNET_MQ_send (tc->mq, env);
3718}
3719
3720
3733static void
3735{
3736 if ((NULL == pm->client) || (GNUNET_YES == pm->client_credited))
3737 return;
3739 send_ok_to_client (pm->client, &pm->vl->target);
3740}
3741
3742
3748static void
3750{
3751 struct PendingMessage *pm;
3752 struct CoreSentContext *csc;
3753 struct CommunicatorMessageContext *cmc;
3754
3756 "free virtual link %p\n",
3757 vl);
3758
3759 /* Communicators that are blocked on CORE flow control for this link MUST
3760 be resumed here. Otherwise their `struct CommunicatorMessageContext's
3761 leak and -- worse -- those clients never get their
3762 GNUNET_SERVICE_client_continue() and stall forever. */
3763 while (NULL != (cmc = vl->cmc_head))
3764 release_stalled_cmc (vl, cmc);
3765 if (NULL != vl->core_fc_stall_task)
3766 {
3768 vl->core_fc_stall_task = NULL;
3769 }
3770
3771 if (NULL != vl->reassembly_map)
3772 {
3775 NULL);
3777 vl->reassembly_map = NULL;
3779 vl->reassembly_heap = NULL;
3780 }
3781 if (NULL != vl->reassembly_timeout_task)
3782 {
3784 vl->reassembly_timeout_task = NULL;
3785 }
3786 while (NULL != (pm = vl->pending_msg_head))
3787 {
3788 /* These never got transmitted, so #completed_pending_message() will not
3789 run for them and nobody else answers their SEND either. Return the
3790 window credit anyway: CORE keeps its `struct Neighbour' -- and thus
3791 the window -- until it sees our DISCONNECT, and #handle_client_send()
3792 deliberately tolerates a SEND for a link that is already gone, so a
3793 client can easily still be sending while we free this. */
3794 credit_client (pm);
3796 }
3799 if (NULL != vl->visibility_task)
3800 {
3802 vl->visibility_task = NULL;
3803 }
3804 if (NULL != vl->fc_retransmit_task)
3805 {
3807 vl->fc_retransmit_task = NULL;
3808 }
3809 while (NULL != (csc = vl->csc_head))
3810 {
3812 GNUNET_assert (vl == csc->vl);
3813 csc->vl = NULL;
3814 }
3815 if (NULL != vl->unconfirmed_timeout_task)
3816 {
3818 vl->unconfirmed_timeout_task = NULL;
3819 }
3820 if (NULL != vl->ic)
3821 {
3822 /* the closure of this iteration is @e sb_cls, released just below */
3824 vl->ic = NULL;
3825 }
3826 if (NULL != vl->sb_cls)
3827 {
3828 /* Cancels #burst_task if that task's closure is ours: it would
3829 otherwise run on this (freed) link. */
3830 free_burst_cls (vl->sb_cls);
3831 GNUNET_assert (NULL == vl->sb_cls);
3832 }
3833 GNUNET_free (vl->burst_addr);
3834 GNUNET_break (NULL == vl->n);
3835 GNUNET_break (NULL == vl->dv);
3836 GNUNET_free (vl);
3837}
3838
3839
3845static void
3847{
3848 if (NULL != vs->revalidation_task)
3849 {
3850 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3851 vs->revalidation_task = NULL;
3852 }
3853 /*memcpy (&hkey,
3854 &hc,
3855 sizeof (hkey));*/
3857 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3858 GNUNET_h2s (&vs->hc),
3859 vs->address,
3862 &vs->hc));
3865 GNUNET_YES ==
3868 vs->hn = NULL;
3869 if (NULL != vs->sc)
3870 {
3872 "store cancel\n");
3874 vs->sc = NULL;
3875 }
3876 GNUNET_free (vs->address);
3877 GNUNET_free (vs);
3878}
3879
3880
3887static struct Neighbour *
3892
3893
3900static struct VirtualLink *
3902{
3904}
3905
3906
3939
3940
3949static void
3951{
3952 struct Neighbour *n = dvh->next_hop;
3953 struct DistanceVector *dv = dvh->dv;
3954 struct PendingAcknowledgement *pa;
3955
3956 while (NULL != (pa = dvh->pa_head))
3957 {
3959 pa->dvh = NULL;
3960 }
3961 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3963 GNUNET_free (dvh);
3964}
3965
3966
3973static void
3974check_link_down (void *cls);
3975
3976
3982static void
3984{
3986 "Informing CORE clients about disconnect from %s\n",
3987 GNUNET_i2s (pid));
3988 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3989 {
3990 struct GNUNET_MQ_Envelope *env;
3991 struct DisconnectInfoMessage *dim;
3992
3993 if (CT_CORE != tc->type)
3994 continue;
3996 dim->peer = *pid;
3997 GNUNET_MQ_send (tc->mq, env);
3998 }
3999}
4000
4001
4002static void
4003try_to_bring_link_up (const struct GNUNET_PeerIdentity *pid);
4004
4005
4028static void
4030{
4031 struct GNUNET_PeerIdentity target = vl->target;
4032
4033 for (struct PendingMessage *pm = vl->pending_msg_head;
4034 NULL != pm;
4035 pm = pm->next_vl)
4036 credit_client (pm);
4038 free_virtual_link (vl);
4039 /* Start getting it back now. Only #handle_validation_response() can
4040 rebuild it, and a successful validation parks @e revalidation_task just
4041 short of #ADDRESS_VALIDATION_LIFETIME -- four hours away. */
4042 try_to_bring_link_up (&target);
4043}
4044
4045
4052static void
4054{
4055 struct DistanceVectorHop *dvh;
4056 struct VirtualLink *vl;
4057
4058 while (NULL != (dvh = dv->dv_head))
4060
4062 GNUNET_YES ==
4064 if (NULL != (vl = dv->vl))
4065 {
4066 GNUNET_assert (dv == vl->dv);
4067 vl->dv = NULL;
4068 if (NULL == vl->n)
4069 {
4071 }
4072 else
4073 {
4076 }
4077 dv->vl = NULL;
4078 }
4079
4080 if (NULL != dv->timeout_task)
4081 {
4083 dv->timeout_task = NULL;
4084 }
4085 GNUNET_free (dv->km);
4086 GNUNET_free (dv);
4087}
4088
4089
4103static void
4105 const struct GNUNET_PeerIdentity *peer,
4106 const char *address,
4108 const struct MonitorEvent *me)
4109{
4110 struct GNUNET_MQ_Envelope *env;
4112 size_t addr_len = strlen (address) + 1;
4113
4115 addr_len,
4117 md->nt = htonl ((uint32_t) nt);
4118 md->peer = *peer;
4119 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
4120 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
4121 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
4122 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
4123 md->cs = htonl ((uint32_t) me->cs);
4124 md->num_msg_pending = htonl (me->num_msg_pending);
4125 md->num_bytes_pending = htonl (me->num_bytes_pending);
4126 memcpy (&md[1], address, addr_len);
4127 GNUNET_MQ_send (tc->mq, env);
4128}
4129
4130
4140static void
4142 const char *address,
4144 const struct MonitorEvent *me)
4145{
4146 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4147 {
4148 if (CT_MONITOR != tc->type)
4149 continue;
4150 if (tc->details.monitor.one_shot)
4151 continue;
4152 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
4153 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
4154 continue;
4156 }
4157}
4158
4159
4169static void *
4171 struct GNUNET_SERVICE_Client *client,
4172 struct GNUNET_MQ_Handle *mq)
4173{
4174 struct TransportClient *tc;
4175
4176 (void) cls;
4177 tc = GNUNET_new (struct TransportClient);
4178 tc->client = client;
4179 tc->mq = mq;
4182 "Client %p of type %u connected\n",
4183 tc,
4184 tc->type);
4185 return tc;
4186}
4187
4188
4189static enum GNUNET_GenericReturnValue
4191 const struct GNUNET_PeerIdentity *pid,
4192 void *value)
4193{
4194 struct TransportGlobalNattedAddress *tgna = value;
4195 (void) cls;
4196
4197 GNUNET_free (tgna);
4198
4199 return GNUNET_OK;
4200}
4201
4202
4209static void
4210free_neighbour (struct Neighbour *neighbour,
4211 enum GNUNET_GenericReturnValue drop_link)
4212{
4213 struct DistanceVectorHop *dvh;
4214 struct VirtualLink *vl;
4215
4216 GNUNET_assert (NULL == neighbour->queue_head);
4219 &neighbour->pid,
4220 neighbour));
4222 "Freeing neighbour\n");
4225 NULL);
4227 while (NULL != (dvh = neighbour->dv_head))
4228 {
4229 struct DistanceVector *dv = dvh->dv;
4230
4232 if (NULL == dv->dv_head)
4233 free_dv_route (dv);
4234 }
4235 if (NULL != neighbour->get)
4236 {
4238 neighbour->get = NULL;
4239 }
4240 if (NULL != neighbour->sc)
4241 {
4243 "store cancel\n");
4244 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
4245 neighbour->sc = NULL;
4246 }
4247 if (NULL != (vl = neighbour->vl))
4248 {
4249 GNUNET_assert (neighbour == vl->n);
4250 vl->n = NULL;
4251 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
4252 {
4254 }
4255 else
4256 {
4259 }
4260 neighbour->vl = NULL;
4261 }
4262 GNUNET_free (neighbour);
4263}
4264
4265
4272static void
4274 const struct GNUNET_PeerIdentity *pid)
4275{
4276 struct GNUNET_MQ_Envelope *env;
4277 struct ConnectInfoMessage *cim;
4278
4279 GNUNET_assert (CT_CORE == tc->type);
4281 cim->id = *pid;
4282 GNUNET_MQ_send (tc->mq, env);
4283}
4284
4285
4291static void
4293{
4295 "Informing CORE clients about connection to %s\n",
4296 GNUNET_i2s (pid));
4297 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4298 {
4299 if (CT_CORE != tc->type)
4300 continue;
4302 }
4303}
4304
4305
4313static void
4314transmit_on_queue (void *cls);
4315
4316
4320static unsigned int
4322{
4323 for (struct Queue *s = queue_head; NULL != s;
4324 s = s->next_client)
4325 {
4326 if (s->tc->details.communicator.address_prefix !=
4327 queue->tc->details.communicator.address_prefix)
4328 {
4330 "queue address %s qid %u compare with queue: address %s qid %u\n",
4331 queue->address,
4332 queue->qid,
4333 s->address,
4334 s->qid);
4335 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
4336 (QUEUE_LENGTH_LIMIT > s->queue_length) )
4337 return GNUNET_YES;
4339 "Lower prio\n");
4340 }
4341 }
4342 return GNUNET_NO;
4343}
4344
4345
4352static void
4354
4355
4363static void
4365 struct Queue *queue,
4367{
4369
4370 if (queue->validated_until.abs_value_us < now.abs_value_us)
4371 return;
4373 queue->tc->details.communicator.
4374 queue_head))
4375 return;
4376
4377 if (queue->tc->details.communicator.total_queue_length >=
4379 {
4381 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
4382 queue->address,
4383 queue->qid);
4385 GST_stats,
4386 "# Transmission throttled due to communicator queue limit",
4387 1,
4388 GNUNET_NO);
4389 queue->idle = GNUNET_NO;
4390 /* @e total_queue_length is shared by every peer this communicator serves,
4391 so at the limit we can send to none of them, and the only things that
4392 lower it again are an ACK from the communicator, #free_queue() and
4393 #free_timedout_queue_entry(). If we got here because a peer stopped
4394 acknowledging, no ACK is coming; and we just declined to arm
4395 @e transmit_task, so #queue_send_msg() -- the *only* place that arms
4396 the sweeper -- will not run either. That leaves nothing at all to
4397 recover the count, and the communicator stays mute towards every peer
4398 until some unrelated queue happens to go down. Keep the sweeper
4399 going. */
4401 return;
4402 }
4403 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
4404 {
4406 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
4407 queue->address,
4408 queue->qid);
4410 "# Transmission throttled due to queue queue limit",
4411 1,
4412 GNUNET_NO);
4413 queue->idle = GNUNET_NO;
4414 /* Same reasoning as above, for the per-queue limit. */
4416 return;
4417 }
4418 if (0 == queue->q_capacity)
4419 {
4421 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
4422 PRIu64 ".\n",
4423 queue->address,
4424 queue->qid,
4425 queue->q_capacity);
4427 "# Transmission throttled due to message queue capacity",
4428 1,
4429 GNUNET_NO);
4430 queue->idle = GNUNET_NO;
4431 return;
4432 }
4433 /* queue might indeed be ready, schedule it */
4434 if (NULL != queue->transmit_task)
4435 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4436 queue->transmit_task =
4438 queue);
4440 "Considering transmission on queue `%s' QID %llu to %s\n",
4441 queue->address,
4442 (unsigned long long) queue->qid,
4443 GNUNET_i2s (&queue->neighbour->pid));
4444}
4445
4446
4447static void
4449 const char *address);
4450
4451
4458static void
4460{
4461 struct VirtualLink *vl = cls;
4462 struct DistanceVector *dv = vl->dv;
4463 struct Neighbour *n = vl->n;
4464 struct GNUNET_TIME_Absolute dvh_timeout;
4465 struct GNUNET_TIME_Absolute q_timeout;
4466
4468 "Checking if link is down\n");
4469 vl->visibility_task = NULL;
4470 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4471 if (NULL != dv)
4472 {
4473 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4474 pos = pos->next_dv)
4475 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4476 pos->path_valid_until);
4477 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4478 {
4479 vl->dv->vl = NULL;
4480 vl->dv = NULL;
4481 }
4482 }
4483 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4484 /* NOTE: @e n may be NULL here: #free_neighbour() clears vl->n and then
4485 schedules us when the link still has a DV route. */
4486 if (NULL != n)
4487 {
4488 struct GNUNET_TIME_Absolute liveness_deadline;
4489
4490 /* A successful validation is good for #ADDRESS_VALIDATION_LIFETIME (four
4491 hours). Do not take a communicator's word for that long: cap what the
4492 queues are worth by how recently this neighbour actually said anything
4493 to us. Otherwise a communicator that stops working without sending a
4494 QUEUE_TEARDOWN keeps this link -- and CORE's idea of the connection --
4495 alive until the validation expires. */
4496 liveness_deadline = GNUNET_TIME_absolute_add (n->last_inbound,
4498 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4499 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4500 if (GNUNET_TIME_absolute_cmp (liveness_deadline, <, q_timeout))
4501 {
4502 if (0 ==
4504 {
4505 /* Only reachable if a communicator failed to tear its queue down. */
4507 "Neighbour %s was silent for %s while its communicator "
4508 "kept claiming the queue works; treating link as down\n",
4509 GNUNET_i2s (&vl->target),
4512 GNUNET_YES));
4514 "# links dropped (neighbour silent)",
4515 1,
4516 GNUNET_NO);
4517 }
4518 q_timeout = liveness_deadline;
4519 }
4520 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
4521 {
4522 vl->n->vl = NULL;
4523 vl->n = NULL;
4524 }
4525 }
4526 if ((NULL == vl->n) && (NULL == vl->dv))
4527 {
4529 /* @e n (if any) outlives the link, and so do its queues: the liveness cap
4530 above drops a link whose addresses are still well inside
4531 #ADDRESS_VALIDATION_LIFETIME. In that state nothing would ever ask for
4532 a fresh challenge -- @e revalidation_task does not fire until the four
4533 hour validity is nearly over, and the HELLO path reaches
4534 #start_address_validation() only to find an address that still counts
4535 as valid. Since #handle_validation_response() is the only thing that
4536 can rebuild this link and tell CORE about the peer again, ask for that
4537 validation now, or CORE never hears about this peer again. */
4538 if (NULL != n)
4539 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4540 start_address_validation (&n->pid, q->address);
4541 return;
4542 }
4543 vl->visibility_task =
4544 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4546 vl);
4547}
4548
4549
4555static void
4557{
4558 struct Neighbour *neighbour = queue->neighbour;
4559 struct TransportClient *tc = queue->tc;
4560 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4562 struct QueueEntry *qe;
4563 int maxxed;
4564 struct PendingAcknowledgement *pa;
4565 struct VirtualLink *vl;
4566
4568 "Cleaning up queue %u\n", queue->qid);
4569 if (NULL != queue->mo)
4570 {
4572 queue->mo = NULL;
4573 }
4574 if (NULL != queue->transmit_task)
4575 {
4576 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4577 queue->transmit_task = NULL;
4578 }
4579 while (NULL != (pa = queue->pa_head))
4580 {
4581 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4582 pa->queue = NULL;
4583 }
4584
4586 neighbour->queue_head,
4587 neighbour->queue_tail,
4588 queue);
4590 tc->details.communicator.queue_head,
4591 tc->details.communicator.queue_tail,
4592 queue);
4594 tc->details.communicator.total_queue_length);
4596 "Cleaning up queue with length %u\n",
4597 queue->queue_length);
4598 while (NULL != (qe = queue->queue_head))
4599 {
4600 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4601 queue->queue_length--;
4602 tc->details.communicator.total_queue_length--;
4603 if (NULL != qe->pm)
4604 {
4605 GNUNET_assert (qe == qe->pm->qe);
4606 qe->pm->qe = NULL;
4607 }
4608 GNUNET_free (qe);
4609 }
4610 GNUNET_assert (0 == queue->queue_length);
4611 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4612 tc->details.communicator.total_queue_length))
4613 {
4614 /* Communicator dropped below threshold, resume all _other_ queues */
4616 GST_stats,
4617 "# Transmission throttled due to communicator queue limit",
4618 -1,
4619 GNUNET_NO);
4620 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4621 s = s->next_client)
4623 s,
4625 }
4626 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4628
4629 vl = lookup_virtual_link (&neighbour->pid);
4630 if ((NULL != vl) && (neighbour == vl->n))
4631 {
4633 check_link_down (vl);
4634 }
4635 if (NULL == neighbour->queue_head)
4636 {
4637 free_neighbour (neighbour, GNUNET_NO);
4638 }
4639}
4640
4641
4649static void
4651
4652
4658static void
4660{
4661 struct TransportClient *tc = ale->tc;
4662
4663 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4664 tc->details.communicator.addr_tail,
4665 ale);
4666 /* Cancels @e sc, @e shc and the pending PILS signature request, all of
4667 which would otherwise run their callbacks on this freed entry. */
4669 if (NULL != ale->sc)
4670 {
4672 "store cancel\n");
4674 ale->sc = NULL;
4675 }
4676 if (NULL != ale->shc)
4677 {
4679 ale->shc = NULL;
4680 }
4681 if (NULL != ale->st)
4682 {
4684 ale->st = NULL;
4685 }
4686 if (NULL != ale->signed_address)
4688 GNUNET_free (ale);
4689}
4690
4691
4700static int
4702 const struct GNUNET_PeerIdentity *pid,
4703 void *value)
4704{
4705 struct TransportClient *tc = cls;
4706 struct PeerRequest *pr = value;
4707
4708 if (NULL != pr->nc)
4710 pr->nc = NULL;
4712 GNUNET_YES ==
4713 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4714 pid,
4715 pr));
4716 GNUNET_free (pr);
4717
4718 return GNUNET_OK;
4719}
4720
4721
4722static void
4723do_shutdown (void *cls);
4724
4733static void
4735 struct GNUNET_SERVICE_Client *client,
4736 void *app_ctx)
4737{
4738 struct TransportClient *tc = app_ctx;
4739
4740 (void) cls;
4741 (void) client;
4743 switch (tc->type)
4744 {
4745 case CT_NONE:
4747 "Unknown Client %p disconnected, cleaning up.\n",
4748 tc);
4749 break;
4750
4751 case CT_CORE: {
4752 struct PendingMessage *pm;
4754 "CORE Client %p disconnected, cleaning up.\n",
4755 tc);
4756
4757
4758 while (NULL != (pm = tc->details.core.pending_msg_head))
4759 {
4761 tc->details.core.pending_msg_head,
4762 tc->details.core.pending_msg_tail,
4763 pm);
4764 pm->client = NULL;
4765 }
4766 }
4767 break;
4768
4769 case CT_MONITOR:
4771 "MONITOR Client %p disconnected, cleaning up.\n",
4772 tc);
4773
4774 break;
4775
4776 case CT_COMMUNICATOR: {
4777 struct Queue *q;
4778 struct AddressListEntry *ale;
4779
4781 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4782 tc);
4783
4784 if (NULL != tc->details.communicator.free_queue_entry_task)
4786 tc->details.communicator.free_queue_entry_task);
4787 while (NULL != (q = tc->details.communicator.queue_head))
4788 free_queue (q);
4789 while (NULL != (ale = tc->details.communicator.addr_head))
4791 GNUNET_free (tc->details.communicator.address_prefix);
4792 }
4793 break;
4794
4795 case CT_APPLICATION:
4797 "APPLICATION Client %p disconnected, cleaning up.\n",
4798 tc);
4799
4800 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4802 tc);
4803 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4804 break;
4805 }
4806 GNUNET_free (tc);
4807 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4808 {
4810 "Our last client disconnected\n");
4811 do_shutdown (cls);
4812 }
4813}
4814
4815
4825static int
4827 const struct GNUNET_PeerIdentity *pid,
4828 void *value)
4829{
4830 struct TransportClient *tc = cls;
4831 struct VirtualLink *vl = value;
4832
4833 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4834 return GNUNET_OK;
4835
4837 "Telling new CORE client about existing connection to %s\n",
4838 GNUNET_i2s (pid));
4840 return GNUNET_OK;
4841}
4842
4843
4849static void
4851 unsigned
4852 int free_cmc);
4853
4854static enum GNUNET_GenericReturnValue
4856 const struct GNUNET_PeerIdentity *pid,
4857 void *value)
4858{
4859 struct VirtualLink *vl = value;
4860 struct CommunicatorMessageContext *cmc;
4861
4862 /* resume communicators */
4863 while (NULL != (cmc = vl->cmc_tail))
4864 release_stalled_cmc (vl, cmc);
4865 if (NULL != vl->core_fc_stall_task)
4866 {
4868 vl->core_fc_stall_task = NULL;
4869 }
4870 /* A CORE client that just attached has nothing outstanding, so give it a
4871 full window. The RECV_OKs that would have returned the credit spent by
4872 its predecessor died with that client, and #handle_client_recv_ok() is
4873 the only thing that ever raises this counter -- so without the reset
4874 every message on this link takes the "CORE ran out of window" path from
4875 here on, and only #core_fc_stalled() (after CORE_FC_STALL_TIMEOUT, and
4876 once per round) ever lets any through. */
4878 return GNUNET_OK;
4879}
4880
4881
4890static void
4891handle_client_start (void *cls, const struct StartMessage *start)
4892{
4893 // const struct GNUNET_PeerIdentity *my_identity;
4894 struct TransportClient *tc = cls;
4895 // uint32_t options;
4896 //
4897 // my_identity = GNUNET_PILS_get_identity (pils);
4898 // GNUNET_assert (my_identity);
4899 //
4900 // FIXME ignore the check of the peer ids for now.
4901 // (also deprecate the old way of obtaining our own peer ID)
4902 // options = ntohl (start->options);
4903 // if ((0 != (1 & options)) &&
4904 // (0 != GNUNET_memcmp (&start->self, my_identity)))
4905 // {
4906 // /* client thinks this is a different peer, reject */
4907 // GNUNET_break (0);
4908 // GNUNET_SERVICE_client_drop (tc->client);
4909 // return;
4910 // }
4911 if (CT_NONE != tc->type)
4912 {
4913 GNUNET_break (0);
4915 return;
4916 }
4917 tc->type = CT_CORE;
4919 "New CORE client with PID %s registered\n",
4920 GNUNET_i2s (&start->self));
4923 tc);
4926 NULL);
4928}
4929
4930
4937static int
4938check_client_send (void *cls, const struct OutboundMessage *obm)
4939{
4940 struct TransportClient *tc = cls;
4941 uint16_t size;
4942 const struct GNUNET_MessageHeader *obmm;
4943
4944 if (CT_CORE != tc->type)
4945 {
4946 GNUNET_break (0);
4947 return GNUNET_SYSERR;
4948 }
4949 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4950 if (size < sizeof(struct GNUNET_MessageHeader))
4951 {
4952 GNUNET_break (0);
4953 return GNUNET_SYSERR;
4954 }
4955 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4956 if (size != ntohs (obmm->size))
4957 {
4958 GNUNET_break (0);
4959 return GNUNET_SYSERR;
4960 }
4961 return GNUNET_OK;
4962}
4963
4964
4972static void
4974{
4975 struct TransportClient *tc = pm->client;
4976 struct VirtualLink *vl = pm->vl;
4977
4979 "client send response\n");
4980 if (NULL != tc)
4981 {
4983 "Confirming transmission of <%" PRIu64 "> to %s\n",
4984 pm->logging_uuid,
4985 GNUNET_i2s (&vl->target));
4986 credit_client (pm);
4987 }
4989}
4990
4991
5001static unsigned int
5004 struct DistanceVectorHop **hops_array,
5005 unsigned int hops_array_length)
5006{
5007 uint64_t choices[hops_array_length];
5008 uint64_t num_dv;
5009 unsigned int dv_count;
5010
5011 /* Pick random vectors, but weighted by distance, giving more weight
5012 to shorter vectors */
5013 num_dv = 0;
5014 dv_count = 0;
5015 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5016 pos = pos->next_dv)
5017 {
5018 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
5019 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
5020 .rel_value_us == 0))
5021 continue; /* pos unconfirmed and confirmed required */
5022 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
5023 dv_count++;
5024 }
5025 if (0 == dv_count)
5026 return 0;
5027 if (dv_count <= hops_array_length)
5028 {
5029 dv_count = 0;
5030 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5031 pos = pos->next_dv)
5032 hops_array[dv_count++] = pos;
5033 return dv_count;
5034 }
5035 for (unsigned int i = 0; i < hops_array_length; i++)
5036 {
5037 int ok = GNUNET_NO;
5038 while (GNUNET_NO == ok)
5039 {
5040 choices[i] =
5041 GNUNET_CRYPTO_random_u64 (num_dv);
5042 ok = GNUNET_YES;
5043 for (unsigned int j = 0; j < i; j++)
5044 if (choices[i] == choices[j])
5045 {
5046 ok = GNUNET_NO;
5047 break;
5048 }
5049 }
5050 }
5051 dv_count = 0;
5052 num_dv = 0;
5053 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5054 pos = pos->next_dv)
5055 {
5056 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
5057
5058 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
5059 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
5060 .rel_value_us == 0))
5061 continue; /* pos unconfirmed and confirmed required */
5062 for (unsigned int i = 0; i < hops_array_length; i++)
5063 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
5064 hops_array[dv_count++] = pos;
5065 num_dv += delta;
5066 }
5067 return dv_count;
5068}
5069
5070
5077static int
5079 void *cls,
5081{
5082 struct TransportClient *tc = cls;
5083 uint16_t size;
5084
5085 if (CT_NONE != tc->type)
5086 {
5087 GNUNET_break (0);
5088 return GNUNET_SYSERR;
5089 }
5090 tc->type = CT_COMMUNICATOR;
5091 size = ntohs (cam->header.size) - sizeof(*cam);
5092 if (0 == size)
5093 return GNUNET_OK; /* receive-only communicator */
5095 return GNUNET_OK;
5096}
5097
5098
5110static void
5112{
5113 struct GNUNET_MQ_Envelope *env;
5115
5116 if (GNUNET_YES == cmc->ack_sent)
5117 return;
5118 cmc->ack_sent = GNUNET_YES;
5119 if (0 == ntohl (cmc->im.fc_on))
5120 return; /* communicator did not ask for flow control */
5122 "Acknowledge message with flow control id %" PRIu64 "\n",
5123 cmc->im.fc_id);
5125 ack->reserved = htonl (0);
5126 ack->fc_id = cmc->im.fc_id;
5127 ack->sender = cmc->im.neighbour_sender;
5128 GNUNET_MQ_send (cmc->tc->mq, env);
5129}
5130
5131
5142static void
5144{
5145 if (GNUNET_YES == cmc->client_resumed)
5146 return;
5149}
5150
5151
5160static void
5162 unsigned
5163 int free_cmc)
5164{
5165 send_cmc_ack (cmc);
5166 resume_cmc_client (cmc);
5167 if (GNUNET_YES == free_cmc)
5168 {
5169 GNUNET_free (cmc);
5170 }
5171}
5172
5173
5174static void
5183
5184
5185static void
5190
5191
5201static void
5202handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
5203{
5204 struct TransportClient *tc = cls;
5205 struct VirtualLink *vl;
5206 uint32_t delta;
5207 struct CommunicatorMessageContext *cmc;
5208
5209 if (CT_CORE != tc->type)
5210 {
5211 GNUNET_break (0);
5213 return;
5214 }
5215 vl = lookup_virtual_link (&rom->peer);
5216 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5217 {
5219 "# RECV_OK dropped: virtual link unknown",
5220 1,
5221 GNUNET_NO);
5223 return;
5224 }
5225 delta = ntohl (rom->increase_window_delta);
5226 vl->core_recv_window += delta;
5228 "CORE ack receiving message, increased CORE recv window to %d\n",
5229 vl->core_recv_window);
5231 if (vl->core_recv_window <= 0)
5232 return;
5233 /* release the flow control credit we withheld from the communicators */
5234 while (NULL != (cmc = vl->cmc_tail))
5235 release_stalled_cmc (vl, cmc);
5236 if (NULL != vl->core_fc_stall_task)
5237 {
5239 vl->core_fc_stall_task = NULL;
5240 }
5241}
5242
5243
5250static void
5252 void *cls,
5254{
5255 const struct GNUNET_PeerIdentity *my_identity;
5256 struct TransportClient *tc = cls;
5257 uint16_t size;
5258
5259 size = ntohs (cam->header.size) - sizeof(*cam);
5260 if (0 == size)
5261 {
5263 "Receive-only communicator connected\n");
5264 /* Receive-only communicator: it has no address prefix, but we still
5265 MUST resume the client or we will never read from it again. Use an
5266 empty prefix so that the various strcmp()s do not see NULL. */
5267 tc->details.communicator.address_prefix = GNUNET_strdup ("");
5269 return;
5270 }
5271 tc->details.communicator.address_prefix =
5272 GNUNET_strdup ((const char *) &cam[1]);
5273 tc->details.communicator.cc = ntohl (cam->cc);
5274 tc->details.communicator.can_burst = ntohl (cam->can_burst);
5276 if (NULL != my_identity)
5277 {
5279 "Communicator for peer %s with prefix '%s' connected %s\n",
5281 tc->details.communicator.address_prefix,
5282 tc->details.communicator.can_burst ? "can burst" :
5283 "can not burst");
5284 }
5285 else
5286 {
5288 "Communicator for local peer with prefix '%s' connected %s\n",
5289 tc->details.communicator.address_prefix,
5290 tc->details.communicator.can_burst ? "can burst" :
5291 "can not burst");
5292 }
5294}
5295
5296
5304static int
5306 void *cls,
5308{
5309 const struct GNUNET_MessageHeader *inbox;
5310 const char *is;
5311 uint16_t msize;
5312 uint16_t isize;
5313
5314 (void) cls;
5315 msize = ntohs (cb->header.size) - sizeof(*cb);
5316 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
5317 /* MUST bound the buffer before dereferencing @a inbox. */
5318 if (msize <= sizeof(struct GNUNET_MessageHeader))
5319 {
5320 GNUNET_break (0);
5321 return GNUNET_SYSERR;
5322 }
5323 isize = ntohs (inbox->size);
5324 if (isize >= msize)
5325 {
5326 GNUNET_break (0);
5327 return GNUNET_SYSERR;
5328 }
5329 is = (const char *) inbox;
5330 is += isize;
5331 msize -= isize;
5332 GNUNET_assert (0 < msize);
5333 if ('\0' != is[msize - 1])
5334 {
5335 GNUNET_break (0);
5336 return GNUNET_SYSERR;
5337 }
5338 return GNUNET_OK;
5339}
5340
5341
5356static enum GNUNET_GenericReturnValue
5371
5372
5373static void
5375 struct TransportClient *tc);
5376
5377
5378static void
5380{
5381 struct TransportClient *tc = cls;
5383
5385 "freeing timedout queue entries\n");
5386
5387 tc->details.communicator.free_queue_entry_task = NULL;
5388 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
5389 queue = queue->next_client)
5390 {
5391 struct QueueEntry *qep = queue->queue_head;
5392
5394 "checking QID %u for timedout queue entries\n",
5395 queue->qid);
5396 while (NULL != qep)
5397 {
5398 struct QueueEntry *pos = qep;
5400 pos->creation_timestamp, now);
5401 qep = qep->next;
5402
5404 "diff to now %s \n",
5407 {
5409 "Freeing timed out QueueEntry with MID %" PRIu64
5410 " and QID %u\n",
5411 pos->mid,
5412 queue->qid);
5414 "# QueueEntries timed out",
5415 1,
5416 GNUNET_NO);
5417 free_queue_entry (pos, tc);
5418 }
5419 }
5420 }
5421 /* Entries younger than #QUEUE_ENTRY_TIMEOUT are still to be reclaimed, and
5422 this task used to be a one-shot armed only by #queue_send_msg(). So the
5423 sweep that was supposed to bound how long an unacknowledged entry holds
5424 its slot only ever ran while *new* messages were being queued -- exactly
5425 not the case once the throttles in #schedule_transmit_on_queue() have
5426 stopped transmission. Keep going as long as anything is outstanding. */
5428}
5429
5430
5431static void
5433{
5434 if (NULL != tc->details.communicator.free_queue_entry_task)
5435 return;
5436 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
5437 queue = queue->next_client)
5438 {
5439 if (NULL == queue->queue_head)
5440 continue;
5441 tc->details.communicator.free_queue_entry_task =
5444 tc);
5445 return;
5446 }
5447}
5448
5449
5459static void
5461 struct PendingMessage *pm,
5462 const void *payload,
5463 size_t payload_size)
5464{
5465 struct Neighbour *n = queue->neighbour;
5467 struct GNUNET_MQ_Envelope *env;
5468 struct PendingAcknowledgement *pa;
5469
5470 GNUNET_log (
5472 "Queueing %u bytes of payload for transmission <%" PRIu64
5473 "> on queue %llu to %s\n",
5474 (unsigned int) payload_size,
5475 (NULL == pm) ? 0 : pm->logging_uuid,
5476 (unsigned long long) queue->qid,
5477 GNUNET_i2s (&queue->neighbour->pid));
5478 env = GNUNET_MQ_msg_extra (smt,
5479 payload_size,
5481 smt->qid = htonl (queue->qid);
5482 smt->mid = GNUNET_htonll (queue->mid_gen);
5483 smt->receiver = n->pid;
5484 memcpy (&smt[1], payload, payload_size);
5485 {
5486 /* Pass the env to the communicator of queue for transmission. */
5487 struct QueueEntry *qe;
5488
5489 qe = GNUNET_new (struct QueueEntry);
5490 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
5491 qe->mid = queue->mid_gen;
5493 "Create QueueEntry with MID %" PRIu64
5494 " and QID %u and prefix %s\n",
5495 qe->mid,
5496 queue->qid,
5497 queue->tc->details.communicator.address_prefix);
5498 queue->mid_gen++;
5499 qe->queue = queue;
5500 if (NULL != pm)
5501 {
5502 qe->pm = pm;
5503 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
5504 // GNUNET_assert (NULL == pm->qe);
5505 if (NULL != pm->qe)
5506 {
5508 "Retransmitting message <%" PRIu64
5509 "> remove pm from qe with MID: %llu \n",
5511 (unsigned long long) pm->qe->mid);
5512 pm->qe->pm = NULL;
5513 }
5514 pm->qe = qe;
5515 }
5516 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
5517 if (0 == queue->q_capacity)
5518 {
5519 // Messages without FC or fragments can get here.
5520 if (NULL != pm)
5521 {
5523 "Message %" PRIu64
5524 " (pm type %u) was not send because queue has no capacity.\n",
5526 pm->pmt);
5527 pm->qe = NULL;
5528 }
5529 GNUNET_free (env);
5530 GNUNET_free (qe);
5531 return;
5532 }
5533 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
5534 queue->queue_length++;
5535 queue->tc->details.communicator.total_queue_length++;
5536 if (GNUNET_NO == queue->unlimited_length)
5537 queue->q_capacity--;
5539 "Queue %s with qid %u has capacity %" PRIu64 "\n",
5540 queue->address,
5541 queue->qid,
5542 queue->q_capacity);
5544 queue->tc->details.communicator.total_queue_length)
5545 queue->idle = GNUNET_NO;
5546 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
5547 queue->idle = GNUNET_NO;
5548 if (0 == queue->q_capacity)
5549 queue->idle = GNUNET_NO;
5550
5551 if (GNUNET_NO == queue->idle)
5553 if (NULL != pm && NULL != (pa = pm->pa_head))
5554 {
5555 while (pm != pa->pm)
5556 pa = pa->next_pa;
5557 pa->num_send++;
5558 }
5559 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
5561 "Sending message MID %" PRIu64
5562 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
5563 PRIu64 "\n",
5564 GNUNET_ntohll (smt->mid),
5565 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
5566 ntohs (smt->header.size),
5567 (unsigned long) payload_size,
5568 queue->tc->mq,
5569 queue->address,
5570 queue->qid,
5571 (NULL == pm) ? 0 : pm->logging_uuid);
5572 GNUNET_MQ_send (queue->tc->mq, env);
5573 }
5574}
5575
5576
5587static struct GNUNET_TIME_Relative
5589 const struct GNUNET_MessageHeader *hdr,
5591{
5592 struct GNUNET_TIME_Absolute now;
5593 unsigned int candidates;
5594 unsigned int sel1;
5595 unsigned int sel2;
5596 struct GNUNET_TIME_Relative rtt;
5597
5598 /* Pick one or two 'random' queues from n (under constraints of options) */
5599 now = GNUNET_TIME_absolute_get ();
5600 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
5601 weight in the future; weight could be assigned by observed
5602 bandwidth (note: not sure if we should do this for this type
5603 of control traffic though). */
5604 candidates = 0;
5605 for (struct Queue *pos = n->queue_head; NULL != pos;
5606 pos = pos->next_neighbour)
5607 {
5608 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5609 (pos->validated_until.abs_value_us > now.abs_value_us))
5610 candidates++;
5611 }
5612 if (0 == candidates)
5613 {
5614 /* This can happen rarely if the last confirmed queue timed
5615 out just as we were beginning to process this message. */
5617 "Could not route message of type %u to %s: no valid queue\n",
5618 ntohs (hdr->type),
5619 GNUNET_i2s (&n->pid));
5621 "# route selection failed (all no valid queue)",
5622 1,
5623 GNUNET_NO);
5625 }
5626
5628 sel1 = GNUNET_CRYPTO_random_u32 (candidates);
5629 if (0 == (options & RMO_REDUNDANT))
5630 sel2 = candidates; /* picks none! */
5631 else
5632 sel2 = GNUNET_CRYPTO_random_u32 (candidates);
5633 candidates = 0;
5634 for (struct Queue *pos = n->queue_head; NULL != pos;
5635 pos = pos->next_neighbour)
5636 {
5637 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5638 (pos->validated_until.abs_value_us > now.abs_value_us))
5639 {
5640 if ((sel1 == candidates) || (sel2 == candidates))
5641 {
5643 "Routing message of type %u to %s using %s (#%u)\n",
5644 ntohs (hdr->type),
5645 GNUNET_i2s (&n->pid),
5646 pos->address,
5647 (sel1 == candidates) ? 1 : 2);
5648 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5649 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5650 }
5651 candidates++;
5652 }
5653 }
5654 return rtt;
5655}
5656
5657
5668typedef void (*DVMessageHandler) (void *cls,
5669 struct Neighbour *next_hop,
5670 const struct GNUNET_MessageHeader *hdr,
5672
5687static struct GNUNET_TIME_Relative
5689 unsigned int num_dvhs,
5690 struct DistanceVectorHop **dvhs,
5691 const struct GNUNET_MessageHeader *hdr,
5692 DVMessageHandler use,
5693 void *use_cls,
5695 enum GNUNET_GenericReturnValue without_fc)
5696{
5697 const struct GNUNET_PeerIdentity *my_identity;
5698 struct TransportDVBoxMessage box_hdr;
5699 struct TransportDVBoxPayloadP *payload_hdr;
5700 uint16_t body_len_hbo = ntohs (hdr->size);
5701 unsigned char pt[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5703 unsigned char ct[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5705 struct GNUNET_TIME_Relative rtt;
5707
5708 payload_hdr = (struct TransportDVBoxPayloadP*) pt;
5711
5712 /* Encrypt payload */
5713 memset (&box_hdr, 0, sizeof (box_hdr));
5715 box_hdr.total_hops = htons (0);
5716 box_hdr.without_fc = htonl (without_fc);
5717 // update_ephemeral (dv);
5718 if ((0 ==
5719 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5720 || (NULL == dv->km))
5721 {
5722 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5723 &dv->ephemeral_key,
5724 (struct GNUNET_ShortHashCode*) &km);
5725 GNUNET_free (dv->km); /* do not leak the previous key material */
5726 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5727 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5728 if (GNUNET_OK != sign_ephemeral (dv))
5729 {
5730 /* Without a matching signature the box is undecryptable noise to the
5731 receiver; do not spend the bandwidth. Expire the ephemeral so the
5732 next attempt re-derives and re-signs rather than reusing it. */
5733 dv->ephemeral_validity = GNUNET_TIME_UNIT_ZERO_ABS;
5735 }
5736 }
5737 else
5738 {
5739 /* The ephemeral key is still valid, so reuse the cached key material.
5740 Without this @a km stayed UNINITIALISED stack memory and the
5741 receiver could not decrypt the box. */
5742 GNUNET_memcpy (&km, dv->km, sizeof(struct GNUNET_ShortHashCode));
5743 }
5744 box_hdr.ephemeral_key = dv->ephemeral_key;
5745 payload_hdr->sender_sig = dv->sender_sig;
5746 memcpy (&payload_hdr[1], hdr, body_len_hbo);
5748 sizeof(box_hdr.iv));
5749 payload_hdr->sender = *my_identity;
5750 payload_hdr->monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5751 GNUNET_CRYPTO_aead_encrypt (sizeof pt,
5752 pt,
5753 0,
5754 NULL,
5755 &km,
5756 &box_hdr.iv,
5757 ct,
5758 &box_hdr.mac);
5760 /* For each selected path, take the pre-computed header and body
5761 and add the path in the middle of the message; then send it. */
5762 for (unsigned int i = 0; i < num_dvhs; i++)
5763 {
5764 struct DistanceVectorHop *dvh = dvhs[i];
5765 unsigned int num_hops = dvh->distance + 1;
5766 char buf[sizeof(struct TransportDVBoxMessage)
5767 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5768 + sizeof(struct TransportDVBoxPayloadP)
5769 + body_len_hbo] GNUNET_ALIGN;
5770 struct GNUNET_PeerIdentity *dhops;
5771
5772 box_hdr.header.size = htons (sizeof(buf));
5773 box_hdr.orig_size = htons (sizeof(buf));
5774 box_hdr.num_hops = htons (num_hops);
5775 memcpy (buf, &box_hdr, sizeof(box_hdr));
5776 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5777 memcpy (dhops,
5778 dvh->path,
5779 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5780 dhops[dvh->distance] = dv->target;
5781 if (GNUNET_EXTRA_LOGGING > 0)
5782 {
5783 char *path;
5784
5786 for (unsigned int j = 0; j < num_hops; j++)
5787 {
5788 char *tmp;
5789
5790 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5791 GNUNET_free (path);
5792 path = tmp;
5793 }
5795 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5796 ntohs (hdr->type),
5797 GNUNET_i2s (&dv->target),
5798 i + 1,
5799 num_dvhs,
5800 path);
5801 GNUNET_free (path);
5802 }
5803 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5804 memcpy (&dhops[num_hops], ct, sizeof(ct));
5805 use (use_cls,
5806 dvh->next_hop,
5807 (const struct GNUNET_MessageHeader *) buf,
5808 options);
5809 }
5810 return rtt;
5811}
5812
5813
5823static void
5825 struct Neighbour *next_hop,
5826 const struct GNUNET_MessageHeader *hdr,
5828{
5829 (void) cls;
5830 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5831}
5832
5833
5845static struct GNUNET_TIME_Relative
5847// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5848 const struct GNUNET_MessageHeader *hdr,
5850{
5851 // struct VirtualLink *vl;
5852 struct Neighbour *n;
5853 struct DistanceVector *dv;
5854 struct GNUNET_TIME_Relative rtt1;
5855 struct GNUNET_TIME_Relative rtt2;
5856 const struct GNUNET_PeerIdentity *target = &vl->target;
5857
5859 "Trying to route message of type %u to %s without fc\n",
5860 ntohs (hdr->type),
5861 GNUNET_i2s (target));
5862
5863 // TODO Do this elsewhere. vl should be given as parameter to method.
5864 // vl = lookup_virtual_link (target);
5865 /* An unconfirmed link is allowed here: it has no @e n and no @e dv of its
5866 own, so the "confirmed required" branch below resolves the route from
5867 #neighbours / #dv_routes. Refusing to route at all is what deadlocks a
5868 pair of peers, see #consider_sending_fc(). */
5869 GNUNET_assert (NULL != vl);
5870 n = vl->n;
5871 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5872 /* An unconfirmed link has neither @e n nor @e dv of its own, so resolve
5873 the route from #neighbours / #dv_routes. This used to be done only
5874 while #RMO_UNCONFIRMED_ALLOWED was *not* set -- exactly backwards: with
5875 the flag set (the caller that needs it most) we would find no route at
5876 all and drop the message. Whether an unvalidated queue or an
5877 unvalidated path may then be used is still decided by @a options, in
5878 #route_via_neighbour() and #pick_random_dv_hops(). */
5879 if (NULL == n)
5880 n = lookup_neighbour (target);
5881 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5883 if ((NULL == n) && (NULL == dv))
5884 {
5886 "Cannot route message of type %u to %s: no route\n",
5887 ntohs (hdr->type),
5888 GNUNET_i2s (target));
5890 "# Messages dropped in routing: no acceptable method",
5891 1,
5892 GNUNET_NO);
5894 }
5896 "Routing message of type %u to %s with options %X\n",
5897 ntohs (hdr->type),
5898 GNUNET_i2s (target),
5899 (unsigned int) options);
5900 /* If both dv and n are possible and we must choose:
5901 flip a coin for the choice between the two; for now 50/50 */
5902 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5903 {
5904 if (0 == GNUNET_CRYPTO_random_u32 (2))
5905 n = NULL;
5906 else
5907 dv = NULL;
5908 }
5909 if ((NULL != n) && (NULL != dv))
5910 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5911 enough for redundancy, so clear the flag. */
5914 if (NULL != n)
5915 {
5917 "Try to route message of type %u to %s without fc via neighbour\n",
5918 ntohs (hdr->type),
5919 GNUNET_i2s (target));
5920 rtt1 = route_via_neighbour (n, hdr, options);
5921 }
5922 if (NULL != dv)
5923 {
5924 struct DistanceVectorHop *hops[2];
5925 unsigned int res;
5926
5928 options,
5929 hops,
5930 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5931 if (0 == res)
5932 {
5934 "Failed to route message, could not determine DV path\n");
5935 return rtt1;
5936 }
5938 "encapsulate_for_dv 1\n");
5939 rtt2 = encapsulate_for_dv (dv,
5940 res,
5941 hops,
5942 hdr,
5944 NULL,
5946 GNUNET_YES);
5947 }
5948 return GNUNET_TIME_relative_min (rtt1, rtt2);
5949}
5950
5951
5952static void
5953consider_sending_fc (void *cls);
5954
5961static void
5963{
5964 struct VirtualLink *vl = cls;
5965 vl->fc_retransmit_task = NULL;
5966 consider_sending_fc (cls);
5967}
5968
5969
5970static char *
5971get_address_without_port (const char *address);
5972
5973
5975{
5976 size_t off;
5977
5983 size_t size;
5984
5985 char *tgnas;
5986};
5987
5988
5989static enum GNUNET_GenericReturnValue
5991 const struct GNUNET_PeerIdentity *pid,
5992 void *value)
5993{
5994 struct AddGlobalAddressesContext *ctx = cls;
5995 struct TransportGlobalNattedAddress *tgna = value;
5996 char *addr = (char *) &tgna[1];
5997 size_t alen = ntohl (tgna->address_length);
5998 size_t need = sizeof (struct TransportGlobalNattedAddress) + alen;
5999
6000 /* NOTE: the address is NOT 0-terminated, it must be printed with an
6001 explicit precision. */
6003 "sending address %.*s length %lu\n",
6004 (int) alen,
6005 addr,
6006 (unsigned long) alen);
6007 if (ctx->off + need > ctx->size)
6008 {
6009 GNUNET_break (0);
6010 return GNUNET_NO;
6011 }
6012 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, need);
6013 ctx->off += need;
6014
6015 return GNUNET_OK;
6016}
6017
6018
6019static struct GNUNET_TIME_Relative
6020calculate_rtt (struct DistanceVector *dv);
6021
6022
6029static void
6031{
6032 struct VirtualLink *vl = cls;
6033 struct GNUNET_TIME_Absolute monotime;
6034 struct TransportFlowControlMessage *fc;
6036 struct GNUNET_TIME_Relative rtt;
6037 struct GNUNET_TIME_Relative rtt_average;
6038 struct Neighbour *n = vl->n;
6039 size_t addresses_size;
6040
6041 if ((GNUNET_YES != vl->confirmed) &&
6042 (NULL == lookup_neighbour (&vl->target)) &&
6044 {
6045 /* Unconfirmed AND no way to reach the peer at all -- nothing to send on.
6046 An unconfirmed link that *does* have a route must still answer,
6047 see below.
6048
6049 Do NOT just return: #task_consider_sending_fc() cleared
6050 @e fc_retransmit_task before calling us, and the only other place that
6051 arms it is #handle_flow_control() -- which only does so when it is
6052 already non-NULL. Leaving without re-arming therefore ends the
6053 keepalive chain for this link permanently, and #check_link_down()
6054 tears it down #NEIGHBOUR_LIVENESS_TIMEOUT later. */
6056 "Not sending FC to %s: link unconfirmed and no route\n",
6057 GNUNET_i2s (&vl->target));
6058 if (NULL == vl->fc_retransmit_task)
6062 vl);
6063 return;
6064 }
6065 addresses_size = 0;
6066 if (NULL != n && 0 < n->number_of_addresses)
6067 {
6068 addresses_size =
6069 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
6070 ->size_of_global_addresses;
6071 if (addresses_size >
6072 UINT16_MAX - sizeof (struct TransportFlowControlMessage))
6073 {
6074 /* htons() below would silently truncate `header.size', leaving a
6075 message whose declared length does not match its contents. */
6076 GNUNET_break (0);
6077 addresses_size = 0;
6078 }
6079 }
6080 if (0 != addresses_size)
6081 {
6082 char *tgnas = GNUNET_malloc (addresses_size);
6084 ctx.off = 0;
6085 ctx.size = addresses_size;
6086 ctx.tgnas = tgnas;
6087
6089 + addresses_size);
6090 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
6091 + addresses_size);
6092 fc->size_of_addresses = htonl ((uint32_t) n->size_of_global_addresses);
6093 fc->number_of_addresses = htonl (n->number_of_addresses);
6096 &ctx);
6099 }
6100 else
6101 {
6102 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
6103 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
6104 }
6105
6107 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
6108 it always! */
6109 /* For example, we should probably ONLY do this if a bit more than
6110 an RTT has passed, or if the window changed "significantly" since
6111 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
6112 need an estimate for the bandwidth-delay-product for the entire
6113 VL, as that determines "significantly". We have the delay, but
6114 the bandwidth statistics need to be added for the VL!*/(void) duration;
6115
6116 if (NULL != vl->dv)
6117 rtt_average = calculate_rtt (vl->dv);
6118 else
6119 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
6120 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
6122 "Sending FC seq %u to %s with new window %llu %lu %u\n",
6123 (unsigned int) vl->fc_seq_gen,
6124 GNUNET_i2s (&vl->target),
6125 (unsigned long long) vl->incoming_fc_window_size,
6126 (unsigned long) rtt_average.rel_value_us,
6127 vl->sync_ready);
6129 vl->last_fc_transmission = monotime;
6130 fc->sync_ready = htonl ((uint32_t) vl->sync_ready);
6132 fc->seq = htonl (vl->fc_seq_gen++);
6133 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
6136 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
6137 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
6138 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
6139 /* On an unconfirmed link the only queues and paths we have are, by
6140 definition, unvalidated ones -- that is what "unconfirmed" means.
6141 Requiring a validated route here is what deadlocks the pair: the peer
6142 has a confirmed link to us and flow-controls us, we cannot answer, so
6143 its @e outbound_fc_window_size stays at zero and it cannot send us a
6144 single byte -- not its CORE handshake, not DHT traffic -- while its
6145 `gnunet-transport' shows an established link with messages pending
6146 forever. It reached us over that queue, so answering on it is sound. */
6148 &fc->header,
6149 (GNUNET_YES == vl->confirmed)
6152 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
6153 {
6156 "FC retransmission to %s failed, will retry in %s\n",
6157 GNUNET_i2s (&vl->target),
6160 }
6161 else
6162 {
6163 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
6164 vl->last_fc_rtt = rtt;
6165 }
6166 if (NULL != vl->fc_retransmit_task)
6168 /* Never re-arm with (near) zero delay: @a rtt is zero whenever we have no
6169 RTT sample yet, which turned this into a tight send loop. */
6171 {
6172 /* Back off while the peer stays silent. Retransmitting at the plain RTT
6173 for #MAX_FC_RETRANSMIT_COUNT rounds is a flood on a link that is not
6174 being answered -- and a peer that cannot answer keeps *every* one of
6175 its links in exactly that state, which is enough traffic to make
6176 transport fall behind its communicators. */
6178
6179 for (unsigned int i = 0;
6180 (i < vl->fc_retransmit_count) && (rtt.rel_value_us < cap.rel_value_us);
6181 i++)
6182 rtt = GNUNET_TIME_relative_multiply (rtt, 2);
6183 rtt = GNUNET_TIME_relative_min (rtt, cap);
6184 }
6185 vl->fc_retransmit_task =
6188 vl->fc_retransmit_count++;
6189 GNUNET_free (fc);
6190}
6191
6192
6209static void
6211{
6212 struct Neighbour *n = vl->n;
6213 struct DistanceVector *dv = vl->dv;
6214 struct GNUNET_TIME_Absolute now;
6215 struct VirtualLink *vl_next_hop;
6216 int elig;
6217
6219 "check_vl_transmission to target %s\n",
6220 GNUNET_i2s (&vl->target));
6221 /* Check that we have an eligible pending message!
6222 (cheaper than having #transmit_on_queue() find out!) */
6223 elig = GNUNET_NO;
6224 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
6225 pm = pm->next_vl)
6226 {
6228 "check_vl_transmission loop\n");
6229 if (NULL != pm->qe)
6230 continue; /* not eligible, is in a queue! */
6231 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
6233 {
6235 "Stalled message %" PRIu64
6236 " transmission on VL %s due to flow control: %llu < %llu\n",
6237 pm->logging_uuid,
6238 GNUNET_i2s (&vl->target),
6239 (unsigned long long) vl->outbound_fc_window_size,
6240 (unsigned long long) (pm->bytes_msg
6243 return; /* We have a message, but flow control says "nope" */
6244 }
6246 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
6247 GNUNET_i2s (&vl->target));
6248 /* Notify queues at direct neighbours that we are interested */
6249 now = GNUNET_TIME_absolute_get ();
6250 if (NULL != n)
6251 {
6252 for (struct Queue *queue = n->queue_head; NULL != queue;
6253 queue = queue->next_neighbour)
6254 {
6255 if ((GNUNET_YES == queue->idle) &&
6256 (queue->validated_until.abs_value_us > now.abs_value_us))
6257 {
6259 "Direct neighbour %s not stalled\n",
6260 GNUNET_i2s (&n->pid));
6262 queue,
6264 elig = GNUNET_YES;
6265 }
6266 else
6268 "Neighbour Queue QID: %u (%u) busy or invalid\n",
6269 queue->qid,
6270 queue->idle);
6271 }
6272 }
6273 /* Notify queues via DV that we are interested */
6274 if (NULL != dv)
6275 {
6276 /* Do DV with lower scheduler priority, which effectively means that
6277 IF a neighbour exists and is available, we prefer it. */
6278 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6279 pos = pos->next_dv)
6280 {
6281 struct Neighbour *nh_iter = pos->next_hop;
6282
6283
6284 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
6285 continue; /* skip this one: path not validated */
6286 else
6287 {
6288 /* The next hop is a neighbour we have queues to; it need not have
6289 a virtual link of its own, and then there is no window of it to
6290 respect either. */
6291 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
6292 if ((NULL != vl_next_hop) &&
6293 (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
6294 vl_next_hop->outbound_fc_window_size))
6295 {
6297 "Stalled message %" PRIu64
6298 " transmission on next hop %s due to flow control: %llu < %llu\n",
6299 pm->logging_uuid,
6300 GNUNET_i2s (&vl_next_hop->target),
6301 (unsigned long
6302 long) vl_next_hop->outbound_fc_window_size,
6303 (unsigned long long) (pm->bytes_msg
6304 + vl_next_hop->
6305 outbound_fc_window_size_used));
6306 consider_sending_fc (vl_next_hop);
6307 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
6308 }
6309 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
6310 queue = queue->next_neighbour)
6311 if ((GNUNET_YES == queue->idle) &&
6312 (queue->validated_until.abs_value_us > now.abs_value_us))
6313 {
6315 "Next hop neighbour %s not stalled\n",
6316 GNUNET_i2s (&nh_iter->pid));
6318 queue,
6320 elig = GNUNET_YES;
6321 }
6322 else
6324 "DV Queue QID: %u (%u) busy or invalid\n",
6325 queue->qid,
6326 queue->idle);
6327 }
6328 }
6329 }
6330 if (GNUNET_YES == elig)
6332 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
6333 pm->logging_uuid,
6334 pm->bytes_msg,
6335 GNUNET_i2s (&vl->target),
6336 (unsigned long long) vl->outbound_fc_window_size,
6337 (unsigned long long) (pm->bytes_msg
6339 break;
6340 }
6341}
6342
6343
6350static void
6351handle_client_send (void *cls, const struct OutboundMessage *obm)
6352{
6353 struct TransportClient *tc = cls;
6354 struct PendingMessage *pm;
6355 const struct GNUNET_MessageHeader *obmm;
6356 uint32_t bytes_msg;
6357 struct VirtualLink *vl;
6359
6360 GNUNET_assert (CT_CORE == tc->type);
6361 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
6362 bytes_msg = ntohs (obmm->size);
6363 pp = ntohl (obm->priority);
6364 vl = lookup_virtual_link (&obm->peer);
6365 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6366 {
6368 "Don't have %s as a neighbour (anymore).\n",
6369 GNUNET_i2s (&obm->peer));
6370 /* Failure: don't have this peer as a neighbour (anymore).
6371 Might have gone down asynchronously, so this is NOT
6372 a protocol violation by CORE. Still count the event,
6373 as this should be rare. */
6374 /* Precisely because this is not a protocol violation we leave the
6375 client's `struct Neighbour' -- and its send window -- in place, so we
6376 owe it the SEND_OK for the message we are dropping here. Without it
6377 the window shrinks by one every time this happens and never grows
6378 back; after #SEND_WINDOW_SIZE such drops #mq_send_impl() parks every
6379 further message for this peer forever ("Flow control delays
6380 transmission to CORE until we see SEND_OK") and CORE goes mute
6381 towards a peer it still believes it is connected to -- while
6382 continuing to receive from it, so its own idle timeout is what
6383 eventually reports the peer down. */
6384 send_ok_to_client (tc, &obm->peer);
6387 "# messages dropped (neighbour unknown)",
6388 1,
6389 GNUNET_NO);
6390 return;
6391 }
6392
6393 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
6395 "1 created pm %p storing vl %p\n",
6396 pm,
6397 vl);
6399 pm->prefs = pp;
6400 pm->client = tc;
6401 pm->vl = vl;
6402 pm->bytes_msg = bytes_msg;
6403 memcpy (&pm[1], obmm, bytes_msg);
6405 "Sending message of type %u with %u bytes as <%" PRIu64
6406 "> to %s\n",
6407 ntohs (obmm->type),
6408 bytes_msg,
6409 pm->logging_uuid,
6410 GNUNET_i2s (&obm->peer));
6412 tc->details.core.pending_msg_head,
6413 tc->details.core.pending_msg_tail,
6414 pm);
6416 vl->pending_msg_head,
6417 vl->pending_msg_tail,
6418 pm);
6421}
6422
6423
6433static void
6435 void *cls,
6437{
6438 struct Neighbour *n;
6439 struct VirtualLink *vl;
6440 struct TransportClient *tc = cls;
6441 const struct GNUNET_MessageHeader *inbox =
6442 (const struct GNUNET_MessageHeader *) &cb[1];
6443 uint16_t isize = ntohs (inbox->size);
6444 const char *is = ((const char *) &cb[1]) + isize;
6445 size_t slen = strlen (is) + 1;
6446 char
6447 mbuf[slen + isize
6448 + sizeof(struct
6452
6453 /* 0-termination of 'is' was checked already in
6454 #check_communicator_backchannel() */
6456 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
6457 GNUNET_i2s (&cb->pid),
6458 is,
6459 ntohs (inbox->type),
6460 ntohs (inbox->size));
6461 /* encapsulate and encrypt message */
6462 be->header.type =
6464 be->header.size = htons (sizeof(mbuf));
6465 memcpy (&be[1], inbox, isize);
6466 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
6467 + isize],
6468 is,
6469 strlen (is) + 1);
6470 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
6471 vl = lookup_virtual_link (&cb->pid);
6472 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6473 {
6475 }
6476 else
6477 {
6478 /* Use route via neighbour */
6479 n = lookup_neighbour (&cb->pid);
6480 if (NULL != n)
6482 n,
6483 &be->header,
6484 RMO_NONE);
6485 }
6487}
6488
6489
6497static int
6499 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6500{
6501 struct TransportClient *tc = cls;
6502
6503 if (CT_COMMUNICATOR != tc->type)
6504 {
6505 GNUNET_break (0);
6506 return GNUNET_SYSERR;
6507 }
6509 return GNUNET_OK;
6510}
6511
6512
6518static void
6519store_pi (void *cls);
6520
6521
6526{
6527
6532
6537
6538
6543};
6544
6545
6552static void
6554{
6555 struct PilsAddressSignContext *pc = ale->pc;
6556
6557 if (NULL == pc)
6558 return;
6559 ale->pc = NULL;
6560 /* Each stage of the chain passes @a pc as its closure, so every handle
6561 that could still deliver one has to go before @a pc is released. */
6562 if (NULL != ale->sc)
6563 {
6565 ale->sc = NULL;
6566 }
6567 if (NULL != ale->shc)
6568 {
6570 ale->shc = NULL;
6571 }
6572 if (NULL != pc->req)
6573 {
6574 if (NULL != pc->req->op)
6575 GNUNET_PILS_cancel (pc->req->op);
6578 pc->req);
6579 GNUNET_free (pc->req);
6580 pc->req = NULL;
6581 }
6582 GNUNET_free (pc);
6583}
6584
6585
6586static void
6587shc_cont (void *cls, int success)
6588{
6589 struct PilsAddressSignContext *pc = cls;
6590
6591 GNUNET_assert (NULL == pc->req);
6592 /* The store completed; the handle is dead and must not be cancelled
6593 later by #free_address_list_entry(). */
6594 pc->ale->shc = NULL;
6595 pc->ale->pc = NULL;
6596 if (GNUNET_OK != success)
6597 {
6599 "Failed to store our address `%s' with peerstore\n",
6600 pc->ale->address);
6601 if (NULL == pc->ale->st)
6602 {
6604 &store_pi,
6605 pc->ale);
6606 }
6607 }
6608 GNUNET_free (pc);
6609}
6610
6611
6615static void
6617 const struct GNUNET_PeerIdentity *pid,
6618 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6619{
6620 struct PilsAddressSignContext *pc = cls;
6621 struct GNUNET_MQ_Envelope *env;
6622 const struct GNUNET_MessageHeader *msg;
6623
6624 pc->req->op = NULL;
6627 pc->req);
6628 GNUNET_free (pc->req);
6629 pc->req = NULL;
6632 pid,
6633 sig,
6634 pc->et);
6637 "store_pi 1\n");
6639 msg,
6640 shc_cont,
6641 pc);
6642 GNUNET_free (env);
6643}
6644
6645
6652static void
6653peerstore_store_own_cb (void *cls, int success)
6654{
6655 struct PilsAddressSignContext *pc = cls;
6656
6657 pc->ale->sc = NULL;
6658 if (GNUNET_YES != success)
6660 "Failed to store our own address `%s' in peerstore!\n",
6661 pc->ale->address);
6662 else
6664 "Successfully stored our own address `%s' in peerstore!\n",
6665 pc->ale->address);
6666 /* refresh period is 1/4 of expiration time, that should be plenty
6667 without being excessive. */
6668 if (NULL == pc->ale->st)
6669 {
6670 pc->ale->st =
6672 GNUNET_TIME_relative_divide (pc->ale->expiration,
6673 4ULL),
6674 &store_pi,
6675 pc->ale);
6676 }
6677
6678 /* Now we have to update our HELLO! */
6680 pc->req = GNUNET_new (struct PilsRequest);
6683 pc->req);
6684 pc->req->op = GNUNET_PILS_sign_hello (pils,
6686 pc->et,
6688 pc);
6689}
6690
6691
6699static void
6701 const struct GNUNET_PeerIdentity *pid,
6702 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6703{
6704 char *sig_str;
6705 void *result;
6706 size_t result_size;
6707
6708 sig_str = NULL;
6709 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6710 result_size =
6711 1 + GNUNET_asprintf (
6712 (char **) &result,
6713 "%s;%llu;%u;%s",
6714 sig_str,
6715 (unsigned long long) pc->et.abs_value_us,
6716 (unsigned int) pc->ale->nt,
6717 pc->ale->address);
6718 GNUNET_free (sig_str);
6719
6721 "Build our HELLO URI `%s'\n",
6722 (char*) result);
6723
6724 GNUNET_free (pc->ale->signed_address);
6725 pc->ale->signed_address = result;
6726 pc->ale->signed_address_len = result_size;
6728
6729 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6731 "transport",
6732 pid,
6734 result,
6735 result_size,
6736 expiration,
6739 pc);
6740}
6741
6742
6763
6764
6778void
6780 struct AddressListEntry *ale,
6781 struct GNUNET_TIME_Absolute mono_time)
6782{
6783 struct SignedAddress sa;
6784 struct PilsAddressSignContext *pc;
6786 const struct GNUNET_PeerIdentity *my_identity;
6787
6789 sa.purpose.size = htonl (sizeof(sa));
6790 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6791 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6792 /* Only ever one chain per entry: the previous one (if any) still holds a
6793 pointer to @a ale and must be torn down first. */
6796 if ((NULL == my_identity) ||
6797 (GNUNET_OK != sign_by_my_identity (&sa.purpose, &sig)))
6798 {
6799 /* Nothing else re-arms @e st: #store_pi() cleared it before calling us,
6800 and the only other thing that sets it is #peerstore_store_own_cb(),
6801 which is on the far side of the store we just failed to start. So a
6802 single failure to sign used to end the refresh cycle for this address
6803 for the rest of the process' life. */
6804 if (NULL == ale->st)
6805 {
6808 &store_pi,
6809 ale);
6810 }
6811 return;
6812 }
6814 pc->ale = ale;
6815 pc->et = mono_time;
6816 ale->pc = pc;
6818}
6819
6820
6826static void
6827store_pi (void *cls)
6828{
6829 struct AddressListEntry *ale = cls;
6830 const char *dash;
6831 char *address_uri;
6832 char *prefix;
6833 unsigned int add_success;
6834
6835 if ((GNUNET_YES == in_shutdown) || (NULL == pils))
6836 {
6837 ale->st = NULL;
6838 return;
6839 }
6840 if (NULL == GNUNET_PILS_get_identity (pils))
6841 {
6842 /* Do NOT poll at 1kHz: that burns CPU and keeps the scheduler task
6843 list non-empty, which prevents the service from ever exiting. */
6846 &store_pi,
6847 ale);
6848 return;
6849 }
6852 dash = strchr (ale->address, '-');
6853 GNUNET_assert (NULL != dash);
6854 dash++;
6855 GNUNET_asprintf (&address_uri,
6856 "%s://%s",
6857 prefix,
6858 dash);
6860 ale->st = NULL;
6862 "Storing our address `%s' in peerstore until %s!\n",
6863 ale->address,
6866 address_uri);
6867 /* NOTE: #GNUNET_HELLO_builder_add_address() answers GNUNET_NO for an
6868 address that is already in the builder, and on every call after the
6869 first one for a given address that is exactly what happens: nothing
6870 ever removes an address from @a GST_my_hello except
6871 #handle_del_address(). This function is the *refresh* cycle --
6872 #peerstore_store_own_cb() re-arms it at a quarter of the address'
6873 expiration -- so bailing out on GNUNET_NO here stopped the refresh
6874 after precisely one round. Our own HELLO then expired
6875 (#GNUNET_HELLO_ADDRESS_EXPIRATION, twelve hours) and was never
6876 renewed: peers can no longer learn how to reach us, and a link that
6877 drops after that never comes back. Only GNUNET_SYSERR -- a malformed
6878 URI, which retrying cannot fix -- is a reason not to store. */
6879 if (GNUNET_SYSERR == add_success)
6880 {
6882 "Not storing our address `%s': not a valid HELLO URI\n",
6883 address_uri);
6884 GNUNET_free (address_uri);
6885 return;
6886 }
6887 GNUNET_log ((GNUNET_NO == add_success) ?
6889 "%s our address `%s' in PEERSTORE\n",
6890 (GNUNET_NO == add_success) ? "Refreshing" : "Storing",
6891 address_uri);
6892 // FIXME hello_mono_time used here?? What about expiration in ale?
6893 pils_sign_address (ale,
6895 // TODO keep track of op and potentially cancel/clean
6896 GNUNET_free (address_uri);
6897}
6898
6899
6900static struct AddressListEntry *
6904 const char *address,
6905 uint32_t aid,
6906 size_t slen)
6907{
6908 struct AddressListEntry *ale;
6909 char *address_without_port;
6910
6911 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6912 ale->tc = tc;
6913 ale->address = (const char *) &ale[1];
6914 ale->expiration = expiration;
6915 ale->aid = aid;
6916 ale->nt = nt;
6917 memcpy (&ale[1], address, slen);
6918 address_without_port = get_address_without_port (ale->address);
6920 "Is this %s a local address (%s)\n",
6921 (NULL == address_without_port) ? "<unparsable>"
6922 : address_without_port,
6923 ale->address);
6924 if ((NULL == address_without_port) ||
6925 (0 != strcmp ("127.0.0.1", address_without_port)))
6926 {
6927 if (NULL != ale->st)
6928 {
6930 }
6931 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6932 }
6933 GNUNET_free (address_without_port);
6934
6935 return ale;
6936}
6937
6938
6939static void
6941{
6942
6944 "Feeding addresses to PILS\n");
6945 pils_feed_task = NULL;
6946
6948 GST_my_hello);
6949}
6950
6951
6958static void
6960 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6961{
6962 struct TransportClient *tc = cls;
6963 struct AddressListEntry *ale;
6964 size_t slen;
6965 char *address;
6966
6967 /* 0-termination of &aam[1] was checked in #check_add_address */
6969 "Communicator added address `%s'!\n",
6970 (const char *) &aam[1]);
6971 slen = ntohs (aam->header.size) - sizeof(*aam);
6972 address = GNUNET_malloc (slen);
6973 memcpy (address, &aam[1], slen);
6974 ale = create_address_entry (tc,
6976 ntohl (aam->nt),
6977 address,
6978 aam->aid,
6979 slen);
6980 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6981 tc->details.communicator.addr_tail,
6982 ale);
6983 {
6984 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6985 NULL != iter;
6986 iter = iter->next)
6987 {
6988 char *address_uri;
6989 const char *dash = strchr (iter->address, '-');
6990 char *prefix = GNUNET_HELLO_address_to_prefix (iter->address);
6991 GNUNET_assert (NULL != dash);
6992 dash++;
6993 GNUNET_asprintf (&address_uri,
6994 "%s://%s",
6995 prefix,
6996 dash);
6999 GNUNET_free (address_uri);
7000 }
7001 if (NULL != pils_feed_task)
7005 NULL);
7006 }
7009}
7010
7011
7018static void
7020 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
7021{
7022 struct TransportClient *tc = cls;
7023 struct AddressListEntry *alen;
7024
7025 if (CT_COMMUNICATOR != tc->type)
7026 {
7027 GNUNET_break (0);
7029 return;
7030 }
7031 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
7032 NULL != ale;
7033 ale = alen)
7034 {
7035 alen = ale->next;
7036 if (dam->aid != ale->aid)
7037 continue;
7038 GNUNET_assert (ale->tc == tc);
7040 "Communicator deleted address `%s'!\n",
7041 ale->address);
7043 ale->address);
7044 if (NULL != pils_feed_task)
7048 NULL);
7051 return;
7052 }
7054 "Communicator removed address we did not even have.\n");
7056 // GNUNET_SERVICE_client_drop (tc->client);
7057}
7058
7059
7067static void
7069
7070
7078static void
7080{
7081 struct CoreSentContext *ctx = cls;
7082 struct VirtualLink *vl = ctx->vl;
7083
7084 if (NULL == vl)
7085 {
7086 /* lost the link in the meantime, ignore */
7087 GNUNET_free (ctx);
7088 return;
7089 }
7092 vl->incoming_fc_window_size_ram -= ctx->size;
7093 vl->incoming_fc_window_size_used += ctx->isize;
7095 GNUNET_free (ctx);
7096}
7097
7098
7120static void
7122{
7123 struct VirtualLink *vl = cls;
7124 struct CommunicatorMessageContext *cmc;
7125
7126 vl->core_fc_stall_task = NULL;
7128 "CORE did not acknowledge messages from %s within %s; "
7129 "releasing the flow control credit anyway\n",
7130 GNUNET_i2s (&vl->target),
7132 GNUNET_YES));
7134 "# CORE flow control stalls",
7135 1,
7136 GNUNET_NO);
7137 while (NULL != (cmc = vl->cmc_tail))
7138 release_stalled_cmc (vl, cmc);
7141}
7142
7143
7144static void
7146 const struct GNUNET_MessageHeader *mh,
7147 struct CommunicatorMessageContext *cmc,
7148 unsigned int free_cmc)
7149{
7150 uint16_t size = ntohs (mh->size);
7151 int have_core;
7152
7153 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
7154 {
7156 "# CORE messages dropped (FC arithmetic overflow)",
7157 1,
7158 GNUNET_NO);
7160 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
7161 (unsigned int) ntohs (mh->type),
7162 (unsigned int) ntohs (mh->size));
7163 if (GNUNET_YES == free_cmc)
7165 return;
7166 }
7168 {
7170 "# CORE messages dropped (FC window overflow)",
7171 1,
7172 GNUNET_NO);
7174 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
7175 (unsigned int) ntohs (mh->type),
7176 (unsigned int) ntohs (mh->size));
7177 if (GNUNET_YES == free_cmc)
7179 return;
7180 }
7181
7182 /* Forward to all CORE clients */
7183 have_core = GNUNET_NO;
7184 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
7185 {
7186 struct GNUNET_MQ_Envelope *env;
7187 struct InboundMessage *im;
7188 struct CoreSentContext *ctx;
7189
7190 if (CT_CORE != tc->type)
7191 continue;
7194 ctx = GNUNET_new (struct CoreSentContext);
7195 ctx->vl = vl;
7196 ctx->size = size;
7197 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
7198 have_core = GNUNET_YES;
7201 im->peer = cmc->im.sender;
7202 memcpy (&im[1], mh, size);
7203 GNUNET_MQ_send (tc->mq, env);
7205 }
7206 if (GNUNET_NO == have_core)
7207 {
7209 "Dropped message to CORE: no CORE client connected!\n");
7210 /* Nevertheless, count window as used, as it is from the
7211 perspective of the other peer! */
7213 /* TODO-M1 */
7215 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
7216 (unsigned int) ntohs (mh->type),
7217 (unsigned int) ntohs (mh->size));
7218 if (GNUNET_YES == free_cmc)
7220 return;
7221 }
7223 "Delivered message from %s of type %u to CORE recv window %d\n",
7224 GNUNET_i2s (&cmc->im.sender),
7225 ntohs (mh->type),
7227 if (vl->core_recv_window > 0)
7228 {
7229 if (GNUNET_YES == free_cmc)
7231 return;
7232 }
7233 /* CORE ran out of receive window for *this* link. Withhold the
7234 per-message ACK -- that is what expresses the backpressure -- but
7235 resume the client immediately. The client is the communicator
7236 *process*, which carries every peer we reach through it, and a
7237 communicator we stop reading from does not stop receiving: it starts
7238 discarding, see "transport is too slow" in
7239 #GNUNET_TRANSPORT_communicator_receive(). Discarding is precisely
7240 what we cannot afford here, because among the messages dropped are
7241 the ones CORE needs in order to reopen the window it is waiting on. */
7242 if (GNUNET_YES == free_cmc)
7243 {
7244 resume_cmc_client (cmc);
7246 vl->cmc_count++;
7247 /* Nothing stalls the producer any more, so bound the list ourselves. */
7248 while (MAX_STALLED_CMCS < vl->cmc_count)
7250 /* ... and do not withhold the ACKs forever: see #core_fc_stalled(). */
7251 if (NULL == vl->core_fc_stall_task)
7255 vl);
7256 }
7257}
7258
7259
7268static void
7270{
7271 struct CommunicatorMessageContext *cmc = cls;
7272 // struct CommunicatorMessageContext *cmc_copy =
7273 // GNUNET_new (struct CommunicatorMessageContext);
7274 struct GNUNET_MessageHeader *mh_copy;
7275 struct RingBufferEntry *rbe;
7276 struct VirtualLink *vl;
7277 uint16_t size = ntohs (mh->size);
7278
7280 "Handling raw message of type %u with %u bytes\n",
7281 (unsigned int) ntohs (mh->type),
7282 (unsigned int) ntohs (mh->size));
7283
7284 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
7285 (size < sizeof(struct GNUNET_MessageHeader)))
7286 {
7287 /* @a mh was unwrapped from what a *remote peer* sent us, so a bad size
7288 is that peer's protocol violation and says nothing about the
7289 communicator that carried it. Dropping the client here disconnects
7290 the communicator process and with it every neighbour reachable
7291 through it -- see the rationale in #demultiplex_with_cmc(). */
7292 GNUNET_break_op (0);
7294 "# CORE messages dropped (bad size)",
7295 1,
7296 GNUNET_NO);
7297 finish_cmc_handling (cmc);
7298 return;
7299 }
7300 vl = lookup_virtual_link (&cmc->im.sender);
7301 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
7302 {
7303 /* FIXME: sender is giving us messages for CORE but we don't have
7304 the link up yet! I *suspect* this can happen right now (i.e.
7305 sender has verified us, but we didn't verify sender), but if
7306 we pass this on, CORE would be confused (link down, messages
7307 arrive). We should investigate more if this happens often,
7308 or in a persistent manner, and possibly do "something" about
7309 it. Thus logging as error for now. */
7310
7311 mh_copy = GNUNET_malloc (size);
7312 rbe = GNUNET_new (struct RingBufferEntry);
7313 rbe->cmc = cmc;
7314 /*cmc_copy->tc = cmc->tc;
7315 cmc_copy->im = cmc->im;*/
7316 GNUNET_memcpy (mh_copy, mh, size);
7317
7318 rbe->mh = mh_copy;
7319
7321 {
7322 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
7323 GNUNET_free (rbe_old->cmc);
7324 GNUNET_free (rbe_old->mh);
7325 GNUNET_free (rbe_old);
7326 }
7327 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
7328 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
7329 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
7331 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
7332 GNUNET_i2s (&cmc->im.sender),
7333 (unsigned int) ntohs (mh->type),
7334 (unsigned int) ntohs (mh_copy->type),
7338 {
7339 ring_buffer_head = 0;
7341 }
7342 else
7344
7346 "%u items stored in ring buffer\n",
7349
7350 /*GNUNET_break_op (0);
7351 GNUNET_STATISTICS_update (GST_stats,
7352 "# CORE messages dropped (virtual link still down)",
7353 1,
7354 GNUNET_NO);
7355
7356 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7357 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
7358 (unsigned int) ntohs (mh->type),
7359 (unsigned int) ntohs (mh->size));
7360 finish_cmc_handling (cmc);*/
7361 /* @a cmc lives on in the ring buffer; #send_cmc_ack() and
7362 #resume_cmc_client() have recorded that they ran, so replaying it
7363 from #send_msg_from_cache() cannot ACK or continue a second time. */
7365 return;
7366 }
7368}
7369
7370
7378static int
7380{
7381 uint16_t size = ntohs (fb->header.size);
7382 uint16_t bsize = size - sizeof(*fb);
7383
7384 (void) cls;
7385 if (0 == bsize)
7386 {
7387 GNUNET_break_op (0);
7388 return GNUNET_SYSERR;
7389 }
7390 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
7391 {
7392 GNUNET_break_op (0);
7393 return GNUNET_SYSERR;
7394 }
7395 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
7396 {
7397 GNUNET_break_op (0);
7398 return GNUNET_SYSERR;
7399 }
7400 return GNUNET_YES;
7401}
7402
7403
7409static void
7411{
7412 struct AcknowledgementCummulator *ac = cls;
7413
7414 ac->task = NULL;
7415 GNUNET_assert (0 == ac->num_acks);
7417 GNUNET_YES ==
7419 GNUNET_free (ac);
7420}
7421
7422
7428static void
7430{
7431 struct Neighbour *n;
7432 struct VirtualLink *vl;
7433 struct AcknowledgementCummulator *ac = cls;
7434 char buf[sizeof(struct TransportReliabilityAckMessage)
7435 + ac->num_acks
7437 struct TransportReliabilityAckMessage *ack =
7438 (struct TransportReliabilityAckMessage *) buf;
7440
7441 ac->task = NULL;
7443 "Sending ACK with %u components to %s\n",
7444 ac->num_acks,
7445 GNUNET_i2s (&ac->target));
7446 GNUNET_assert (0 < ac->num_acks);
7448 ack->header.size =
7449 htons (sizeof(*ack)
7450 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
7451 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
7452 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
7453 for (unsigned int i = 0; i < ac->num_acks; i++)
7454 {
7455 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
7458 }
7459 /*route_control_message_without_fc (
7460 &ac->target,
7461 &ack->header,
7462 RMO_DV_ALLOWED);*/
7463 vl = lookup_virtual_link (&ac->target);
7464 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7465 {
7467 vl,
7468 &ack->header,
7470 }
7471 else
7472 {
7473 /* Use route via neighbour */
7474 n = lookup_neighbour (&ac->target);
7475 if (NULL != n)
7477 n,
7478 &ack->header,
7479 RMO_NONE);
7480 }
7481 ac->num_acks = 0;
7484 ac);
7485}
7486
7487
7496static void
7498 const struct AcknowledgementUUIDP *ack_uuid,
7499 struct GNUNET_TIME_Absolute max_delay)
7500{
7501 struct AcknowledgementCummulator *ac;
7502
7504 "Scheduling ACK %s for transmission to %s\n",
7505 GNUNET_uuid2s (&ack_uuid->value),
7506 GNUNET_i2s (pid));
7508 if (NULL == ac)
7509 {
7511 ac->target = *pid;
7512 ac->min_transmission_time = max_delay;
7516 &ac->target,
7517 ac,
7519 }
7520 else
7521 {
7522 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
7523 {
7524 /* Must run immediately, ack buffer full. Cancel the pending task
7525 FIRST: #transmit_cummulative_ack_cb() clears @e task without
7526 cancelling it, which would leave the old task armed with its
7527 handle lost. */
7529 ac->task = NULL;
7531 }
7535 }
7538 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
7539 ac->num_acks++;
7542 ac);
7543}
7544
7545
7561
7562
7572static int
7573find_by_message_uuid (void *cls, uint32_t key, void *value)
7574{
7575 struct FindByMessageUuidContext *fc = cls;
7576 struct ReassemblyContext *rc = value;
7577
7578 (void) key;
7579 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
7580 {
7581 fc->rc = rc;
7582 return GNUNET_NO;
7583 }
7584 return GNUNET_YES;
7585}
7586
7587
7595static void
7597{
7598 struct CommunicatorMessageContext *cmc = cls;
7599 struct VirtualLink *vl;
7600 struct ReassemblyContext *rc;
7601 const struct GNUNET_MessageHeader *msg;
7602 uint16_t msize;
7603 uint16_t fsize;
7604 uint16_t frag_off;
7605 char *target;
7606 struct GNUNET_TIME_Relative cdelay;
7607 struct FindByMessageUuidContext fc;
7608
7609 vl = lookup_virtual_link (&cmc->im.sender);
7610 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
7611 {
7612 /* Entirely normal: fragments of a message that was already in flight
7613 keep arriving for a while after a link goes down, and a peer that has
7614 validated us may start sending before we have validated it. This used
7615 to call #GNUNET_SERVICE_client_drop(), which disconnects the
7616 communicator *process* -- every queue it owns, hence every neighbour
7617 reachable through it, hence every CORE session. On a peer with many
7618 neighbours a single ill-timed fragment therefore dropped all
7619 connections at once, and since the fragment comes from the network,
7620 any peer could cause it at will. Drop the fragment, keep the
7621 communicator; see #demultiplex_with_cmc() for the same reasoning. */
7623 "No virtual link for %s to handle fragment\n",
7624 GNUNET_i2s (&cmc->im.sender));
7626 "# fragments dropped (virtual link down)",
7627 1,
7628 GNUNET_NO);
7629 finish_cmc_handling (cmc);
7630 return;
7631 }
7632 if (NULL == vl->reassembly_map)
7633 {
7635 vl->reassembly_heap =
7640 vl);
7641 }
7642 msize = ntohs (fb->msg_size);
7643 fc.message_uuid = fb->msg_uuid;
7644 fc.rc = NULL;
7646 fb->msg_uuid.uuid,
7648 &fc);
7649 fsize = ntohs (fb->header.size) - sizeof(*fb);
7650 if (NULL == (rc = fc.rc))
7651 {
7652 /* Bound the RAM a single sender can pin here: @e msg_size is chosen by
7653 the peer, not by us. */
7656 {
7657 struct ReassemblyContext *drop;
7658
7660 GNUNET_assert (NULL != drop);
7662 "# Reassembly contexts dropped (limit reached)",
7663 1,
7664 GNUNET_NO);
7666 }
7667 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
7668 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
7669 rc->msg_uuid = fb->msg_uuid;
7670 rc->virtual_link = vl;
7671 rc->msg_size = msize;
7672 rc->reassembly_timeout =
7676 rc,
7680 vl->reassembly_map,
7681 rc->msg_uuid.uuid,
7682 rc,
7684 target = (char *) &rc[1];
7685 rc->bitfield = (uint8_t *) (target + rc->msg_size);
7686 /* The bitfield loop below decrements @e msg_missing once per newly
7687 received byte, so this must always start at the full message size:
7688 initialising it to 0 for a single-fragment message made it
7689 underflow, and the message was then never delivered. */
7690 rc->msg_missing = rc->msg_size;
7692 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
7693 PRIu64 "\n",
7694 fsize,
7695 ntohs (fb->frag_off),
7696 msize,
7697 rc->msg_missing,
7698 GNUNET_i2s (&cmc->im.sender),
7699 fb->msg_uuid.uuid);
7700 }
7701 else
7702 {
7703 target = (char *) &rc[1];
7705 "Received fragment at offset %u/%u from %s for message %u\n",
7706 ntohs (fb->frag_off),
7707 msize,
7708 GNUNET_i2s (&cmc->im.sender),
7709 (unsigned int) fb->msg_uuid.uuid);
7710 }
7711 if (msize != rc->msg_size)
7712 {
7713 GNUNET_break (0);
7714 finish_cmc_handling (cmc);
7715 return;
7716 }
7717
7718 /* reassemble */
7719 if (0 == fsize)
7720 {
7721 GNUNET_break (0);
7722 finish_cmc_handling (cmc);
7723 return;
7724 }
7725 frag_off = ntohs (fb->frag_off);
7726 if (frag_off + fsize > msize)
7727 {
7728 /* Fragment (plus fragment size) exceeds message size! */
7729 GNUNET_break_op (0);
7730 finish_cmc_handling (cmc);
7731 return;
7732 }
7733 memcpy (&target[frag_off], &fb[1], fsize);
7734 /* update bitfield and msg_missing */
7735 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
7736 {
7737 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
7738 {
7739 rc->bitfield[i / 8] |= (1 << (i % 8));
7740 rc->msg_missing--;
7741 }
7742 }
7743
7744 /* Compute cumulative ACK */
7746 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
7747 if (0 == rc->msg_missing)
7748 cdelay = GNUNET_TIME_UNIT_ZERO;
7749 cummulative_ack (&cmc->im.sender,
7750 &fb->ack_uuid,
7753 /* is reassembly complete? */
7754 if (0 != rc->msg_missing)
7755 {
7756 finish_cmc_handling (cmc);
7757 return;
7758 }
7759 /* reassembly is complete, verify result */
7760 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7761 if (ntohs (msg->size) != rc->msg_size)
7762 {
7763 GNUNET_break (0);
7765 finish_cmc_handling (cmc);
7766 return;
7767 }
7768 /* successful reassembly */
7770 "Fragment reassembly complete for message %u\n",
7771 (unsigned int) fb->msg_uuid.uuid);
7772 /* FIXME: check that the resulting msg is NOT a
7773 DV Box or Reliability Box, as that is NOT allowed! */
7774 {
7775 uint16_t rsize = rc->msg_size;
7776 char rbuf[rsize] GNUNET_ALIGN;
7777
7778 /* Copy the reassembled message out and release `rc' BEFORE
7779 demultiplexing: the inner message may tear down the virtual link,
7780 which frees every reassembly context of that link -- the old code
7781 then used and freed `rc' a second time afterwards. */
7782 memcpy (rbuf, msg, rsize);
7784 cmc->mh = (const struct GNUNET_MessageHeader *) rbuf;
7786 }
7787}
7788
7789
7797static int
7799 const struct TransportReliabilityBoxMessage *rb)
7800{
7801 const struct GNUNET_MessageHeader *box = (const struct
7802 GNUNET_MessageHeader *) &rb[1];
7803 (void) cls;
7804
7806 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7807 ntohs (rb->header.size),
7808 ntohs (box->type),
7809 ntohs (box->size),
7810 sizeof (struct TransportReliabilityBoxMessage),
7811 sizeof (struct GNUNET_MessageHeader));
7813 return GNUNET_YES;
7814}
7815
7816
7824static void
7826 const struct TransportReliabilityBoxMessage *rb)
7827{
7828 struct CommunicatorMessageContext *cmc = cls;
7829 const struct GNUNET_MessageHeader *inbox =
7830 (const struct GNUNET_MessageHeader *) &rb[1];
7831 struct GNUNET_TIME_Relative rtt;
7832
7834 "Received reliability box from %s with UUID %s of type %u\n",
7835 GNUNET_i2s (&cmc->im.sender),
7837 (unsigned int) ntohs (inbox->type));
7838 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
7839 do not really have an RTT for the
7840 * incoming* queue (should we have
7841 the sender add it to the rb message?) */
7843 &cmc->im.sender,
7844 &rb->ack_uuid,
7845 (0 == ntohl (rb->ack_countdown))
7848 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
7849 /* continue with inner message */
7850 /* FIXME: check that inbox is NOT a DV Box, fragment or another
7851 reliability box (not allowed!) */
7852 cmc->mh = inbox;
7854}
7855
7856
7865static void
7866update_pd_age (struct PerformanceData *pd, unsigned int age)
7867{
7868 unsigned int sage;
7869
7870 if (age == pd->last_age)
7871 return; /* nothing to do */
7872 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7873 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7874 {
7875 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7876
7877 the->bytes_sent = 0;
7878 the->bytes_received = 0;
7879 }
7880 pd->last_age = age;
7881}
7882
7883
7892static void
7894 struct GNUNET_TIME_Relative rtt,
7895 uint16_t bytes_transmitted_ok)
7896{
7897 uint64_t nval = rtt.rel_value_us;
7898 uint64_t oval = pd->aged_rtt.rel_value_us;
7899 unsigned int age = get_age ();
7900 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7901
7902 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7903 pd->aged_rtt = rtt;
7904 else
7905 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7906 update_pd_age (pd, age);
7907 the->bytes_received += bytes_transmitted_ok;
7908}
7909
7910
7918static void
7920 struct GNUNET_TIME_Relative rtt,
7921 uint16_t bytes_transmitted_ok)
7922{
7923 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7924}
7925
7926
7934static void
7936 struct GNUNET_TIME_Relative rtt,
7937 uint16_t bytes_transmitted_ok)
7938{
7939 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7940}
7941
7942
7950static void
7952{
7953 struct PendingMessage *pos;
7954
7956 "Complete transmission of message %" PRIu64 " %u\n",
7957 pm->logging_uuid,
7958 pm->pmt);
7959 switch (pm->pmt)
7960 {
7961 case PMT_CORE:
7963 /* Full message sent, we are done */
7965 return;
7966
7967 case PMT_FRAGMENT_BOX:
7968 /* Fragment sent over reliable channel */
7969 pos = pm->frag_parent;
7970 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
7973 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7974 (unsigned long) pos->frag_off,
7975 (unsigned long) pos->bytes_msg,
7976 pos->pmt,
7977 NULL == pos->frag_parent ? 1 : 0);
7978 /* check if subtree is done */
7979 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7980 - sizeof(struct
7982 &&
7983 (NULL != pos->frag_parent))
7984 {
7985 pm = pos;
7986 pos = pm->frag_parent;
7987 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7988 {
7990 return;
7991 }
7992 else if (PMT_DV_BOX == pm->pmt)
7993 {
7995 return;
7996 }
7997 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
7999 }
8000
8001 /* Was this the last applicable fragment? */
8002 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
8003 pos->pmt) &&
8004 (pos->frag_off == pos->bytes_msg))
8006 return;
8007
8008 case PMT_DV_BOX:
8010 "Completed transmission of message %" PRIu64 " (DV Box)\n",
8011 pm->logging_uuid);
8012 if (NULL != pm->frag_parent)
8013 {
8014 pos = pm->frag_parent;
8016 pos->bpm = NULL;
8018 }
8019 else
8021 return;
8022 }
8023}
8024
8025
8033static void
8035 struct GNUNET_TIME_Relative ack_delay)
8036{
8037 struct GNUNET_TIME_Relative delay;
8038
8040 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
8041 if (NULL != pa->queue && 1 == pa->num_send)
8043 if (NULL != pa->dvh && 1 == pa->num_send)
8044 update_dvh_performance (pa->dvh, delay, pa->message_size);
8045 if (NULL != pa->pm)
8048}
8049
8050
8058static int
8060 const struct TransportReliabilityAckMessage *ra)
8061{
8062 unsigned int n_acks;
8063
8064 (void) cls;
8065 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
8066 / sizeof(struct TransportCummulativeAckPayloadP);
8067 if (0 == n_acks)
8068 {
8069 GNUNET_break_op (0);
8070 return GNUNET_SYSERR;
8071 }
8072 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
8073 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
8074 {
8075 GNUNET_break_op (0);
8076 return GNUNET_SYSERR;
8077 }
8078 return GNUNET_OK;
8079}
8080
8081
8089static void
8091 const struct TransportReliabilityAckMessage *ra)
8092{
8093 struct CommunicatorMessageContext *cmc = cls;
8094 const struct TransportCummulativeAckPayloadP *ack;
8095 unsigned int n_acks;
8096 uint32_t ack_counter;
8097
8098 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
8099 / sizeof(struct TransportCummulativeAckPayloadP);
8100 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
8101 for (unsigned int i = 0; i < n_acks; i++)
8102 {
8103 struct PendingAcknowledgement *pa =
8105 if (NULL == pa)
8106 {
8108 "Received ACK from %s with UUID %s which is unknown to us!\n",
8109 GNUNET_i2s (&cmc->im.sender),
8110 GNUNET_uuid2s (&ack[i].ack_uuid.value));
8112 GST_stats,
8113 "# FRAGMENT_ACKS dropped, no matching pending message",
8114 1,
8115 GNUNET_NO);
8116 continue;
8117 }
8119 "Received ACK from %s with UUID %s\n",
8120 GNUNET_i2s (&cmc->im.sender),
8121 GNUNET_uuid2s (&ack[i].ack_uuid.value));
8122 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
8123 }
8124
8125 ack_counter = ntohl (ra->ack_counter);
8126 (void) ack_counter; /* silence compiler warning for now */
8127 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
8128 // (DV and/or Neighbour?)
8129 finish_cmc_handling (cmc);
8130}
8131
8132
8140static int
8142 void *cls,
8144{
8145 uint16_t size = ntohs (be->header.size) - sizeof(*be);
8146 const struct GNUNET_MessageHeader *inbox =
8147 (const struct GNUNET_MessageHeader *) &be[1];
8148 const char *is;
8149 uint16_t isize;
8150
8151 (void) cls;
8152 /* MUST bound the buffer before reading @a inbox: the size check below
8153 dereferences it, and a message consisting of nothing but the header
8154 leaves no bytes to read. */
8155 if (size <= sizeof(struct GNUNET_MessageHeader))
8156 {
8157 GNUNET_break_op (0);
8158 return GNUNET_SYSERR;
8159 }
8160 if (ntohs (inbox->size) >= size)
8161 {
8162 GNUNET_break_op (0);
8163 return GNUNET_SYSERR;
8164 }
8165 isize = ntohs (inbox->size);
8166 is = ((const char *) inbox) + isize;
8167 size -= isize;
8168 if ('\0' != is[size - 1])
8169 {
8170 GNUNET_break_op (0);
8171 return GNUNET_SYSERR;
8172 }
8173 return GNUNET_YES;
8174}
8175
8176
8185static void
8187 void *cls,
8189{
8190 const struct GNUNET_PeerIdentity *my_identity;
8191 struct CommunicatorMessageContext *cmc = cls;
8193 struct GNUNET_MQ_Envelope *env;
8194 struct TransportClient *tc;
8195 const struct GNUNET_MessageHeader *inbox =
8196 (const struct GNUNET_MessageHeader *) &be[1];
8197 uint16_t isize = ntohs (inbox->size);
8198 const char *target_communicator = ((const char *) inbox) + isize;
8199 char *sender;
8200 char *self;
8201
8204
8205 GNUNET_asprintf (&sender,
8206 "%s",
8207 GNUNET_i2s (&cmc->im.sender));
8208 GNUNET_asprintf (&self,
8209 "%s",
8211
8212 /* Find client providing this communicator */
8213 for (tc = clients_head; NULL != tc; tc = tc->next)
8214 if ((CT_COMMUNICATOR == tc->type) &&
8215 (NULL != tc->details.communicator.address_prefix) &&
8216 (0 ==
8217 strcmp (tc->details.communicator.address_prefix, target_communicator)))
8218 break;
8219 if (NULL == tc)
8220 {
8221 char *stastr;
8222
8224 &stastr,
8225 "# Backchannel message dropped: target communicator `%s' unknown",
8226 target_communicator);
8228 GNUNET_free (stastr);
8229 GNUNET_free (sender);
8230 GNUNET_free (self);
8231 finish_cmc_handling (cmc);
8232 return;
8233 }
8234 /* Finally, deliver backchannel message to communicator */
8236 "Delivering backchannel message from %s to %s of type %u to %s\n",
8237 sender,
8238 self,
8239 ntohs (inbox->type),
8240 target_communicator);
8242 cbi,
8243 isize,
8245 cbi->pid = cmc->im.sender;
8246 memcpy (&cbi[1], inbox, isize);
8247 GNUNET_MQ_send (tc->mq, env);
8248 GNUNET_free (sender);
8249 GNUNET_free (self);
8250 finish_cmc_handling (cmc);
8251}
8252
8253
8263static void
8265{
8266 struct DistanceVector *dv = cls;
8267 struct DistanceVectorHop *pos;
8268
8269 dv->timeout_task = NULL;
8270 while (NULL != (pos = dv->dv_head))
8271 {
8272 GNUNET_assert (dv == pos->dv);
8274 break;
8276 }
8277 if (NULL == pos)
8278 {
8279 free_dv_route (dv);
8280 return;
8281 }
8282 dv->timeout_task =
8284}
8285
8286
8287static void
8289{
8290
8291 const struct GNUNET_PeerIdentity target = vl->target;
8292
8293
8295 {
8296 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
8297 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
8298 0;
8299 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
8302 struct CommunicatorMessageContext *cmc;
8303 struct RingBufferEntry *rbe;
8304 struct GNUNET_MessageHeader *mh;
8305
8307 "Sending from ring buffer, which has %u items\n",
8308 head);
8309
8310 ring_buffer_head = 0;
8311 for (unsigned int i = 0; i < head; i++)
8312 {
8313 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
8314 cmc = rbe->cmc;
8315 mh = rbe->mh;
8316
8317 im = cmc->im;
8318 // mh = cmc->mh;
8320 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
8321 mh->type,
8322 GNUNET_i2s (&im.sender),
8323 GNUNET_i2s2 (&target),
8324 (i + tail) % RING_BUFFER_SIZE);
8325 if (0 == GNUNET_memcmp (&target, &im.sender))
8326 {
8328 "Finish handling message of type %u and size %u\n",
8329 (unsigned int) ntohs (mh->type),
8330 (unsigned int) ntohs (mh->size));
8332 GNUNET_free (mh);
8333 GNUNET_free (rbe->cmc);
8334 GNUNET_free (rbe);
8335 }
8336 else
8337 {
8338 ring_buffer_copy[ring_buffer_head] = rbe;
8340 }
8341 }
8342
8345 {
8347 }
8348
8349 for (unsigned int i = 0; i < ring_buffer_head; i++)
8350 {
8351 ring_buffer[i] = ring_buffer_copy[i];
8353 "ring_buffer[i]->mh->type for i %u %u\n",
8354 i,
8355 ring_buffer[i]->mh->type);
8356 }
8357 /* MUST clear the consumed slots, we freed those entries above */
8358 for (unsigned int i = ring_buffer_head; i < RING_BUFFER_SIZE; i++)
8359 ring_buffer[i] = NULL;
8360
8362 "%u items still in ring buffer\n",
8364 /* If we consumed nothing, compaction rewrote the buffer in place and
8365 left the write index one past the end. #handle_raw_message() would
8366 then read ring_buffer[RING_BUFFER_SIZE] and free whatever that is.
8367 The buffer is still full, and compaction moved the oldest entry to
8368 slot 0, so that is where the next write belongs. */
8370 ring_buffer_head = 0;
8371 }
8372
8374 {
8375 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
8376 struct PendingMessage *pm;
8377 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
8379 0;
8380 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
8383
8385 "Sending from ring buffer dv, which has %u items\n",
8386 head);
8387
8389 for (unsigned int i = 0; i < head; i++)
8390 {
8391 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
8392
8394 "Sending to ring buffer target %s using vl target %s\n",
8395 GNUNET_i2s (&pm->target),
8396 GNUNET_i2s2 (&target));
8397 if (0 == GNUNET_memcmp (&target, &pm->target))
8398 {
8400 "Adding PendingMessage to vl, checking transmission.\n");
8401 pm->vl = vl;
8405 pm);
8406
8408 }
8409 else
8410 {
8411 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
8413 }
8414 }
8415
8417 {
8419 }
8420
8421 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
8422 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
8423 /* MUST clear the consumed slots: entries we handed to a VirtualLink are
8424 now owned by that link, and #forward_dv_box() would GNUNET_free() them
8425 again once the ring buffer wraps around. */
8426 for (unsigned int i = ring_buffer_dv_head; i < RING_BUFFER_SIZE; i++)
8427 ring_buffer_dv[i] = NULL;
8428
8430 "%u items still in ring buffer dv.\n",
8432 /* Same one-past-the-end hazard as above: #forward_dv_box() reads
8433 ring_buffer_dv[ring_buffer_dv_head] and GNUNET_free()s it. */
8436 }
8437}
8438
8439
8447static void
8449{
8450 struct DistanceVector *dv = hop->dv;
8451 struct VirtualLink *vl;
8452
8453 vl = lookup_virtual_link (&dv->target);
8454 if (NULL == vl)
8455 {
8456
8457 vl = GNUNET_new (struct VirtualLink);
8459 "Creating new virtual link %p to %s using DV!\n",
8460 vl,
8461 GNUNET_i2s (&dv->target));
8462 vl->burst_addr = NULL;
8463 vl->confirmed = GNUNET_YES;
8464 vl->message_uuid_ctr =
8465 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
8466 vl->target = dv->target;
8470 /* What the peer will grant us in its very first FLOW_CONTROL anyway
8471 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
8472 Starting at zero instead means a link that is up, validated and
8473 working carries nothing at all until an FC round trip completes --
8474 and if the peer cannot answer, not ever. */
8478 links,
8479 &vl->target,
8480 vl,
8482 vl->dv = dv;
8483 dv->vl = vl;
8484 vl->visibility_task =
8487 /* We lacked a confirmed connection to the target
8488 before, so tell CORE about it (finally!) */
8491 }
8492 else
8493 {
8494 /* Link was already up, remember dv is also now available and we are done */
8495 vl->dv = dv;
8496 dv->vl = vl;
8497 if (GNUNET_NO == vl->confirmed)
8498 {
8499 vl->confirmed = GNUNET_YES;
8500 vl->visibility_task =
8503 /* We lacked a confirmed connection to the target
8504 before, so tell CORE about it (finally!) */
8507 }
8508 else
8510 "Virtual link to %s could now also use DV!\n",
8511 GNUNET_i2s (&dv->target));
8512 }
8513}
8514
8515
8541static int
8543 unsigned int path_len,
8544 struct GNUNET_TIME_Relative network_latency,
8545 struct GNUNET_TIME_Absolute path_valid_until)
8546{
8547 const struct GNUNET_PeerIdentity *my_identity;
8548 struct DistanceVectorHop *hop;
8549 struct DistanceVector *dv;
8550 struct Neighbour *next_hop;
8551 unsigned int shorter_distance;
8552
8553 if (path_len < 3)
8554 {
8555 /* what a boring path! not allowed! */
8556 GNUNET_break (0);
8557 return GNUNET_SYSERR;
8558 }
8559
8562
8563 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
8564 next_hop = lookup_neighbour (&path[1]);
8565 if (NULL == next_hop)
8566 {
8567 /* next hop must be a neighbour, otherwise this whole thing is useless! */
8568 GNUNET_break (0);
8569 return GNUNET_SYSERR;
8570 }
8571 for (unsigned int i = 2; i < path_len; i++)
8572 {
8573 struct Neighbour *n = lookup_neighbour (&path[i]);
8574 struct GNUNET_TIME_Absolute q_timeout;
8575
8576 if (NULL != n)
8577 {
8578 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
8579 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
8580 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
8582 "remaining %lu to %s\n",
8583 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
8584 .rel_value_us,
8585 GNUNET_i2s (&n->pid));
8586 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
8587 {
8588 /* Useless path: we have a direct active connection to some hop
8589 in the middle of the path, so this one is not even
8590 terribly useful for redundancy */
8592 "Path of %u hops useless: directly link to hop %u (%s)\n",
8593 path_len,
8594 i,
8595 GNUNET_i2s (&path[i]));
8597 "# Useless DV path ignored: hop is neighbour",
8598 1,
8599 GNUNET_NO);
8600 return GNUNET_SYSERR;
8601 }
8602 }
8603 }
8604 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
8605 if (NULL == dv)
8606 {
8607 dv = GNUNET_new (struct DistanceVector);
8608 dv->target = path[path_len - 1];
8611 dv);
8614 dv_routes,
8615 &dv->target,
8616 dv,
8618 }
8619 /* Check if we have this path already! */
8620 shorter_distance = 0;
8621 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
8622 pos = pos->next_dv)
8623 {
8624 if (pos->distance < path_len - 3)
8625 shorter_distance++;
8626 /* Note that the distances in 'pos' excludes us (path[0]),
8627 the next_hop (path[1]) and the target so we need to subtract three
8628 and check next_hop explicitly */
8629 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
8630 {
8631 int match = GNUNET_YES;
8632
8633 for (unsigned int i = 0; i < pos->distance; i++)
8634 {
8635 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
8636 {
8637 match = GNUNET_NO;
8638 break;
8639 }
8640 }
8641 if (GNUNET_YES == match)
8642 {
8643 struct GNUNET_TIME_Relative last_timeout;
8644
8645 /* Re-discovered known path, update timeout */
8647 "# Known DV path refreshed",
8648 1,
8649 GNUNET_NO);
8650 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
8651 pos->timeout =
8653 pos->path_valid_until =
8654 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
8655 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
8656 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
8657 if (0 <
8660 if (last_timeout.rel_value_us <
8663 .rel_value_us)
8664 {
8665 /* Some peer send DV learn messages too often, we are learning
8666 the same path faster than it would be useful; do not forward! */
8668 "Rediscovered path too quickly, not forwarding further\n")
8669 ;
8670 return GNUNET_NO;
8671 }
8673 "Refreshed known path to %s valid until %s, forwarding further\n",
8674 GNUNET_i2s (&dv->target),
8676 pos->path_valid_until));
8677 return GNUNET_YES;
8678 }
8679 }
8680 }
8681 /* Count how many shorter paths we have (incl. direct
8682 neighbours) before simply giving up on this one! */
8683 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
8684 {
8685 /* We have a shorter path already! */
8687 "Have many shorter DV paths %s, not forwarding further\n",
8688 GNUNET_i2s (&dv->target));
8689 return GNUNET_NO;
8690 }
8691 /* create new DV path entry */
8693 "Discovered new DV path to %s valid until %s\n",
8694 GNUNET_i2s (&dv->target),
8695 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
8696 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
8697 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
8698 hop->next_hop = next_hop;
8699 hop->dv = dv;
8700 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
8701 memcpy (&hop[1],
8702 &path[2],
8703 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
8705 hop->path_valid_until = path_valid_until;
8706 hop->distance = path_len - 3;
8707 hop->pd.aged_rtt = network_latency;
8708 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
8710 next_hop->dv_head,
8711 next_hop->dv_tail,
8712 hop);
8713 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
8715 return GNUNET_YES;
8716}
8717
8718
8726static int
8727check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8728{
8729 const struct GNUNET_PeerIdentity *my_identity;
8730 uint16_t size = ntohs (dvl->header.size);
8731 uint16_t num_hops = ntohs (dvl->num_hops);
8732 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
8733
8734 (void) cls;
8735 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
8736 {
8737 GNUNET_break_op (0);
8738 return GNUNET_SYSERR;
8739 }
8740 if (num_hops > MAX_DV_HOPS_ALLOWED)
8741 {
8742 GNUNET_break_op (0);
8743 return GNUNET_SYSERR;
8744 }
8745
8748
8749 for (unsigned int i = 0; i < num_hops; i++)
8750 {
8751 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
8752 {
8753 GNUNET_break_op (0);
8754 return GNUNET_SYSERR;
8755 }
8756 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
8757 {
8758 GNUNET_break_op (0);
8759 return GNUNET_SYSERR;
8760 }
8761 }
8762 return GNUNET_YES;
8763}
8764
8765
8777static void
8779 const struct TransportDVLearnMessage *msg,
8780 uint16_t bi_history,
8781 uint16_t nhops,
8782 const struct DVPathEntryP *hops,
8783 struct GNUNET_TIME_Absolute in_time)
8784{
8785 struct DVPathEntryP *dhops;
8786 size_t fwd_size = sizeof(struct TransportDVLearnMessage)
8787 + (nhops + 1) * sizeof(struct DVPathEntryP);
8788 /* Signing is synchronous and the routing calls below copy the message,
8789 so this never outlives the frame. Keeping it on the stack matters:
8790 a hub forwards a DV learn to every eligible neighbour, so this is one
8791 of the hottest allocation sites in the service. Size it by the hop
8792 limit rather than by @a nhops -- @a nhops is only asserted to be below
8793 that limit further down, and a VLA is sized before we get there. */
8794 char fwd_buf[sizeof(struct TransportDVLearnMessage)
8795 + (MAX_DV_HOPS_ALLOWED + 1)
8796 * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8797 struct TransportDVLearnMessage *fwd
8798 = (struct TransportDVLearnMessage *) fwd_buf;
8799 struct GNUNET_TIME_Relative nnd;
8800 const struct GNUNET_PeerIdentity *my_identity;
8801 struct VirtualLink *vl;
8802 struct Neighbour *n;
8803
8805 memset (fwd_buf, 0, fwd_size);
8806
8807 /* compute message for forwarding */
8809 "Forwarding DV learn message originating from %s to %s\n",
8810 GNUNET_i2s (&msg->initiator),
8811 GNUNET_i2s2 (next_hop));
8814 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8815 + (nhops + 1) * sizeof(struct DVPathEntryP));
8816 fwd->num_hops = htons (nhops + 1);
8817 fwd->bidirectional = htons (bi_history);
8820 msg->non_network_delay));
8822 fwd->init_sig = msg->init_sig;
8823 fwd->initiator = msg->initiator;
8824 fwd->challenge = msg->challenge;
8825 fwd->monotonic_time = msg->monotonic_time;
8826
8829
8830 dhops = (struct DVPathEntryP *) &fwd[1];
8831 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8832 dhops[nhops].hop = *my_identity;
8833 {
8834 struct DvHopPS dhp = {
8836 .purpose.size = htonl (sizeof(dhp)),
8837 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8838 .succ = *next_hop,
8839 .challenge = msg->challenge
8840 };
8841
8843 &dhops[nhops].hop_sig))
8844 return; /* nobody would accept the path without our hop signature */
8845 }
8846 vl = lookup_virtual_link (next_hop);
8847 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8848 {
8850 &fwd->header,
8852 return;
8853 }
8854 /* Use route via neighbour */
8855 n = lookup_neighbour (next_hop);
8856 if (NULL != n)
8858 &fwd->header,
8860}
8861
8862
8872static int
8874 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
8875 const struct GNUNET_PeerIdentity *init,
8877 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
8878{
8879 struct DvInitPS ip = { .purpose.purpose = htonl (
8881 .purpose.size = htonl (sizeof(ip)),
8882 .monotonic_time = sender_monotonic_time,
8883 .challenge = *challenge };
8884
8885 if (
8886 GNUNET_OK !=
8888 &ip,
8889 init_sig,
8890 &init->public_key))
8891 {
8892 GNUNET_break_op (0);
8893 return GNUNET_SYSERR;
8894 }
8895 return GNUNET_OK;
8896}
8897
8898
8903{
8908
8912 const struct DVPathEntryP *hops;
8913
8918
8923
8927 unsigned int num_eligible;
8928
8932 unsigned int num_selections;
8933
8937 uint16_t nhops;
8938
8942 uint16_t bi_history;
8943};
8944
8945
8954static int
8956 const struct GNUNET_PeerIdentity *pid,
8957 void *value)
8958{
8959 struct NeighbourSelectionContext *nsc = cls;
8960
8961 (void) value;
8962 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8963 return GNUNET_YES; /* skip initiator */
8964 for (unsigned int i = 0; i < nsc->nhops; i++)
8965 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8966 return GNUNET_YES;
8967 /* skip peers on path */
8968 nsc->num_eligible++;
8969 return GNUNET_YES;
8970}
8971
8972
8983static int
8985 const struct GNUNET_PeerIdentity *pid,
8986 void *value)
8987{
8988 struct NeighbourSelectionContext *nsc = cls;
8989
8991 "transmission %s\n",
8992 GNUNET_i2s (pid));
8993 (void) value;
8994 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8995 return GNUNET_YES; /* skip initiator */
8996 for (unsigned int i = 0; i < nsc->nhops; i++)
8997 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8998 return GNUNET_YES;
8999 /* skip peers on path */
9000 for (unsigned int i = 0; i < nsc->num_selections; i++)
9001 {
9002 if (nsc->selections[i] == nsc->num_eligible)
9003 {
9004 forward_dv_learn (pid,
9005 nsc->dvl,
9006 nsc->bi_history,
9007 nsc->nhops,
9008 nsc->hops,
9009 nsc->in_time);
9010 break;
9011 }
9012 }
9013 nsc->num_eligible++;
9014 return GNUNET_YES;
9015}
9016
9017
9061static unsigned int
9062calculate_fork_degree (unsigned int hops_taken,
9063 unsigned int neighbour_count,
9064 unsigned int eligible_count)
9065{
9066 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
9067 double eligible_ratio =
9068 ((double) eligible_count) / ((double) neighbour_count);
9069 double boost_factor = eligible_ratio * eligible_ratio;
9070 unsigned int rnd;
9071 double left;
9072
9073 if (hops_taken >= 64)
9074 {
9075 GNUNET_break (0);
9076 return 0; /* precaution given bitshift below */
9077 }
9078 for (unsigned int i = 1; i < hops_taken; i++)
9079 {
9080 /* For each hop, subtract the expected number of targets
9081 reached at distance d (so what remains divided by 2^d) */
9082 target_total -= (target_total * boost_factor / (1LLU << i));
9083 }
9084 {
9085 double degree = target_total * boost_factor / (1LLU << hops_taken);
9086
9087 rnd = (unsigned int) floor (degree);
9088 /* round up or down probabilistically depending on how close we were
9089 when floor()ing to rnd. NOTE: this must be the fractional part of
9090 @e degree; using `target_total - rnd' here made the condition below
9091 true essentially always, so we always rounded up. */
9092 left = degree - (double) rnd;
9093 }
9094 if (UINT32_MAX * left >
9095 GNUNET_CRYPTO_random_u64 (UINT32_MAX))
9096 rnd++; /* round up */
9098 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
9099 hops_taken,
9100 rnd,
9101 eligible_count,
9102 neighbour_count);
9103 return rnd;
9104}
9105
9106
9113static void
9114neighbour_store_dvmono_cb (void *cls, int success)
9115{
9116 struct Neighbour *n = cls;
9117
9118 n->sc = NULL;
9119 if (GNUNET_YES != success)
9121 "Failed to store other peer's monotonic time in peerstore!\n");
9122}
9123
9124
9125static struct GNUNET_TIME_Relative
9127{
9128 struct GNUNET_TIME_Relative host_latency_sum;
9129 struct GNUNET_TIME_Relative latency;
9130 struct GNUNET_TIME_Relative network_latency;
9131 uint16_t nhops = ntohs (dvl->num_hops);;
9132
9133 /* We initiated this, learn the forward path! */
9134 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
9135
9136 // Need also something to lookup initiation time
9137 // to compute RTT! -> add RTT argument here?
9139 dvl->monotonic_time));
9140 /* @e non_network_delay is fully attacker-controlled, and our clock may
9141 simply be behind the initiator's: never assert on this. */
9142 if (latency.rel_value_us < host_latency_sum.rel_value_us)
9143 {
9145 "# DV learn with implausible non-network delay",
9146 1,
9147 GNUNET_NO);
9149 }
9150 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
9151 // (based on dvl->challenge, we can identify time of origin!)
9152
9153 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
9154 /* assumption: latency on all links is the same */
9155 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
9156
9157 return network_latency;
9158}
9159
9160
9168static void
9169handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
9170{
9171 struct CommunicatorMessageContext *cmc = cls;
9173 int bi_hop;
9174 uint16_t nhops;
9175 uint16_t bi_history;
9176 const struct DVPathEntryP *hops;
9177 int do_fwd;
9178 int did_initiator;
9179 struct GNUNET_TIME_Absolute in_time;
9180 struct Neighbour *n;
9181 const struct GNUNET_PeerIdentity *my_identity;
9182
9183 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
9184 bi_history = ntohs (dvl->bidirectional);
9185 hops = (const struct DVPathEntryP *) &dvl[1];
9186 if (0 == nhops)
9187 {
9188 /* sanity check */
9189 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
9190 {
9191 GNUNET_break (0);
9192 finish_cmc_handling (cmc);
9193 return;
9194 }
9195 /* A zero-hop message we supposedly initiated ourselves would make the
9196 "we are the initiator" branch below read hops[0] and write past the
9197 end of its `path[nhops + 1]' array. */
9199 {
9200 GNUNET_break_op (0);
9201 finish_cmc_handling (cmc);
9202 return;
9203 }
9204 }
9205 else
9206 {
9208 "handle dv learn message last hop %s\n",
9209 GNUNET_i2s (&hops[nhops - 1].hop));
9210 /* sanity check */
9211 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
9212 {
9213 GNUNET_break (0);
9214 finish_cmc_handling (cmc);
9215 return;
9216 }
9217 }
9218
9220 cc = cmc->tc->details.communicator.cc;
9221 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
9222 cc); // FIXME: add bi-directional flag to cc?
9223 in_time = GNUNET_TIME_absolute_get ();
9224
9225 /* continue communicator here, everything else can happen asynchronous! */
9226 finish_cmc_handling (cmc);
9227
9228 n = lookup_neighbour (&dvl->initiator);
9229 if (NULL != n)
9230 {
9231 if ((n->dv_monotime_available == GNUNET_YES) &&
9234 {
9236 "DV learn from %s discarded due to time travel",
9237 GNUNET_i2s (&dvl->initiator));
9239 "# DV learn discarded due to time travel",
9240 1,
9241 GNUNET_NO);
9242 return;
9243 }
9245 &dvl->initiator,
9246 &dvl->challenge,
9247 &dvl->init_sig))
9248 {
9250 "DV learn signature from %s invalid\n",
9251 GNUNET_i2s (&dvl->initiator));
9252 GNUNET_break_op (0);
9253 return;
9254 }
9257 {
9258 if (NULL != n->sc)
9259 {
9261 "store cancel\n");
9263 }
9264 n->sc =
9266 "transport",
9267 &dvl->initiator,
9269 &dvl->monotonic_time,
9270 sizeof(dvl->monotonic_time),
9274 n);
9275 }
9276 }
9277
9280
9281 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
9282 If signature verification load too high, implement random drop strategy */
9283 for (unsigned int i = 0; i < nhops; i++)
9284 {
9285 struct DvHopPS dhp = { .purpose.purpose =
9287 .purpose.size = htonl (sizeof(dhp)),
9288 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
9289 .succ = (nhops == i + 1) ? *my_identity
9290 : hops[i + 1].hop,
9291 .challenge = dvl->challenge };
9292
9293 if (GNUNET_OK !=
9295 &dhp,
9296 &hops[i].hop_sig,
9297 &hops[i].hop.public_key))
9298 {
9300 "DV learn from %s signature of hop %u invalid\n",
9301 GNUNET_i2s (&dvl->initiator),
9302 i);
9304 "signature of hop %s invalid\n",
9305 GNUNET_i2s (&hops[i].hop));
9307 "pred %s\n",
9308 GNUNET_i2s (&dhp.pred));
9310 "succ %s\n",
9311 GNUNET_i2s (&dhp.succ));
9313 "hash %s\n",
9314 GNUNET_sh2s (&dhp.challenge.value));
9315 GNUNET_break_op (0);
9316 return;
9317 }
9318 }
9319 if (GNUNET_EXTRA_LOGGING > 0)
9320 {
9321 char *path;
9322
9323 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
9324 for (unsigned int i = 0; i < nhops; i++)
9325 {
9326 char *tmp;
9327
9328 GNUNET_asprintf (&tmp,
9329 "%s%s%s",
9330 path,
9331 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
9332 GNUNET_i2s (&hops[i].hop));
9333 GNUNET_free (path);
9334 path = tmp;
9335 }
9337 "Received DVInit via %s%s%s\n",
9338 path,
9339 bi_hop ? "<->" : "-->",
9341 GNUNET_free (path);
9342 }
9343 do_fwd = GNUNET_YES;
9344 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
9345 {
9346 struct GNUNET_PeerIdentity path[nhops + 1];
9347 struct GNUNET_TIME_Relative network_latency;
9348
9349 /* We initiated this, learn the forward path! */
9350 path[0] = *my_identity;
9351 path[1] = hops[0].hop;
9352
9353 network_latency = get_network_latency (dvl);
9354
9355 for (unsigned int i = 2; i <= nhops; i++)
9356 {
9357 struct GNUNET_TIME_Relative ilat;
9358
9359 /* assumption: linear latency increase per hop */
9360 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
9361 path[i] = hops[i - 1].hop;
9363 "Learned path with %u hops to %s with latency %s\n",
9364 i,
9365 GNUNET_i2s (&path[i]),
9367 learn_dv_path (path,
9368 i + 1,
9369 ilat,
9372 }
9373 /* as we initiated, do not forward again (would be circular!) */
9374 do_fwd = GNUNET_NO;
9375 return;
9376 }
9377 if (bi_hop)
9378 {
9379 /* last hop was bi-directional, we could learn something here! */
9380 struct GNUNET_PeerIdentity path[nhops + 2];
9381 struct GNUNET_TIME_Relative ilat;
9382 struct GNUNET_TIME_Relative network_latency;
9383
9384 path[0] = *my_identity;
9385 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
9386 for (unsigned int i = 0; i < nhops; i++)
9387 {
9388 int iret;
9389
9390 if (0 == (bi_history & (1 << i)))
9391 break; /* i-th hop not bi-directional, stop learning! */
9392 if (i == nhops - 1)
9393 {
9394 path[i + 2] = dvl->initiator;
9395 }
9396 else
9397 {
9398 path[i + 2] = hops[nhops - i - 2].hop;
9399 }
9400
9402 "Learned inverse path with %u hops to %s\n",
9403 i + 2,
9404 GNUNET_i2s (&path[i + 2]));
9405 network_latency = get_network_latency (dvl);
9406 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
9407 iret = learn_dv_path (path,
9408 i + 3,
9409 ilat,
9412 if (GNUNET_SYSERR == iret)
9413 {
9414 /* path invalid or too long to be interesting for US, thus should also
9415 not be interesting to our neighbours, cut path when forwarding to
9416 'i' hops, except of course for the one that goes back to the
9417 initiator */
9419 "# DV learn not forwarded due invalidity of path",
9420 1,
9421 GNUNET_NO);
9422 do_fwd = GNUNET_NO;
9423 break;
9424 }
9425 if ((GNUNET_NO == iret) && (nhops == i + 1))
9426 {
9427 /* we have better paths, and this is the longest target,
9428 so there cannot be anything interesting later */
9430 "# DV learn not forwarded, got better paths",
9431 1,
9432 GNUNET_NO);
9433 do_fwd = GNUNET_NO;
9434 break;
9435 }
9436 }
9437 }
9438 if (MAX_DV_HOPS_ALLOWED == nhops)
9439 {
9440 /* At limit, we're out of here! */
9441 return;
9442 }
9443
9444 /* Forward to initiator, if path non-trivial and possible */
9445 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
9446 did_initiator = GNUNET_NO;
9447 if ((1 <= nhops) &&
9448 (GNUNET_YES ==
9450 {
9451 /* send back to origin! */
9453 "Sending DVL back to initiator %s\n",
9454 GNUNET_i2s (&dvl->initiator));
9455 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
9456 did_initiator = GNUNET_YES;
9457 }
9458 /* We forward under two conditions: either we still learned something
9459 ourselves (do_fwd), or the path was darn short and thus the initiator is
9460 likely to still be very interested in this (and we did NOT already
9461 send it back to the initiator) */
9462 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
9463 (GNUNET_NO == did_initiator)))
9464 {
9465 /* Pick random neighbours that are not yet on the path */
9466 struct NeighbourSelectionContext nsc;
9467 unsigned int n_cnt;
9468 unsigned int n_eligible;
9469
9471 nsc.nhops = nhops;
9472 nsc.dvl = dvl;
9473 nsc.bi_history = bi_history;
9474 nsc.hops = hops;
9475 nsc.in_time = in_time;
9476 nsc.num_eligible = 0;
9479 &nsc);
9480 if (0 == nsc.num_eligible)
9481 return; /* done here, cannot forward to anyone else */
9482 n_eligible = nsc.num_eligible;
9483 nsc.num_selections = calculate_fork_degree (nhops, n_cnt, n_eligible);
9484 nsc.num_selections =
9487 "Forwarding DVL to %u other peers\n",
9488 nsc.num_selections);
9489 /* #dv_neighbour_transmission() counts ELIGIBLE peers only, so the
9490 offsets must be drawn from that range -- drawing from the total
9491 number of neighbours made us silently forward to fewer peers than
9492 #calculate_fork_degree() asked for. */
9493 for (unsigned int i = 0; i < nsc.num_selections; i++)
9494 nsc.selections[i] =
9495 (nsc.num_selections == n_eligible)
9496 ? i /* all were selected, avoid collisions by chance */
9497 : GNUNET_CRYPTO_random_u32 (n_eligible);
9498 nsc.num_eligible = 0;
9501 &nsc);
9502 }
9503}
9504
9505
9513static int
9514check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9515{
9516 uint16_t size = ntohs (dvb->header.size);
9517 uint16_t num_hops = ntohs (dvb->num_hops);
9518 uint16_t total_hops = ntohs (dvb->total_hops);
9519 uint16_t orig_size = ntohs (dvb->orig_size);
9520 const struct GNUNET_PeerIdentity *hops =
9521 (const struct GNUNET_PeerIdentity *) &dvb[1];
9522 const struct GNUNET_PeerIdentity *my_identity;
9523
9524 (void) cls;
9525 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
9526 + sizeof(struct GNUNET_MessageHeader))
9527 {
9528 GNUNET_break_op (0);
9529 return GNUNET_SYSERR;
9530 }
9531 if ((num_hops > MAX_DV_HOPS_ALLOWED) ||
9532 (total_hops > MAX_DV_HOPS_ALLOWED))
9533 {
9534 GNUNET_break_op (0);
9535 return GNUNET_SYSERR;
9536 }
9537 /* #decaps_dv_box_cb() derives a VLA size from
9538 orig_size - sizeof(*dvb) - total_hops * sizeof (struct
9539 GNUNET_PeerIdentity); make sure that cannot underflow and that the
9540 remainder can plausibly hold a payload header plus a message. */
9541 if ((orig_size < size) ||
9542 (orig_size < sizeof(*dvb)
9543 + total_hops * sizeof(struct GNUNET_PeerIdentity)
9544 + sizeof(struct TransportDVBoxPayloadP)
9545 + sizeof(struct GNUNET_MessageHeader)))
9546 {
9547 GNUNET_break_op (0);
9548 return GNUNET_SYSERR;
9549 }
9550
9553
9554 /* This peer must not be on the path */
9555 for (unsigned int i = 0; i < num_hops; i++)
9556 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9557 {
9558 GNUNET_break_op (0);
9559 return GNUNET_SYSERR;
9560 }
9561 return GNUNET_YES;
9562}
9563
9564
9577static void
9578forward_dv_box (struct Neighbour *next_hop,
9579 struct TransportDVBoxMessage *hdr,
9580 uint16_t total_hops,
9581 uint16_t num_hops,
9582 const struct GNUNET_PeerIdentity *hops,
9583 const void *enc_payload,
9584 uint16_t enc_payload_size)
9585{
9586 struct VirtualLink *vl = next_hop->vl;
9587 struct PendingMessage *pm;
9588 size_t msg_size = sizeof(struct TransportDVBoxMessage)
9589 + num_hops * sizeof(struct GNUNET_PeerIdentity)
9590 + enc_payload_size;
9591 char *buf;
9592 char msg_buf[msg_size] GNUNET_ALIGN;
9593 struct GNUNET_PeerIdentity *dhops;
9594
9595 hdr->num_hops = htons (num_hops);
9596 hdr->total_hops = htons (total_hops);
9597 hdr->header.size = htons (msg_size);
9598 memcpy (msg_buf, hdr, sizeof(*hdr));
9599 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
9601 ;
9602 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
9603 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
9604
9605 if (GNUNET_YES == ntohl (hdr->without_fc))
9606 {
9608 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
9609 enc_payload_size,
9610 GNUNET_i2s (&next_hop->pid),
9611 (unsigned int) num_hops,
9612 (unsigned int) total_hops);
9613 route_via_neighbour (next_hop, (const struct
9614 GNUNET_MessageHeader *) msg_buf,
9616 }
9617 else
9618 {
9619 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
9621 "2 created pm %p storing vl %p \n",
9622 pm,
9623 vl);
9624 pm->pmt = PMT_DV_BOX;
9625 pm->vl = vl;
9626 pm->target = next_hop->pid;
9630 pm->bytes_msg = msg_size;
9631 buf = (char *) &pm[1];
9632 memcpy (buf, msg_buf, msg_size);
9633
9635 "Created pending message %" PRIu64
9636 " for DV Box with next hop %s (%u/%u)\n",
9637 pm->logging_uuid,
9638 GNUNET_i2s (&next_hop->pid),
9639 (unsigned int) num_hops,
9640 (unsigned int) total_hops);
9641
9642 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9643 {
9645 vl->pending_msg_head,
9646 vl->pending_msg_tail,
9647 pm);
9648
9650 }
9651 else
9652 {
9654 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
9655
9657 {
9659
9660 GNUNET_free (pm_old);
9661 }
9664 {
9667 }
9668 else
9670
9672 "%u items stored in DV ring buffer\n",
9675 }
9676 }
9677}
9678
9679
9685static void
9687{
9688 if (NULL != b->get)
9689 {
9691 b->get = NULL;
9692 GNUNET_assert (NULL != b->cmc);
9694 b->cmc = NULL;
9695 }
9696 if (NULL != b->task)
9697 {
9699 b->task = NULL;
9700 }
9701 if (NULL != b->sc)
9702 {
9704 "store cancel\n");
9706 b->sc = NULL;
9707 }
9709 "Removing backtalker for %s\n",
9710 GNUNET_i2s (&b->pid));
9712 GNUNET_YES ==
9714 GNUNET_free (b);
9715}
9716
9717
9726static int
9728 const struct GNUNET_PeerIdentity *pid,
9729 void *value)
9730{
9731 struct Backtalker *b = value;
9732
9733 (void) cls;
9734 (void) pid;
9735 free_backtalker (b);
9736 return GNUNET_OK;
9737}
9738
9739
9745static void
9747{
9748 struct Backtalker *b = cls;
9749
9751 "backtalker timeout.\n");
9752 b->task = NULL;
9754 {
9756 return;
9757 }
9758 /* A monotime store may well still be in flight -- @e timeout is about how
9759 long the *peer* has been quiet, and says nothing about PEERSTORE. This
9760 used to `GNUNET_assert (NULL == b->sc)', which aborted the service in
9761 exactly that case. #free_backtalker() cancels the store. */
9762 free_backtalker (b);
9763}
9764
9765
9774static void
9776 const struct GNUNET_PEERSTORE_Record *record,
9777 const char *emsg)
9778{
9779 struct Backtalker *b = cls;
9780 struct GNUNET_TIME_AbsoluteNBO *mtbe;
9781 struct GNUNET_TIME_Absolute mt;
9782
9783 (void) emsg;
9784 if (NULL == record)
9785 {
9786 struct CommunicatorMessageContext *cmc;
9787
9788 /* we're done with #backtalker_monotime_cb() invocations,
9789 continue normal processing */
9790 b->get = NULL;
9791 GNUNET_assert (NULL != b->cmc);
9792 /* Take @e cmc out of @a b *before* dispatching: the dispatch runs
9793 arbitrary message handling, and writing `b->cmc = NULL' afterwards
9794 is a write to freed memory should anything on that path have
9795 released @a b. #free_backtalker() keys its "must finish the parked
9796 cmc" decision off @e get, which is already NULL here, so clearing
9797 @e cmc early cannot lose the message either. */
9798 cmc = b->cmc;
9799 b->cmc = NULL;
9800 cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
9801 if (0 != b->body_size)
9803 else
9804 finish_cmc_handling (cmc);
9805 return;
9806 }
9807 if (sizeof(*mtbe) != record->value_size)
9808 {
9810 GNUNET_break (0);
9811 return;
9812 }
9813 mtbe = record->value;
9814 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
9816 {
9818 "Backtalker message from %s dropped, monotime in the past\n",
9819 GNUNET_i2s (&b->pid));
9821 GST_stats,
9822 "# Backchannel messages dropped: monotonic time not increasing",
9823 1,
9824 GNUNET_NO);
9825 b->monotonic_time = mt;
9826 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
9827 */
9828 b->body_size = 0;
9829 }
9831}
9832
9833
9841static void
9842backtalker_monotime_store_cb (void *cls, int success)
9843{
9844 struct Backtalker *b = cls;
9845
9846 if (GNUNET_OK != success)
9847 {
9849 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
9850 }
9851 b->sc = NULL;
9852 /* @e task is armed for the whole life of @a b -- #backtalker_timeout_cb()
9853 re-arms itself whenever @e timeout has moved forward -- so there is
9854 nothing to do here beyond releasing the store. It used to cancel and
9855 re-add the task, which is what made the task's existence depend on this
9856 callback ever running. */
9857 GNUNET_assert (NULL != b->task);
9858}
9859
9860
9866static void
9868{
9869 struct GNUNET_TIME_AbsoluteNBO mtbe;
9870
9871 /* At most one store may be outstanding. The value we are about to write
9872 supersedes whatever the previous one carried, and leaving the old
9873 context alive means its completion clears @e sc while the newer store
9874 is still in flight -- after which the next update sees a NULL @e sc and
9875 starts a third one. Cancelling is also what keeps @e sc from being
9876 silently overwritten and leaked.
9877
9878 Note what this must NOT do: touch @e task. That task is the only thing
9879 that ever releases a `struct CommunicatorMessageContext' parked in
9880 @e cmc, and cancelling it here left its re-arming up to
9881 #backtalker_monotime_store_cb() -- i.e. up to PEERSTORE answering. A
9882 lost store completion then stalled the parked communicator client for
9883 the life of the process. #backtalker_timeout_cb() already re-arms
9884 itself against the current @e timeout, so the task needs no help. */
9885 if (NULL != b->sc)
9886 {
9888 "Superseding in-flight backtalker monotime store %p\n",
9889 b->sc);
9891 b->sc = NULL;
9892 }
9894 b->sc =
9896 "transport",
9897 &b->pid,
9899 &mtbe,
9900 sizeof(mtbe),
9904 b);
9905}
9906
9907
9916static void
9918 const struct TransportDVBoxMessage *dvb,
9919 const struct GNUNET_ShortHashCode *km)
9920{
9921 const unsigned char *hdr;
9922 size_t hdr_len;
9924
9925 key = (struct GNUNET_CRYPTO_AeadSecretKey*) km;
9926 /* We are the ultimate target, so #handle_dv_box() has established that no
9927 hop entries are left: the ciphertext directly follows the header, and
9928 its length is what we actually received. Deriving it from orig_size
9929 and total_hops instead would only be equivalent if every forwarder
9930 accounted its skipped hops exactly. */
9931 hdr = (const unsigned char *) &dvb[1];
9932 {
9933 uint16_t size = ntohs (dvb->header.size);
9934
9935 if (size < sizeof(*dvb)
9936 + sizeof(struct TransportDVBoxPayloadP)
9937 + sizeof(struct GNUNET_MessageHeader))
9938 {
9939 GNUNET_break_op (0);
9940 finish_cmc_handling (cmc);
9941 return;
9942 }
9943 hdr_len = size - sizeof(*dvb);
9944 }
9945
9946 /* begin actual decryption */
9947 {
9948 struct Backtalker *b;
9949 struct GNUNET_TIME_Absolute monotime;
9950 struct TransportDVBoxPayloadP *ppay;
9951 unsigned char pt[hdr_len + sizeof *ppay] GNUNET_ALIGN;
9952 unsigned char *body;
9953 const struct GNUNET_MessageHeader *mh;
9954
9955 ppay = (struct TransportDVBoxPayloadP *) pt;
9956 body = &pt[sizeof *ppay];
9957 GNUNET_assert (hdr_len >=
9958 sizeof(*ppay) + sizeof(struct GNUNET_MessageHeader));
9959 if (GNUNET_OK != GNUNET_CRYPTO_aead_decrypt (hdr_len,
9960 hdr,
9961 0,
9962 NULL,
9963 key,
9964 &dvb->iv,
9965 &dvb->mac,
9966 pt))
9967 {
9969 "Error decrypting DV payload header\n");
9970 GNUNET_break_op (0);
9971 finish_cmc_handling (cmc);
9972 return;
9973 }
9974 mh = (const struct GNUNET_MessageHeader *) body;
9975 /* NOTE: this used to compare against `sizeof (body)', i.e. the size of
9976 a pointer, which meant only 8-byte payloads were ever accepted. */
9977 if (ntohs (mh->size) != hdr_len - sizeof(*ppay))
9978 {
9979 GNUNET_break_op (0);
9980 finish_cmc_handling (cmc);
9981 return;
9982 }
9983 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9984 switch (ntohs (mh->type))
9985 {
9987 GNUNET_break_op (0);
9988 finish_cmc_handling (cmc);
9989 return;
9990
9992 GNUNET_break_op (0);
9993 finish_cmc_handling (cmc);
9994 return;
9995
9996 default:
9997 /* permitted, continue */
9998 break;
9999 }
10000 monotime = GNUNET_TIME_absolute_ntoh (ppay->monotonic_time);
10002 "Decrypted backtalk from %s\n",
10003 GNUNET_i2s (&ppay->sender));
10005 &ppay->sender);
10006 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
10007 {
10009 GST_stats,
10010 "# Backchannel messages dropped: monotonic time not increasing",
10011 1,
10012 GNUNET_NO);
10013 finish_cmc_handling (cmc);
10014 return;
10015 }
10016 if ((NULL == b) ||
10017 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
10018 {
10019 /* Check signature */
10020 const struct GNUNET_PeerIdentity *my_identity;
10021 struct EphemeralConfirmationPS ec;
10022
10025
10027 ec.target = *my_identity;
10028 ec.ephemeral_key = dvb->ephemeral_key;
10029 ec.purpose.size = htonl (sizeof(ec));
10031 if (
10032 GNUNET_OK !=
10035 &ec,
10036 &ppay->sender_sig,
10037 &ppay->sender.public_key))
10038 {
10039 /* Signature invalid, discard! */
10040 GNUNET_break_op (0);
10041 finish_cmc_handling (cmc);
10042 return;
10043 }
10044 }
10045 /* Update sender, we now know the real origin! */
10047 "DVBox received for me from %s via %s\n",
10048 GNUNET_i2s2 (&ppay->sender),
10049 GNUNET_i2s (&cmc->im.sender));
10050 cmc->im.sender = ppay->sender;
10051
10052 if (NULL != b)
10053 {
10054 /* update key cache and mono time */
10055 b->last_ephemeral = dvb->ephemeral_key;
10056 b->monotonic_time = monotime;
10058 b->timeout =
10060 cmc->mh = mh;
10062 return;
10063 }
10064 /* setup data structure to cache signature AND check
10065 monotonic time with PEERSTORE before forwarding backchannel payload */
10066 b = GNUNET_malloc (sizeof(struct Backtalker) + (hdr_len - sizeof(*ppay)));
10067 b->pid = ppay->sender;
10068 b->body_size = hdr_len - sizeof(*ppay);
10069 memcpy (&b[1], body, hdr_len - sizeof(*ppay));
10073 &b->pid,
10074 b,
10076 b->monotonic_time = monotime; /* NOTE: to be checked still! */
10077 b->cmc = cmc;
10078 b->timeout =
10081 b->get =
10083 "transport",
10084 &b->pid,
10087 b);
10088 } /* end actual decryption */
10089}
10090
10091
10099static void
10100handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
10101{
10102 struct CommunicatorMessageContext *cmc = cls;
10103 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
10104 uint16_t num_hops = ntohs (dvb->num_hops);
10105 const struct GNUNET_PeerIdentity *hops =
10106 (const struct GNUNET_PeerIdentity *) &dvb[1];
10107 const char *enc_payload = (const char *) &hops[num_hops];
10108 uint16_t enc_payload_size =
10109 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
10110 const struct GNUNET_PeerIdentity *my_identity;
10111
10114
10115 if (GNUNET_EXTRA_LOGGING > 0)
10116 {
10117 char *path;
10118
10120 for (unsigned int i = 0; i < num_hops; i++)
10121 {
10122 char *tmp;
10123
10124 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
10125 GNUNET_free (path);
10126 path = tmp;
10127 }
10129 "Received DVBox with remaining path %s\n",
10130 path);
10131 GNUNET_free (path);
10132 }
10133
10134 if (num_hops > 0)
10135 {
10136 /* We're trying from the end of the hops array, as we may be
10137 able to find a shortcut unknown to the origin that way */
10138 for (int i = num_hops - 1; i >= 0; i--)
10139 {
10140 struct Neighbour *n;
10141
10142 if (0 == GNUNET_memcmp (&hops[i], my_identity))
10143 {
10144 GNUNET_break_op (0);
10145 finish_cmc_handling (cmc);
10146 return;
10147 }
10148 n = lookup_neighbour (&hops[i]);
10149 if (NULL == n)
10150 continue;
10152 "Skipping %u/%u hops ahead while routing DV Box\n",
10153 i,
10154 num_hops);
10155
10156 forward_dv_box (n,
10157 (struct TransportDVBoxMessage *) dvb,
10158 /* we strip i+1 entries, and the receiver reconstructs
10159 the ciphertext offset from total_hops */
10160 ntohs (dvb->total_hops) + i + 1,
10161 num_hops - i - 1, /* number of hops left */
10162 &hops[i + 1], /* remaining hops */
10163 enc_payload,
10164 enc_payload_size);
10166 "# DV hops skipped routing boxes",
10167 i,
10168 GNUNET_NO);
10170 "# DV boxes routed (total)",
10171 1,
10172 GNUNET_NO);
10173 finish_cmc_handling (cmc);
10174 return;
10175 }
10176 /* Woopsie, next hop not in neighbours, drop! */
10178 "# DV Boxes dropped: next hop unknown",
10179 1,
10180 GNUNET_NO);
10181 finish_cmc_handling (cmc);
10182 return;
10183 }
10184 /* We are the target. Unbox and handle message. */
10186 "# DV boxes opened (ultimate target)",
10187 1,
10188 GNUNET_NO);
10189 cmc->total_hops = ntohs (dvb->total_hops);
10190
10191 {
10192 // DH key derivation with received DV, could be garbage.
10194 struct GNUNET_ShortHashCode km;
10195
10197 if ( (NULL == my_private_key) ||
10198 (GNUNET_OK !=
10200 &dvb->ephemeral_key,
10201 &km)) )
10202 {
10203 GNUNET_break_op (0);
10204 finish_cmc_handling (cmc);
10205 return;
10206 }
10207 decaps_dv_box_cont (cmc,
10208 dvb,
10209 &km);
10210 }
10211}
10212
10213
10221static int
10223 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10224{
10225 struct TransportClient *tc = cls;
10226
10227 if (CT_COMMUNICATOR != tc->type)
10228 {
10229 GNUNET_break (0);
10230 return GNUNET_SYSERR;
10231 }
10233 return GNUNET_OK;
10234}
10235
10236
10241{
10245 const char *address;
10246
10251};
10252
10253
10263static int
10265 const struct GNUNET_PeerIdentity *pid,
10266 void *value)
10267{
10268 struct CheckKnownAddressContext *ckac = cls;
10269 struct ValidationState *vs = value;
10270
10271 (void) pid;
10272 if (0 != strcmp (vs->address, ckac->address))
10273 return GNUNET_OK;
10274 ckac->vs = vs;
10275 return GNUNET_NO;
10276}
10277
10278
10284static void
10285validation_start_cb (void *cls);
10286
10287
10295static void
10297 struct GNUNET_TIME_Absolute new_time)
10298{
10300 struct ValidationState *next;
10301
10302 /* NOTE: "be lazy" must not apply while #validation_task is unset. Our
10303 only caller that can leave it unset is #validation_start_cb(), which
10304 NULLs it on entry and relies on us to arm it again -- and nothing else
10305 ever does. Returning early there stops address (re)validation and the
10306 #suggest_to_connect() retries that go with it for *every* peer, for
10307 good. */
10308 if ((new_time.abs_value_us == vs->next_challenge.abs_value_us) &&
10309 (NULL != validation_task) &&
10310 (NULL != vs->hn))
10311 return; /* be lazy */
10312 vs->next_challenge = new_time;
10313 if (NULL == vs->hn)
10314 vs->hn =
10316 else
10319 (NULL != validation_task))
10320 return;
10321 if (NULL != validation_task)
10323 /* Arm for the earliest entry in the heap, which need NOT be @a vs:
10324 #validation_start_cb() calls us with @e validation_task unset and with
10325 @a vs already pushed out to its new @e challenge_backoff, which doubles
10326 up to #MAX_VALIDATION_CHALLENGE_FREQ (one day) while an address stays
10327 unanswered. Arming for @a vs there parks the single global validation
10328 task for that long, no matter how many other addresses are due right
10329 now -- and every address of a peer we cannot reach (NAT) is such an
10330 address. Everything that needs a validation then stops with it:
10331 bringing a lost link back up, and confirming the link to a peer that
10332 contacted us. */
10334 if (NULL == next)
10335 return;
10336 /* randomize a bit */
10341 delta),
10343 NULL);
10344}
10345
10346
10357static enum GNUNET_GenericReturnValue
10359 const struct GNUNET_PeerIdentity *pid,
10360 void *value)
10361{
10362 struct ValidationState *vs = value;
10363 const struct GNUNET_TIME_Absolute now =
10365
10366 (void) cls;
10367 (void) pid;
10368 /* What #start_address_validation() does for an address it hears about
10369 again, but without needing the address string. */
10370 vs->challenge_backoff =
10373 vs->challenge_backoff,
10374 2));
10375 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
10376 vs->first_challenge_use = now;
10379 vs->challenge_backoff));
10380 return GNUNET_OK;
10381}
10382
10383
10390static void
10392 const char *address)
10393{
10394 struct GNUNET_TIME_Absolute now;
10395 struct ValidationState *vs;
10396 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
10397
10399 pid,
10401 &ckac);
10403 if (NULL != (vs = ckac.vs))
10404 {
10405 const struct VirtualLink *vl = lookup_virtual_link (pid);
10406
10407 /* Speed up retrying the validation if 'vs' is not currently valid, or if
10408 * we have no confirmed virtual link to @a pid. In the latter case the
10409 * address may still be well inside its validity window -- but the link is
10410 * down, and #handle_validation_response() is the only thing that can
10411 * rebuild it and tell CORE about the peer again. Without this we would
10412 * wait for @e revalidation_task, which does not fire until
10413 * #ADDRESS_VALIDATION_LIFETIME is nearly over. */
10414 if ((vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us) ||
10415 (NULL == vl) ||
10416 (GNUNET_NO == vl->confirmed))
10417 {
10418 /* reduce backoff as we got a fresh advertisement */
10419 vs->challenge_backoff =
10422 vs->challenge_backoff,
10423 2));
10424 /* A successful validation parks @e first_challenge_use just before
10425 @e validated_until, so that the *next* challenge is not used before
10426 the current validation is about to expire. #validation_start_cb()
10427 refuses to run while that time is still in the future, so pulling
10428 @e next_challenge in without this would only make it reschedule
10429 itself four hours out. The challenge has not been used yet, so
10430 moving the start of its window to now stays truthful -- it is what
10431 the fresh-@a vs path below does as well. */
10432 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
10433 vs->first_challenge_use = now;
10436 vs->challenge_backoff));
10437 }
10438 return;
10439 }
10440 vs = GNUNET_new (struct ValidationState);
10441 vs->pid = *pid;
10442 vs->valid_until =
10444 vs->first_challenge_use = now;
10445 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
10446 GNUNET_CRYPTO_random_block (&vs->challenge,
10447 sizeof(vs->challenge));
10448 vs->address = GNUNET_strdup (address);
10449 {
10450 /* The peer identity MUST be part of @e hc: two peers behind the same NAT
10451 advertise the very same address string (`PROTO-IP:0'), and with an
10452 address-only key the second one's #revalidation_map entry would be
10453 rejected as a duplicate of the first one's. */
10454 struct GNUNET_HashContext *hsh;
10455
10457 GNUNET_CRYPTO_hash_context_read (hsh, vs->address, strlen (vs->address));
10458 GNUNET_CRYPTO_hash_context_read (hsh, &vs->pid, sizeof(vs->pid));
10459 GNUNET_CRYPTO_hash_context_finish (hsh, &vs->hc);
10460 }
10462 "Starting address validation `%s' of peer %s using challenge %s\n",
10463 address,
10464 GNUNET_i2s (pid),
10465 GNUNET_sh2s (&vs->challenge.value));
10469 &vs->pid,
10470 vs,
10473}
10474
10475
10476static struct Queue *
10477find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
10478
10479
10480static void
10481suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
10482
10483
10484static void
10486 const struct GNUNET_PeerIdentity *pid,
10487 const char *uri)
10488{
10489 struct Queue *q;
10490 int pfx_len;
10491 const char *eou;
10492 char *address;
10493 (void) cls;
10494
10495 eou = strstr (uri,
10496 "://");
10497 pfx_len = eou - uri;
10498 eou += 3;
10500 "%.*s-%s",
10501 pfx_len,
10502 uri,
10503 eou);
10504
10506 "helo for client %s\n",
10507 address);
10508 q = find_queue (pid, address);
10509 if (NULL == q)
10510 {
10512 }
10513 else
10516}
10517
10518
10541static const struct GNUNET_MessageHeader *
10543{
10544 const struct GNUNET_MessageHeader *hello;
10545
10546 if ((NULL == record) ||
10547 (NULL == record->value) ||
10548 (record->value_size < sizeof(*hello)))
10549 {
10550 GNUNET_break_op (0);
10551 return NULL;
10552 }
10553 hello = record->value;
10554 if (ntohs (hello->size) > record->value_size)
10555 {
10556 GNUNET_break_op (0);
10557 return NULL;
10558 }
10559 return hello;
10560}
10561
10562
10570static void
10572 const struct GNUNET_PEERSTORE_Record *record,
10573 const char *emsg)
10574{
10575 struct IncomingRequest *ir = cls;
10576 struct GNUNET_HELLO_Parser *parser;
10577 const struct GNUNET_MessageHeader *hello;
10578 const struct GNUNET_PeerIdentity *my_identity;
10579
10580 if (NULL != emsg)
10581 {
10583 "Got failure from PEERSTORE: %s\n",
10584 emsg);
10586 return;
10587 }
10588 if (NULL == record)
10589 {
10590 GNUNET_break (0);
10592 return;
10593 }
10594 hello = hello_from_record (record);
10595 if (NULL == hello)
10596 {
10597 /* MUST still ask for the next record: a bad one is not a reason to
10598 stall this monitor forever. */
10600 return;
10601 }
10603 if (NULL == my_identity)
10604 {
10606 return;
10607 }
10608 if (0 == GNUNET_memcmp (&record->peer, my_identity))
10609 {
10611 return;
10612 }
10613 if (0 != GNUNET_memcmp (&record->peer, &ir->pid))
10614 {
10615 /* Not the peer this request is about. */
10617 return;
10618 }
10619 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10620 if (NULL != parser)
10621 {
10624 NULL);
10625 GNUNET_HELLO_parser_free (parser);
10626 }
10627 /* MUST ask for the next record, or this monitor stalls after one HELLO */
10629}
10630
10631
10632static void
10634{
10636 "Error in PEERSTORE monitoring\n");
10637}
10638
10639
10640static void
10642{
10644 "Done with initial PEERSTORE iteration during monitoring\n");
10645}
10646
10647
10656static void
10658{
10659 struct Neighbour *n;
10660 struct IncomingRequest *ir;
10661
10662 if (GNUNET_YES == in_shutdown)
10663 return;
10664 /* (1) Addresses we already track. These outlive the queues, which is the
10665 point: once a link is down the queue that carried it is usually gone,
10666 so there is no address string left for #start_address_validation(). */
10668 pid,
10670 NULL);
10671 /* (2) Queues we still have; may cover an address with no validation state
10672 yet. After (1), because it may insert into #validation_map. */
10673 n = lookup_neighbour (pid);
10674 if (NULL != n)
10675 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
10676 start_address_validation (pid, q->address);
10677 /* (3) Failing that, look for an address in PEERSTORE. */
10678 for (ir = ir_head; NULL != ir; ir = ir->next)
10679 {
10680 if (0 == GNUNET_memcmp (&ir->pid, pid))
10681 return; /* we are already trying */
10682 }
10683 ir = GNUNET_new (struct IncomingRequest);
10684 ir->pid = *pid;
10686 /* Monitor only @a pid: with NULL every request sees every HELLO in
10687 PEERSTORE, so each of the up to #MAX_INCOMING_REQUEST requests started
10688 a connection attempt and an address validation for peers it was not
10689 created for. */
10691 GNUNET_YES,
10692 "peerstore",
10693 &ir->pid,
10696 NULL,
10698 NULL,
10700 ir);
10701 ir_total++;
10702 /* Bound attempts we do in parallel here, might otherwise get excessive.
10703 Drop the OLDEST request: #ir_head is the one we just inserted, so
10704 freeing that would immediately undo the work above. */
10707}
10708
10709
10717static void
10720{
10721 struct VirtualLink *vl;
10722 struct Neighbour *n;
10723 struct GNUNET_PeerIdentity sender;
10724
10725 sender = cmc->im.sender;
10726 vl = lookup_virtual_link (&sender);
10727 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
10728 {
10729 // route_control_message_without_fc (&cmc->im.sender,
10731 &tvr.header,
10733 }
10734 else
10735 {
10736 /* Use route via neighbour */
10737 n = lookup_neighbour (&sender);
10738 if (NULL != n)
10739 route_via_neighbour (n, &tvr.header,
10742 }
10743
10744 finish_cmc_handling (cmc);
10745 /* An *unconfirmed* link is not a link -- it carries nothing, and CORE has
10746 never been told about the peer. Bailing out on one merely because it
10747 exists is what deadlocks a pair of peers into permanent one-way state:
10748 the challenger validated us, so it believes the connection is up and
10749 starts sending us FLOW_CONTROL; #handle_flow_control() answers an
10750 unknown sender by allocating exactly such an unconfirmed link; and from
10751 then on every challenge it retransmits lands here, gets a response --
10752 which keeps *its* side confirmed and its RTT healthy -- and returns
10753 without ever validating an address of its own. The unconfirmed link
10754 reaps itself after #UNCONFIRMED_LINK_TIMEOUT, but the next FLOW_CONTROL
10755 recreates it, and the peer keeps sending those precisely because it
10756 thinks it is connected. Nothing ever breaks the tie, so CORE on this
10757 side never hears about the peer and never answers its handshake.
10758 Only a confirmed link means there is nothing left to do. */
10759 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
10760 return;
10761
10762 /* For us, the link is still down, but we need bi-directional
10763 connections (for flow-control and for this to be useful for
10764 CORE), so we must try to bring the link up! */
10765 try_to_bring_link_up (&sender);
10766}
10767
10768
10777static void
10779 void *cls,
10780 const struct TransportValidationChallengeMessage *tvc)
10781{
10782 struct CommunicatorMessageContext *cmc = cls;
10783 struct TransportValidationResponseMessage tvr = { 0 };
10784 struct GNUNET_TIME_RelativeNBO validity_duration;
10785
10786 /* DV-routed messages are not allowed for validation challenges */
10787 if (cmc->total_hops > 0)
10788 {
10789 GNUNET_break_op (0);
10790 finish_cmc_handling (cmc);
10791 return;
10792 }
10793 validity_duration = cmc->im.expected_address_validity;
10795 "Received address validation challenge %s\n",
10796 GNUNET_sh2s (&tvc->challenge.value));
10797 /* If we have a virtual link, we use this mechanism to signal the
10798 size of the flow control window, and to allow the sender
10799 to ask for increases. If for us the virtual link is still down,
10800 we will always give a window size of zero. */
10801 tvr.header.type =
10803 tvr.header.size = htons (sizeof(tvr));
10804 tvr.reserved = htonl (0);
10805 tvr.challenge = tvc->challenge;
10806 tvr.origin_time = tvc->sender_time;
10807 tvr.validity_duration = validity_duration;
10808 {
10809 /* create signature */
10810 struct TransportValidationPS tvp = {
10812 .purpose.size = htonl (sizeof(tvp)),
10813 .validity_duration = validity_duration,
10814 .challenge = tvc->challenge
10815 };
10816 if (GNUNET_OK != sign_by_my_identity (&tvp.purpose, &tvr.signature))
10817 {
10818 /* Not answering costs us this address validation; leaving @a cmc
10819 behind would cost us the communicator. */
10820 finish_cmc_handling (cmc);
10821 return;
10822 }
10823 }
10824 send_t_validation_response (cmc, tvr);
10825}
10826
10827
10843
10844
10854static int
10856 const struct GNUNET_PeerIdentity *pid,
10857 void *value)
10858{
10859 struct CheckKnownChallengeContext *ckac = cls;
10860 struct ValidationState *vs = value;
10861
10862 (void) pid;
10863 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
10864 return GNUNET_OK;
10865 ckac->vs = vs;
10866 return GNUNET_NO;
10867}
10868
10869
10877static void
10878peerstore_store_validation_cb (void *cls, int success)
10879{
10880 struct ValidationState *vs = cls;
10881
10882 vs->sc = NULL;
10883 if (GNUNET_YES == success)
10884 return;
10886 "# Peerstore failed to store foreign address",
10887 1,
10888 GNUNET_NO);
10889}
10890
10891
10899static struct Queue *
10900find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
10901{
10902 struct Neighbour *n;
10903
10904 n = lookup_neighbour (pid);
10905 if (NULL == n)
10906 return NULL;
10907 for (struct Queue *pos = n->queue_head; NULL != pos;
10908 pos = pos->next_neighbour)
10909 {
10910 if (0 == strcmp (pos->address, address))
10911 return pos;
10912 }
10913 return NULL;
10914}
10915
10916
10932static struct Queue *
10933find_queue_by_ip (const struct GNUNET_PeerIdentity *pid, const char *address)
10934{
10935 struct Neighbour *n;
10936 struct Queue *ret = NULL;
10937 char *prefix;
10938 char *ip;
10939
10940 n = lookup_neighbour (pid);
10941 if (NULL == n)
10942 return NULL;
10945 if ((NULL == prefix) || (NULL == ip))
10946 {
10948 GNUNET_free (ip);
10949 return NULL;
10950 }
10951 for (struct Queue *pos = n->queue_head; NULL != pos;
10952 pos = pos->next_neighbour)
10953 {
10954 char *q_prefix = GNUNET_HELLO_address_to_prefix (pos->address);
10955 char *q_ip = get_address_without_port (pos->address);
10956
10957 /* Same communicator and same host -- only the port may differ. */
10958 if ((NULL != q_prefix) && (NULL != q_ip) &&
10959 (0 == strcmp (q_prefix, prefix)) &&
10960 (0 == strcmp (q_ip, ip)))
10961 ret = pos;
10962 GNUNET_free (q_prefix);
10963 GNUNET_free (q_ip);
10964 if (NULL != ret)
10965 break;
10966 }
10968 GNUNET_free (ip);
10969 return ret;
10970}
10971
10972
10973static void
10975
10976static void
10978{
10979 struct ValidationState *vs = cls;
10980 struct Queue *q;
10981 struct GNUNET_TIME_Absolute now;
10982
10983 vs->revalidation_task = NULL;
10984 q = find_queue (&vs->pid, vs->address);
10985 if (NULL == q)
10986 {
10987 now = GNUNET_TIME_absolute_get ();
10988 vs->awaiting_queue = GNUNET_YES;
10989 suggest_to_connect (&vs->pid, vs->address);
10991 }
10992 else
10994}
10995
10996
10997static enum GNUNET_GenericReturnValue
10999 void *cls,
11000 const struct GNUNET_HashCode *key,
11001 void *value)
11002{
11003 (void) cls;
11005 "Key in revalidate map %s \n",
11006 GNUNET_h2s (key));
11007 return GNUNET_YES;
11008}
11009
11010
11019static void
11021 void *cls,
11022 const struct TransportValidationResponseMessage *tvr)
11023{
11024 struct CommunicatorMessageContext *cmc = cls;
11025 struct ValidationState *vs;
11026 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
11027 .vs = NULL};
11028 struct GNUNET_TIME_Absolute origin_time;
11029 struct Queue *q;
11030 struct Neighbour *n;
11031 struct VirtualLink *vl;
11033 GST_cfg);
11034
11035 /* check this is one of our challenges */
11037 &cmc->im.sender,
11039 &ckac);
11040 if (NULL == (vs = ckac.vs))
11041 {
11042 /* This can happen simply if we 'forgot' the challenge by now,
11043 i.e. because we received the validation response twice */
11045 "# Validations dropped, challenge unknown",
11046 1,
11047 GNUNET_NO);
11049 "Validation response %s dropped, challenge unknown\n",
11050 GNUNET_sh2s (&tvr->challenge.value));
11051 finish_cmc_handling (cmc);
11052 return;
11053 }
11054
11055 /* sanity check on origin time */
11056 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
11057 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
11058 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
11059 {
11061 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
11062 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
11063 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
11064 GNUNET_break_op (0);
11065 finish_cmc_handling (cmc);
11066 return;
11067 }
11068
11069 {
11070 /* check signature */
11071 struct TransportValidationPS tvp = {
11073 .purpose.size = htonl (sizeof(tvp)),
11074 .validity_duration = tvr->validity_duration,
11075 .challenge = tvr->challenge
11076 };
11077
11078 if (
11079 GNUNET_OK !=
11081 &tvp,
11082 &tvr->signature,
11083 &cmc->im.sender.public_key))
11084 {
11085 GNUNET_break_op (0);
11086 finish_cmc_handling (cmc);
11087 return;
11088 }
11089 }
11090
11091 /* validity is capped by our willingness to keep track of the
11092 validation entry and the maximum the other peer allows */
11095 tvr->validity_duration),
11097 vs->validated_until =
11101 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
11102 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
11103 GNUNET_CRYPTO_random_block (&vs->challenge,
11104 sizeof(vs->challenge));
11105 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
11106 vs->validated_until,
11107 GNUNET_TIME_relative_multiply (vs->validation_rtt,
11109 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
11110 {
11112 "First challenge use is now %" PRIu64 " %s \n",
11113 vs->first_challenge_use.abs_value_us,
11114 GNUNET_sh2s (&vs->challenge.value));
11115 vs->first_challenge_use = now;
11116 }
11117 else
11119 "First challenge use is later %" PRIu64 " %s \n",
11120 vs->first_challenge_use.abs_value_us,
11121 GNUNET_sh2s (&vs->challenge.value));
11122 vs->last_challenge_use =
11123 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
11124 update_next_challenge_time (vs, vs->first_challenge_use);
11126 "Validation response %s from %s accepted, address valid until %s\n",
11127 GNUNET_sh2s (&tvr->challenge.value),
11128 GNUNET_i2s (&cmc->im.sender),
11130 /*memcpy (&hkey,
11131 &hc,
11132 sizeof (hkey));*/
11134 "Key %s for address %s map size %u contains %u\n",
11135 GNUNET_h2s (&vs->hc),
11136 vs->address,
11139 &vs->hc));
11140 /* NOTE: @e hc hashes the address only, so two `struct ValidationState's
11141 for different peers can collide here. That must not abort us. */
11142 if (GNUNET_YES !=
11145 &vs->hc,
11146 vs,
11149 "Address `%s' already tracked for revalidation\n",
11150 vs->address);
11153 NULL);
11154 vs->revalidation_task =
11159 "transport",
11160 &cmc->im.sender,
11162 vs->address,
11163 strlen (vs->address) + 1,
11164 vs->valid_until,
11167 vs);
11168 finish_cmc_handling (cmc);
11169
11170 /* Finally, we now possibly have a confirmed (!) working queue,
11171 update queue status (if queue still is around) */
11172 q = find_queue (&vs->pid, vs->address);
11173 if (NULL == q)
11174 {
11175 /* The challenge may have gone out on a queue whose address is not
11176 literally @e address: #check_validation_request_pending() matches on
11177 the IP alone, precisely so that a validation waiting for the NAT
11178 address `PROTO-IP:0' can be answered over the queue that the peer
11179 actually established from `PROTO-IP:port'. Insisting on an exact
11180 match here would silently discard that (successful!) validation and
11181 never bring the virtual link up. */
11182 q = find_queue_by_ip (&vs->pid, vs->address);
11183 }
11184 if (NULL == q)
11185 {
11187 "# Queues lost at time of successful validation",
11188 1,
11189 GNUNET_NO);
11190 return;
11191 }
11192 q->validated_until = vs->validated_until;
11193 q->pd.aged_rtt = vs->validation_rtt;
11194 n = q->neighbour;
11195 vl = lookup_virtual_link (&vs->pid);
11196 if (NULL == vl)
11197 {
11198 vl = GNUNET_new (struct VirtualLink);
11200 "Creating new virtual link %p to %s using direct neighbour!\n",
11201 vl,
11202 GNUNET_i2s (&vs->pid));
11203 vl->burst_addr = NULL;
11204 vl->confirmed = GNUNET_YES;
11205 vl->message_uuid_ctr =
11206 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
11207 vl->target = n->pid;
11211 /* What the peer will grant us in its very first FLOW_CONTROL anyway
11212 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
11213 Starting at zero instead means a link that is up, validated and
11214 working carries nothing at all until an FC round trip completes --
11215 and if the peer cannot answer, not ever. */
11219 links,
11220 &vl->target,
11221 vl,
11223 vl->n = n;
11224 n->vl = vl;
11225 q->idle = GNUNET_YES;
11226 vl->visibility_task =
11227 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
11229 /* We lacked a confirmed connection to the target
11230 before, so tell CORE about it (finally!) */
11233 }
11234 else
11235 {
11236 /* Link was already up, remember n is also now available and we are done */
11237 if (NULL == vl->n)
11238 {
11239 vl->n = n;
11240 n->vl = vl;
11241 if (GNUNET_YES == vl->confirmed)
11243 "Virtual link to %s could now also use direct neighbour!\n",
11244 GNUNET_i2s (&vs->pid));
11245 }
11246 else
11247 {
11248 GNUNET_assert (n == vl->n);
11249 }
11250 if (GNUNET_NO == vl->confirmed)
11251 {
11252 vl->confirmed = GNUNET_YES;
11253 q->idle = GNUNET_YES;
11254 vl->visibility_task =
11255 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
11257 /* We lacked a confirmed connection to the target
11258 before, so tell CORE about it (finally!) */
11261 }
11262 }
11263}
11264
11265
11271static void
11273 const struct GNUNET_TRANSPORT_IncomingMessage *im)
11274{
11275 struct TransportClient *tc = cls;
11276 struct Neighbour *n;
11277 struct CommunicatorMessageContext *cmc =
11279
11280 cmc->tc = tc;
11281 cmc->im = *im;
11283 "Received message with size %u and flow control id %" PRIu64
11284 " via communicator from peer %s\n",
11285 ntohs (im->header.size),
11286 im->fc_id,
11287 GNUNET_i2s (&im->sender));
11288 cmc->im.neighbour_sender = cmc->im.sender;
11289 /* A communicator got this straight from @a im->sender, so the queues to
11290 that neighbour demonstrably still work. This is what #check_link_down()
11291 uses to bound how long a communicator that stopped working (without
11292 telling us) can keep a virtual link -- and CORE -- fooled. */
11293 if (NULL != (n = lookup_neighbour (&im->sender)))
11295 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
11297}
11298
11299
11308static int
11310{
11311 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
11312 uint16_t msize = ntohs (fc->header.size);
11313 const char *tgnas;
11314 size_t avail;
11315 size_t off;
11316
11317 (void) cls;
11319 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
11320 ntohs (fc->header.size),
11321 ntohl (fc->size_of_addresses),
11322 ntohl (fc->number_of_addresses),
11323 sizeof(struct TransportFlowControlMessage),
11324 sizeof (struct TransportGlobalNattedAddress));
11325 if (0 == number_of_addresses)
11326 return GNUNET_OK;
11327 if (msize < sizeof(struct TransportFlowControlMessage))
11328 {
11329 GNUNET_break_op (0);
11330 return GNUNET_SYSERR;
11331 }
11332 avail = msize - sizeof(struct TransportFlowControlMessage);
11333 tgnas = (const char *) &fc[1];
11334 off = 0;
11335 /* Validate EVERY entry: checking only the aggregate size lets a single
11336 entry claim a bogus address_length and send #handle_flow_control()
11337 out of bounds. */
11338 for (unsigned int i = 0; i < number_of_addresses; i++)
11339 {
11340 const struct TransportGlobalNattedAddress *tgna;
11341 size_t alen;
11342
11343 if (avail - off < sizeof(struct TransportGlobalNattedAddress))
11344 {
11345 GNUNET_break_op (0);
11346 return GNUNET_SYSERR;
11347 }
11348 tgna = (const struct TransportGlobalNattedAddress *) &tgnas[off];
11349 off += sizeof(struct TransportGlobalNattedAddress);
11350 alen = ntohl (tgna->address_length);
11351 if (avail - off < alen)
11352 {
11353 GNUNET_break_op (0);
11354 return GNUNET_SYSERR;
11355 }
11356 off += alen;
11357 }
11358 return GNUNET_OK;
11359}
11360
11361
11362static struct GNUNET_TIME_Relative
11364{
11366 unsigned int n_hops = 0;
11367
11369 "calculate_rtt\n");
11370 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
11371 pos = pos->next_dv)
11372 {
11374 "calculate_rtt %lu\n",
11375 (unsigned long) pos->pd.aged_rtt.rel_value_us);
11376 n_hops++;
11378 aged_rtt, pos
11379 ->distance
11380 + 2), ret);
11381 }
11382
11383 if (0 == n_hops)
11385 return ret;
11386}
11387
11388
11389static void
11391 const struct GNUNET_PeerIdentity *pid,
11392 const char *uri)
11393{
11394 struct VirtualLink *vl = cls;
11395 const char *slash;
11396 char *address_uri;
11397 char *prefix;
11398 char *uri_without_port;
11399
11400 slash = strrchr (uri, '/');
11401 if ((NULL == slash) || (slash - uri < 2))
11402 {
11403 GNUNET_break_op (0); /* @a uri comes from a remote HELLO */
11404 return;
11405 }
11406 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
11407 slash++;
11408 GNUNET_asprintf (&address_uri,
11409 "%s-%s",
11410 prefix,
11411 slash);
11412
11413 uri_without_port = get_address_without_port (address_uri);
11415 "iterate_address_start_burst %s %s %s %s\n",
11416 (NULL == uri_without_port) ? "<unparsable>" : uri_without_port,
11417 uri,
11418 address_uri,
11419 slash);
11420 GNUNET_free (vl->burst_addr);
11421 if ((NULL != uri_without_port) &&
11422 (0 == strcmp (uri_without_port, slash)))
11423 vl->burst_addr = GNUNET_strdup (uri_without_port);
11424
11426 GNUNET_free (address_uri);
11427 GNUNET_free (uri_without_port);
11428}
11429
11430
11431static void
11433 const struct GNUNET_PEERSTORE_Record *record,
11434 const char *emsg)
11435{
11436 struct GNUNET_StartBurstCls *sb_cls = cls;
11437 struct VirtualLink *vl = sb_cls->vl;
11438 const struct GNUNET_MessageHeader *hello;
11439 struct GNUNET_HELLO_Parser *parser;
11440
11441 if (NULL != emsg)
11442 {
11444 "Got failure from PEERSTORE: %s\n",
11445 emsg);
11446 /* @a emsg comes with a NULL record, which means the iteration is over
11447 and PEERSTORE is releasing the context itself -- stopping it here as
11448 well would free it twice. Just drop our handle. */
11449 vl->ic = NULL;
11450 free_burst_cls (sb_cls);
11451 return;
11452 }
11453 if (NULL == record)
11454 {
11456 "Hello iteration end for %s\n",
11457 GNUNET_i2s (&vl->target));
11458 /* PEERSTORE destroys the context itself once it signals the end. */
11459 vl->ic = NULL;
11460 free_burst_cls (sb_cls);
11461 return;
11462 }
11463
11465 "check_for_burst_address\n");
11466 /* @a hello was published by a remote peer, it may well be malformed. */
11467 hello = hello_from_record (record);
11468 if (NULL != hello)
11469 {
11470 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
11471 if (NULL != parser)
11472 {
11475 vl);
11476 GNUNET_HELLO_parser_free (parser);
11477 }
11478 }
11479
11480 /* MUST clear @e ic: #GNUNET_PEERSTORE_iteration_stop() frees it, and
11481 #free_virtual_link() would otherwise stop it a second time. */
11482 if (NULL != vl->ic)
11483 {
11485 vl->ic = NULL;
11486 }
11487 free_burst_cls (sb_cls);
11488}
11489
11490
11491static void
11492burst_timeout (void *cls)
11493{
11495}
11496
11497
11498static void
11499start_burst (void *cls)
11500{
11501 struct GNUNET_StartBurstCls *sb_cls = cls;
11502 struct VirtualLink *vl = sb_cls->vl;
11503 struct GNUNET_TRANSPORT_StartBurst *sb;
11504 struct GNUNET_MQ_Envelope *env;
11505 char *uri_without_port = vl->burst_addr;
11506
11507 burst_task = NULL;
11508 burst_task_cls = NULL;
11509 if (NULL == uri_without_port)
11510 {
11511 /* Lost the address in the meantime, nothing to burst to. */
11512 free_burst_cls (sb_cls);
11513 return;
11514 }
11515 /*char buf[strlen (uri_without_port) + 1];
11516
11517 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
11518 buf[strlen (uri_without_port)] = '\0';*/
11519 env =
11521 strlen (uri_without_port) + 1,
11523 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
11524 sb->pid = vl->target;
11525 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
11526 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11527 {
11528 if (CT_COMMUNICATOR != tc->type)
11529 continue; /* MUST come first: the log below reads the union! */
11531 "iterate_address_start_burst client tc prefix %s\n",
11532 tc->details.communicator.address_prefix);
11533 if (GNUNET_YES == tc->details.communicator.can_burst)
11534 {
11536 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
11537 uri_without_port,
11538 strlen (uri_without_port),
11539 ntohs (sb->header.size),
11540 (unsigned long) sb_cls->rtt.rel_value_us);
11541 GNUNET_MQ_send (tc->mq, env);
11542 env = NULL; /* MQ took ownership */
11546 60),
11548 NULL);
11549 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
11550 break;
11551 }
11552 }
11553 if (NULL != env)
11555 free_burst_cls (sb_cls);
11556}
11557
11558
11565static void
11567{
11568 struct VirtualLink *vl = sb_cls->vl;
11569
11570 if (burst_task_cls == sb_cls)
11571 {
11572 if (NULL != burst_task)
11573 {
11575 burst_task = NULL;
11576 }
11577 burst_task_cls = NULL;
11578 }
11579 if ((NULL != vl) && (vl->sb_cls == sb_cls))
11580 vl->sb_cls = NULL;
11582}
11583
11584
11585static void
11586queue_burst (void *cls)
11587{
11588 struct GNUNET_StartBurstCls *sb_cls = cls;
11589 struct VirtualLink *vl = sb_cls->vl;
11590
11591 if (GNUNET_YES != use_burst)
11592 {
11593 /* MUST release: nobody else owns @a sb_cls, and #handle_flow_control()
11594 allocates one for every FLOW_CONTROL message we receive. */
11596 return;
11597 }
11599 "burst_task %p ready %s burst addr %s (%p)\n",
11600 burst_task,
11601 sb_cls->sync_ready ? "yes" : "no",
11602 vl->burst_addr,
11603 vl->burst_addr);
11604 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
11605 {
11606 /* Cancel the pending burst. Both closures (the scheduled task's and
11607 ours) are ours to release. */
11609
11611 burst_task = NULL;
11612 burst_task_cls = NULL;
11613 if ((NULL != pending) && (pending != sb_cls))
11615 free_burst_cls (sb_cls);
11616 return;
11617 }
11618 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
11619 )
11620 {
11622 &start_burst,
11623 sb_cls);
11624 burst_task_cls = sb_cls;
11625 }
11626 else if (NULL == vl->burst_addr)
11627 {
11628 if (NULL != vl->ic)
11629 {
11630 /* An address lookup is already running for this link; starting a
11631 second one would leak the first. */
11632 free_burst_cls (sb_cls);
11633 return;
11634 }
11636 "peerstore",
11637 &vl->target,
11640 sb_cls);
11641 }
11642 else
11643 {
11644 /* A burst is already running or already scheduled; we have no use for
11645 this closure. */
11646 free_burst_cls (sb_cls);
11647 }
11648}
11649
11650
11657static void
11659{
11660 struct VirtualLink *vl = cls;
11661
11662 vl->unconfirmed_timeout_task = NULL;
11663 if ((GNUNET_YES == vl->confirmed) ||
11664 (NULL != vl->n) ||
11665 (NULL != vl->dv))
11666 return; /* got promoted in the meantime, its owner will clean up */
11668 "Discarding unconfirmed virtual link to %s\n",
11669 GNUNET_i2s (&vl->target));
11671 "# Unconfirmed virtual links timed out",
11672 1,
11673 GNUNET_NO);
11674 free_virtual_link (vl);
11675}
11676
11677
11686static void
11688{
11689 struct CommunicatorMessageContext *cmc = cls;
11690 struct VirtualLink *vl;
11692 uint32_t seq;
11693 struct GNUNET_TIME_Absolute st;
11694 uint64_t os;
11695 uint64_t wnd;
11696 uint32_t random;
11697
11699 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
11700 vl = lookup_virtual_link (&cmc->im.sender);
11701 if (NULL == vl)
11702 {
11703 vl = GNUNET_new (struct VirtualLink);
11705 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
11706 vl,
11707 GNUNET_i2s (&cmc->im.sender));
11708 vl->burst_addr = NULL;
11709 vl->confirmed = GNUNET_NO;
11710 vl->message_uuid_ctr =
11711 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
11712 vl->target = cmc->im.sender;
11716 /* What the peer will grant us in its very first FLOW_CONTROL anyway
11717 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
11718 Starting at zero instead means a link that is up, validated and
11719 working carries nothing at all until an FC round trip completes --
11720 and if the peer cannot answer, not ever. */
11724 links,
11725 &vl->target,
11726 vl,
11728 /* Nothing else owns this link yet, so it must reap itself if it never
11729 becomes confirmed -- otherwise any peer can make us allocate
11730 VirtualLinks without bound. */
11734 vl);
11735 }
11736 if (GNUNET_YES != vl->confirmed)
11737 {
11738 /* The peer flow-controls us, so it has a confirmed link to us -- but an
11739 unconfirmed link carries nothing and is never reported to CORE. Only
11740 #handle_validation_response() breaks that tie, and nothing here used
11741 to ask for one, so the pair could sit one-way until the peer's own
11742 four hour revalidation came round. */
11744 }
11745 if (NULL != vl->n)
11746 {
11747 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
11748 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
11749 }
11750
11752 "remaining %lu timeout for neighbour %p\n",
11753 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
11754 rel_value_us,
11755 vl->n);
11756 if (NULL == vl->n ||
11757 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
11758 {
11759 struct GNUNET_TIME_Relative rtt;
11760 struct GNUNET_BurstSync burst_sync;
11761 struct GNUNET_StartBurstCls *bcls;
11762
11763 if (NULL != vl->sb_cls)
11764 {
11765 /* A burst attempt for this link is already in flight. Allocating a
11766 second closure would orphan the first one: @e sb_cls is how
11767 #free_virtual_link() finds (and cancels) the pending #burst_task,
11768 and a peer that just keeps sending us FLOW_CONTROL messages would
11769 otherwise make us leak one closure per message. */
11771 "Burst attempt to %s already pending\n",
11772 GNUNET_i2s (&vl->target));
11773 }
11774 else
11775 {
11776 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
11777 bcls->vl = vl;
11778 vl->sb_cls = bcls;
11779 if (NULL != vl->dv)
11780 rtt = calculate_rtt (vl->dv);
11781 else
11783 burst_sync.rtt_average = fc->rtt;
11784 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
11785 /* @e sync_ready of `struct GNUNET_BurstSync' is a host-order enum. */
11786 burst_sync.sync_ready =
11787 (enum GNUNET_GenericReturnValue) ntohl (fc->sync_ready);
11788
11789 /* NOTE: #GNUNET_is_burst_ready() does NOT invoke the task unless both
11790 RTT estimates are known and close; #queue_burst() is thus not
11791 guaranteed to run, which is why @e sb_cls stays owned by @a vl. */
11793 &burst_sync,
11794 &queue_burst,
11795 bcls);
11796 }
11797 }
11798 if (0 != ntohl (fc->number_of_addresses))
11799 {
11800 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
11801 const char *tgnas;
11802 unsigned int off = 0;
11803
11804 tgnas = (const char *) &fc[1];
11805
11806 for (unsigned int i = 0; i < number_of_addresses; i++)
11807 {
11808 struct TransportGlobalNattedAddress *tgna;
11809 char *addr;
11810 uint32_t address_length;
11811
11812 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
11813 addr = (char *) &tgna[1];
11814 address_length = ntohl (tgna->address_length);
11815 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
11816
11817 /* NOTE: the address is NOT 0-terminated (it comes straight off the
11818 wire), it must be printed with an explicit precision. */
11820 "received address %.*s length %u\n",
11821 (int) address_length,
11822 addr,
11824
11825 if (NULL != nh)
11826 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
11827 }
11828 }
11830 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
11831 {
11833 "FC dropped: Message out of order\n");
11834 /* out of order, drop */
11836 "# FC dropped: message out of order",
11837 1,
11838 GNUNET_NO);
11839 finish_cmc_handling (cmc);
11840 return;
11841 }
11842 seq = ntohl (fc->seq);
11843 if (seq < vl->last_fc_seq)
11844 {
11845 /* Wrap-around/reset of other peer; start all counters from zero */
11847 }
11848 vl->last_fc_seq = seq;
11849 vl->last_fc_timestamp = st;
11850 /* The peer is answering, so the backoff in #consider_sending_fc() starts
11851 over: @e fc_retransmit_count counts *unanswered* rounds. */
11852 vl->fc_retransmit_count = 0;
11854 os = GNUNET_ntohll (fc->outbound_sent);
11856 (int64_t) (os - vl->incoming_fc_window_size_used);
11858 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
11859 GNUNET_i2s (&vl->target),
11860 (unsigned int) seq,
11861 (unsigned long long) vl->outbound_fc_window_size,
11862 (long long) vl->incoming_fc_window_size_loss);
11864 random = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
11865 /* NOTE: this must NOT be restricted to a confirmed link. @e
11866 outbound_fc_window_size starts at zero and is raised *only* here, from
11867 the peer's FC. So a peer whose link to us is confirmed while ours to it
11868 is not cannot send us a single byte until we answer -- and it is exactly
11869 that peer that keeps asking. Staying quiet deadlocks the pair: it shows
11870 an established virtual link with messages pending forever, we show none,
11871 and CORE never completes its handshake in either direction. */
11872 if ((wnd < vl->incoming_fc_window_size
11876 (0 == random % FC_NO_CHANGE_REPLY_PROBABILITY))
11877 {
11879 "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",
11880 (unsigned long long) wnd,
11881 (unsigned long long) vl->incoming_fc_window_size,
11882 (unsigned long long) vl->last_outbound_window_size_received,
11885 }
11886 if ((wnd == vl->incoming_fc_window_size
11890 {
11892 "Slowing FC transmission to %s to keepalive rate: peer is current at window %llu\n",
11893 GNUNET_i2s (&vl->target),
11894 (unsigned long long) wnd);
11895 /* NOTE: this used to also require @e fc_retransmit_task to be non-NULL
11896 and did nothing at all otherwise -- so a link whose chain had ended
11897 (see #consider_sending_fc()) could never pick the keepalive back up,
11898 even though the peer was demonstrably still talking to us. */
11899 if (NULL != vl->fc_retransmit_task)
11901 vl->fc_retransmit_count = 0;
11902 /* Drop to the keepalive rate rather than stopping outright. There is
11903 nothing left to retransmit -- but if we go completely quiet, and the
11904 peer does the same for the same reason, then neither end sees any
11905 traffic and #check_link_down() tears down a perfectly healthy link
11906 after #NEIGHBOUR_LIVENESS_TIMEOUT. One tiny FC message every
11907 #FC_KEEPALIVE_INTERVAL is what keeps @e last_inbound moving on the
11908 other side (and, via their reply, on ours). */
11909 vl->fc_retransmit_task =
11912 vl);
11913 }
11915 /* FC window likely increased, check transmission possibilities! */
11917 finish_cmc_handling (cmc);
11918}
11919
11920
11928static void
11930{
11932 { GNUNET_MQ_hd_var_size (fragment_box,
11935 cmc),
11936 GNUNET_MQ_hd_var_size (reliability_box,
11939 cmc),
11940 GNUNET_MQ_hd_var_size (reliability_ack,
11943 cmc),
11944 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
11947 cmc),
11948 GNUNET_MQ_hd_var_size (dv_learn,
11951 cmc),
11952 GNUNET_MQ_hd_var_size (dv_box,
11954 struct TransportDVBoxMessage,
11955 cmc),
11956 GNUNET_MQ_hd_var_size (flow_control,
11959 cmc),
11961 validation_challenge,
11964 cmc),
11966 validation_response,
11969 cmc),
11971 int ret;
11972 const struct GNUNET_MessageHeader *msg = cmc->mh;
11973
11975 "Handling message of type %u with %u bytes\n",
11976 (unsigned int) ntohs (msg->type),
11977 (unsigned int) ntohs (msg->size));
11978 /* @a handlers only covers the encapsulations *we* add; anything else is a
11979 payload for CORE and leaves through #handle_raw_message() below. So
11980 #GNUNET_NO is the common case here -- one per delivered CORE message --
11981 and not something to log about, which is why this is the "try" variant. */
11983 if (GNUNET_SYSERR == ret)
11984 {
11985 /* @a msg is the message a *remote peer* sent us: #handle_incoming_msg()
11986 points @e mh into the payload of the
11987 #GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG the communicator
11988 delivered, and every other caller unwraps it from remote traffic as
11989 well. So failing a check here is that peer's protocol violation, and
11990 it says nothing at all about the communicator that carried it.
11991
11992 Dropping the client therefore punishes the wrong party, and it
11993 punishes it hard: #GNUNET_SERVICE_client_drop() disconnects the
11994 communicator *process*, which takes down every queue it owns and thus
11995 every neighbour reachable through it. One malformed DV box on a
11996 shared UDP communicator disconnects every peer we have on it, CORE
11997 tears the sessions down, and the key exchanges that would rebuild
11998 them have to wait for the communicator to come back and revalidate.
11999 Since the offending bytes arrive from the network, any peer can do
12000 this to us at will, repeatedly.
12001
12002 Drop the message and keep the communicator: resume it exactly as the
12003 success path does, so it still gets its flow-control ACK and its
12004 GNUNET_SERVICE_client_continue(). */
12005 GNUNET_break_op (0);
12007 "# malformed messages discarded",
12008 1,
12009 GNUNET_NO);
12011 return;
12012 }
12013 if (GNUNET_NO == ret)
12014 {
12015 /* unencapsulated 'raw' message */
12016 handle_raw_message (cmc, msg);
12017 }
12018}
12019
12020
12027static int
12029 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12030{
12031 struct TransportClient *tc = cls;
12032
12033 if (CT_COMMUNICATOR != tc->type)
12034 {
12035 GNUNET_break (0);
12036 return GNUNET_SYSERR;
12037 }
12039 return GNUNET_OK;
12040}
12041
12042
12048static void
12050{
12051 if (pm->msg_uuid_set)
12052 return;
12053 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
12055}
12056
12057
12066static struct PendingAcknowledgement *
12068 struct DistanceVectorHop *dvh,
12069 struct PendingMessage *pm)
12070{
12071 struct PendingAcknowledgement *pa;
12072
12073 pa = GNUNET_new (struct PendingAcknowledgement);
12074 pa->queue = queue;
12075 pa->dvh = dvh;
12076 pa->pm = pm;
12077 do
12078 {
12080 sizeof(pa->ack_uuid));
12081 }
12084 &pa->ack_uuid.value,
12085 pa,
12087 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
12089 if (NULL != dvh)
12092 pa->message_size = pm->bytes_msg;
12094 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
12096 pm->logging_uuid);
12097 return pa;
12098}
12099
12100
12112static struct PendingMessage *
12114 struct DistanceVectorHop *dvh,
12115 struct PendingMessage *pm)
12116{
12117 struct PendingAcknowledgement *pa;
12118 struct PendingMessage *ff;
12119 uint16_t mtu;
12120 uint16_t msize;
12121
12122 mtu = (UINT16_MAX == queue->mtu)
12123 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
12124 : queue->mtu;
12126 "Fragmenting message <%" PRIu64
12127 "> with size %u to %s for MTU %u\n",
12128 pm->logging_uuid,
12129 pm->bytes_msg,
12130 GNUNET_i2s (&pm->vl->target),
12131 (unsigned int) mtu);
12134 "Fragmenting message %" PRIu64 " <%" PRIu64
12135 "> with size %u to %s for MTU %u\n",
12136 pm->msg_uuid.uuid,
12137 pm->logging_uuid,
12138 pm->bytes_msg,
12139 GNUNET_i2s (&pm->vl->target),
12140 (unsigned int) mtu);
12141
12142 /* This invariant is established in #handle_add_queue_message() */
12143 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
12144
12145 /* select fragment for transmission, descending the tree if it has
12146 been expanded until we are at a leaf or at a fragment that is small
12147 enough
12148 */
12149 ff = pm;
12150 msize = ff->bytes_msg;
12151
12152 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
12153 (ff->frag_off == msize) && (NULL != ff->head_frag))
12154 {
12155 ff = ff->head_frag; /* descent into fragmented fragments */
12156 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
12157 }
12158
12159 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
12160 {
12161 /* Did not yet calculate all fragments, calculate next fragment */
12162 struct PendingMessage *frag;
12163 struct TransportFragmentBoxMessage tfb;
12164 const char *orig;
12165 char *msg;
12166 uint16_t fragmax;
12167 uint16_t fragsize;
12168 uint16_t msize_ff;
12169 uint16_t xoff = 0;
12170 pm->frag_count++;
12171
12172 orig = (const char *) &ff[1];
12173 msize_ff = ff->bytes_msg;
12174 if (pm != ff)
12175 {
12176 const struct TransportFragmentBoxMessage *tfbo;
12177
12178 tfbo = (const struct TransportFragmentBoxMessage *) orig;
12179 orig += sizeof(struct TransportFragmentBoxMessage);
12180 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
12181 xoff = ntohs (tfbo->frag_off);
12182 }
12183 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
12184 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
12185 frag =
12186 GNUNET_malloc (sizeof(struct PendingMessage)
12187 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
12189 "3 created pm %p from pm %p storing vl %p from pm %p\n",
12190 frag,
12191 ff,
12192 pm->vl,
12193 pm);
12195 frag->vl = pm->vl;
12196 frag->frag_parent = ff;
12197 frag->timeout = pm->timeout;
12198 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
12199 frag->pmt = PMT_FRAGMENT_BOX;
12200 msg = (char *) &frag[1];
12202 tfb.header.size =
12203 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
12204 pa = prepare_pending_acknowledgement (queue, dvh, frag);
12205 tfb.ack_uuid = pa->ack_uuid;
12206 tfb.msg_uuid = pm->msg_uuid;
12207 tfb.frag_off = htons (ff->frag_off + xoff);
12208 tfb.msg_size = htons (pm->bytes_msg);
12209 memcpy (msg, &tfb, sizeof(tfb));
12210 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
12212 ff->tail_frag, frag);
12213 ff->frag_off += fragsize;
12214 ff = frag;
12215 }
12216
12217 /* Move head to the tail and return it */
12221 ff);
12225 ff);
12226
12227 return ff;
12228}
12229
12230
12243static struct PendingMessage *
12245 struct DistanceVectorHop *dvh,
12246 struct PendingMessage *pm)
12247{
12249 struct PendingAcknowledgement *pa;
12250 struct PendingMessage *bpm;
12251 char *msg;
12252
12253 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
12254 return pm; /* already fragmented or reliability boxed, or control message:
12255 do nothing */
12256 if (NULL != pm->bpm)
12257 return pm->bpm; /* already computed earlier: do nothing */
12258 // TODO I guess we do not need this assertion. We might have a DLL with
12259 // fragments, because the MTU changed, and we do not need to fragment anymore.
12260 // But we should keep the fragments until message was completed, because
12261 // the MTU might change again.
12262 // GNUNET_assert (NULL == pm->head_frag);
12263 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
12264 {
12265 /* failed hard */
12266 GNUNET_break (0);
12268 return NULL;
12269 }
12270
12271 pa = prepare_pending_acknowledgement (queue, dvh, pm);
12272
12273 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
12274 + pm->bytes_msg);
12276 "4 created pm %p storing vl %p from pm %p\n",
12277 bpm,
12278 pm->vl,
12279 pm);
12281 bpm->vl = pm->vl;
12282 bpm->frag_parent = pm;
12283 // Why was this needed?
12284 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
12285 bpm->timeout = pm->timeout;
12287 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
12290 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
12291 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
12292
12293 rbox.ack_uuid = pa->ack_uuid;
12294 msg = (char *) &bpm[1];
12295 memcpy (msg, &rbox, sizeof(rbox));
12296 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
12297 pm->bpm = bpm;
12299 "Preparing reliability box for message <%" PRIu64
12300 "> of size %d (%d) to %s on queue %s\n",
12301 pm->logging_uuid,
12302 pm->bytes_msg,
12303 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
12304 GNUNET_i2s (&pm->vl->target),
12305 queue->address);
12306 return bpm;
12307}
12308
12309
12310static void
12313{
12314 struct VirtualLink *vl = pm->vl;
12315 struct PendingMessage *pos;
12316
12317 /* Only a message without a parent is on vl->pending_msg_head; anything
12318 else is not ours to reorder and MDLL_remove() would abort on it. */
12319 if ((NULL == vl) ||
12320 (NULL != pm->frag_parent) ||
12321 ((NULL == pm->prev_vl) && (vl->pending_msg_head != pm)))
12322 {
12323 GNUNET_break (0);
12324 return;
12325 }
12326 /* re-insert sort in neighbour list */
12330 pm);
12331 pos = vl->pending_msg_tail;
12332 while ((NULL != pos) &&
12334 pos = pos->prev_vl;
12338 pos,
12339 pm);
12340}
12341
12342
12343static unsigned int
12345{
12346 struct PendingMessage *pos;
12347 /* MUST be initialised: for a leaf the loop below never runs */
12349
12350 pos = pm->head_frag;
12351 while (NULL != pos)
12352 {
12354 GNUNET_NO == check_next_attempt_tree (pos, root))
12356 else
12357 {
12359 break;
12360 }
12361 pos = pos->next_frag;
12362 }
12363
12364 return frags_in_flight;
12365}
12366
12367
12368static void
12370{
12371 struct PendingMessage *pos;
12372
12373 pos = pm->head_frag;
12374 while (NULL != pos)
12375 {
12378 pos = pos->next_frag;
12379 }
12380}
12381
12382
12391static void
12394{
12395 if (NULL == pm->frag_parent)
12396 {
12399 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
12400 pm->logging_uuid,
12403 }
12404 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
12405 {
12406 struct PendingMessage *root = pm->frag_parent;
12407
12408 while (NULL != root->frag_parent)
12409 root = root->frag_parent;
12411 "Next attempt for root message <%" PRIu64 "> set to %s\n",
12412 root->logging_uuid,
12414 root->next_attempt = next_attempt;
12416 }
12417 else
12418 {
12419 struct PendingMessage *root = pm->frag_parent;
12420
12421 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
12422 root = root->frag_parent;
12423
12425 "frag_count next attempt %u\n",
12426 root->frag_count);
12427
12428 if (GNUNET_NO == root->frags_in_flight)
12429 {
12430 root->next_attempt = next_attempt;
12432 root->frags_in_flight_round++;
12434 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
12435 ">)set to %" PRIu64 "\n",
12436 pm->logging_uuid,
12437 root->logging_uuid,
12439 }
12440
12441 pm->next_attempt = root->next_attempt;
12444
12445 if (root->bytes_msg == root->frag_off)
12446 root->frags_in_flight = check_next_attempt_tree (root, root);
12447 else
12449
12450 if (GNUNET_NO == root->frags_in_flight)
12451 {
12452 /* `root' deliberately stops at a DV box, which is itself a child of
12453 the message on vl->pending_msg_head. Walk the rest of the way for
12454 the reorder: only the parentless message is on that list. */
12455 struct PendingMessage *vl_root = root;
12456
12457 while (NULL != vl_root->frag_parent)
12458 vl_root = vl_root->frag_parent;
12459 vl_root->next_attempt = root->next_attempt;
12461 "We have no fragments in flight for message %" PRIu64
12462 ", reorder root %" PRIu64 "! Next attempt is %" PRIu64 "\n",
12463 root->logging_uuid,
12464 vl_root->logging_uuid,
12465 vl_root->next_attempt.abs_value_us);
12466 reorder_root_pm (vl_root, vl_root->next_attempt);
12467 }
12468 else
12469 {
12470 double factor = ((double) root->frag_count - 1)
12471 / (double) root->frag_count;
12472 struct GNUNET_TIME_Relative s1;
12473 struct GNUNET_TIME_Relative s2;
12474 struct GNUNET_TIME_Relative plus_mean =
12477 next_attempt);
12478
12480 "frag_count %u after factor\n",
12481 root->frag_count);
12483 factor);
12484 s2 = GNUNET_TIME_relative_divide (plus,
12485 root->frag_count);
12486 plus_mean = GNUNET_TIME_relative_add (s1, s2);
12489 "We have fragments in flight for message %" PRIu64
12490 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
12491 root->logging_uuid,
12493 }
12494 }
12495}
12496
12497
12502{
12507
12512
12517
12522
12526 int frag;
12527
12531 int relb;
12532
12537
12541 unsigned int frags_in_flight;
12542
12547};
12548
12549
12561static void
12563 struct Queue *queue,
12564 struct VirtualLink *vl,
12565 struct DistanceVectorHop *dvh,
12566 size_t overhead)
12567{
12568 struct GNUNET_TIME_Absolute now;
12569
12570 now = GNUNET_TIME_absolute_get ();
12571 sc->to_early = GNUNET_NO;
12572 sc->frags_in_flight = GNUNET_NO;
12573 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
12574 pos = pos->next_vl)
12575 {
12576 size_t real_overhead = overhead;
12577 int frag;
12578 int relb;
12579
12580 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
12581 {
12583 "DV messages must not be DV-routed to next hop!\n");
12584 continue; /* DV messages must not be DV-routed to next hop! */
12585 }
12586 if (pos->next_attempt.abs_value_us > now.abs_value_us)
12587 {
12588 if (GNUNET_YES == pos->frags_in_flight)
12589 {
12590 sc->frags_in_flight = GNUNET_YES;
12592 "Fragments in flight for message %" PRIu64 "\n",
12593 pos->logging_uuid);
12594 }
12595 else
12596 {
12598 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
12599 PRIu64 "\n",
12600 pos->logging_uuid);
12601 sc->to_early = GNUNET_YES;
12602 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
12603 pos->next_attempt);
12604 continue;
12605 }
12606 // break; /* too early for all messages, they are sorted by next_attempt */
12607 }
12608 if (NULL != pos->qe)
12609 {
12611 "not eligible\n");
12612 continue; /* not eligible */
12613 }
12614 sc->consideration_counter++;
12615 /* determine if we have to fragment, if so add fragmentation
12616 overhead! */
12618 "check %" PRIu64 " for sc->best\n",
12619 pos->logging_uuid);
12620 frag = GNUNET_NO;
12621 if (((0 != queue->mtu) &&
12622 (pos->bytes_msg + real_overhead > queue->mtu)) ||
12623 (pos->bytes_msg > UINT16_MAX - sizeof(struct
12625 ||
12626 (NULL != pos->head_frag /* fragments already exist, should
12627 respect that even if MTU is UINT16_MAX for
12628 this queue */))
12629 {
12631 "fragment msg with size %u, realoverhead is %lu\n",
12632 pos->bytes_msg,
12633 real_overhead);
12634 frag = GNUNET_YES;
12635 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
12636 {
12637 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
12638 header without the ACK UUID when using a *reliable* channel! */
12639 }
12640 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
12641 }
12642 /* determine if we have to reliability-box, if so add reliability box
12643 overhead */
12644 relb = GNUNET_NO;
12645 if ((GNUNET_NO == frag) &&
12646 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
12647 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
12648 {
12649 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
12650
12651 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
12652 {
12653 frag = GNUNET_YES;
12654 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
12655 }
12656 else
12657 {
12658 relb = GNUNET_YES;
12659 }
12661 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
12662 pos->bytes_msg,
12663 real_overhead,
12664 queue->mtu,
12665 frag,
12666 relb);
12667 }
12668
12669 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
12670 message would beat it! */
12671 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
12672 {
12673 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
12674 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
12675 experimentally validated. There may be some huge potential for
12676 improvement here. Also, we right now only compare how well the
12677 given message fits _this_ queue, and do not consider how well other
12678 queues might suit the message. Taking other queues into consideration
12679 may further improve the result, but could also be expensive
12680 in terms of CPU time. */
12681 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
12682 long long pm_score = frag * 40 + relb * 20 + real_overhead;
12683 long long time_delta =
12684 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
12685 / 1000LL;
12686
12687 /* "time_delta" considers which message has been 'ready' for transmission
12688 for longer, if a message has a preference for low latency, increase
12689 the weight of the time_delta by 10x if it is favorable for that message */
12690 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
12691 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
12692 time_delta *= 10; /* increase weight (always, both are low latency) */
12693 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
12694 (time_delta > 0))
12695 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
12696 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
12697 (time_delta < 0))
12698 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
12699 if (0 != queue->mtu)
12700 {
12701 /* Grant bonus if we are below MTU, larger bonus the closer we will
12702 be to the MTU */
12703 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
12704 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
12705 if (queue->mtu > real_overhead + pos->bytes_msg)
12706 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
12707 }
12708 if (sc_score + time_delta > pm_score)
12709 {
12711 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
12712 "\n",
12713 pos->logging_uuid,
12714 sc->best->logging_uuid);
12715 continue; /* sc_score larger, keep sc->best */
12716 }
12717 }
12718 sc->best = pos;
12719 sc->dvh = dvh;
12720 sc->frag = frag;
12721 sc->relb = relb;
12722 sc->real_overhead = real_overhead;
12723 }
12724}
12725
12726
12737static void
12739 struct Neighbour *next_hop,
12740 const struct GNUNET_MessageHeader *hdr,
12742{
12743 struct PendingMessageScoreContext *sc = cls;
12744 struct PendingMessage *pm = sc->best;
12745 struct PendingMessage *bpm;
12746 uint16_t bsize = ntohs (hdr->size);
12747
12748 GNUNET_assert (NULL == pm->bpm);
12749 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
12751 "5 created pm %p storing vl %p from pm %p\n",
12752 bpm,
12753 pm->vl,
12754 pm);
12756 bpm->pmt = PMT_DV_BOX;
12757 bpm->vl = pm->vl;
12758 bpm->timeout = pm->timeout;
12759 bpm->bytes_msg = bsize;
12760 bpm->frag_parent = pm;
12763 "Creating DV Box %" PRIu64 " for original message %" PRIu64
12764 " (next hop is %s)\n",
12766 pm->logging_uuid,
12767 GNUNET_i2s (&next_hop->pid));
12768 memcpy (&bpm[1], hdr, bsize);
12769 pm->bpm = bpm;
12770}
12771
12772
12788static void
12790{
12791 struct Queue *queue = cls;
12792 struct Neighbour *n = queue->neighbour;
12794 struct PendingMessage *pm;
12795
12796 queue->transmit_task = NULL;
12797 if ((NULL == n->vl) && (NULL == n->dv_head))
12798 {
12800 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
12801 GNUNET_i2s (&n->pid),
12802 queue->address);
12803 queue->idle = GNUNET_YES;
12804 return;
12805 }
12806 memset (&sc, 0, sizeof(sc));
12807 /* @e n need not have a link of its own: it may serve only as the first
12808 hop of DV paths, and the traffic queued for those still has to go out. */
12809 if (NULL != n->vl)
12810 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
12811 if (NULL == sc.best)
12812 {
12813 /* Also look at DVH that have the n as first hop! */
12814 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
12815 dvh = dvh->next_neighbour)
12816 {
12817 if (NULL == dvh->dv->vl)
12818 continue; /* route not (yet) visible to CORE, no messages for it */
12820 queue,
12821 dvh->dv->vl,
12822 dvh,
12823 sizeof(struct GNUNET_PeerIdentity)
12824 * (1 + dvh->distance)
12825 + sizeof(struct TransportDVBoxMessage)
12826 + sizeof(struct TransportDVBoxPayloadP));
12827 }
12828 }
12829 if (NULL == sc.best)
12830 {
12831 /* no message pending, nothing to do here! */
12833 "No pending messages, queue `%s' to %s now idle\n",
12834 queue->address,
12835 GNUNET_i2s (&n->pid));
12836 if (GNUNET_YES == sc.to_early)
12837 schedule_transmit_on_queue (sc.to_early_retry_delay,
12838 queue,
12840 queue->idle = GNUNET_YES;
12841 return;
12842 }
12843 /* There is a message pending, we are certainly not idle */
12844 queue->idle = GNUNET_NO;
12845
12846 /* Given selection in `sc`, do transmission */
12847 pm = sc.best;
12849 "Selected message <%" PRIu64 ">\n",
12850 pm->logging_uuid);
12851 if (NULL != sc.dvh)
12852 {
12854 "Is this %u a DV box?\n",
12855 pm->pmt);
12856 GNUNET_assert (PMT_DV_BOX != pm->pmt);
12857 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
12858 {
12860 "Discard old box, because we have a new DV path.\n");
12861 free_pending_message (sc.best->bpm);
12862 sc.best->bpm = NULL;
12863 }
12864
12865 if (NULL == sc.best->bpm)
12866 {
12868 "encapsulate_for_dv 2\n");
12869 encapsulate_for_dv (sc.dvh->dv,
12870 1,
12871 &sc.dvh,
12872 (const struct GNUNET_MessageHeader *) &sc.best[1],
12874 &sc,
12875 RMO_NONE,
12876 GNUNET_NO);
12877 GNUNET_assert (NULL != sc.best->bpm);
12879 "%lu %lu %lu %lu %u\n",
12880 sizeof(struct GNUNET_PeerIdentity),
12881 sizeof(struct TransportDVBoxMessage),
12882 sizeof(struct TransportDVBoxPayloadP),
12883 sizeof(struct TransportFragmentBoxMessage),
12884 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
12885 sc.best->bpm->used_dvh = sc.dvh;
12886 }
12887 pm = sc.best->bpm;
12888 }
12889 if (GNUNET_YES == sc.frag)
12890 {
12891 pm = fragment_message (queue, sc.dvh, pm);
12892 if (NULL == pm)
12893 {
12895 "Fragmentation failed queue %s to %s for <%" PRIu64
12896 ">, trying again\n",
12897 queue->address,
12898 GNUNET_i2s (&n->pid),
12899 sc.best->logging_uuid);
12901 queue,
12903 return;
12904 }
12905 }
12906 else if (GNUNET_YES == sc.relb)
12907 {
12908 pm = reliability_box_message (queue, sc.dvh, pm);
12909 if (NULL == pm)
12910 {
12911 /* Reliability boxing failed, try next message... */
12912 GNUNET_log (
12914 "Reliability boxing failed queue %s to %s for <%" PRIu64
12915 ">, trying again\n",
12916 queue->address,
12917 GNUNET_i2s (&n->pid),
12918 sc.best->logging_uuid);
12920 queue,
12922 return;
12923 }
12924 }
12925
12926 /* Pass 'pm' for transission to the communicator */
12927 GNUNET_log (
12929 "Passing message <%" PRIu64
12930 "> to queue %s for peer %s (considered %u others)\n",
12931 pm->logging_uuid,
12932 queue->address,
12933 GNUNET_i2s (&n->pid),
12934 sc.consideration_counter);
12935
12936 /* Flow control: increment amount of traffic sent; if we are routing
12937 via DV (and thus the ultimate target of the pending message is for
12938 a different virtual link than the one of the queue), then we need
12939 to use up not only the window of the direct link but also the
12940 flow control window for the DV link! */
12942
12943 if (pm->vl != queue->neighbour->vl)
12944 {
12945 /* If the virtual link of the queue differs, this better be distance
12946 vector routing! */
12947 GNUNET_assert (NULL != sc.dvh);
12948 /* If we do distance vector routing, we better not do this for a
12949 message that was itself DV-routed */
12950 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
12951 /* We use the size of the unboxed message here, to avoid counting
12952 the DV-Box header which is eaten up on the way by intermediaries.
12953 The next hop need not have a link of its own, in which case there is
12954 no window of it to charge. */
12955 if (NULL != queue->neighbour->vl)
12956 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
12957 }
12958 else
12959 {
12960 GNUNET_assert (NULL == sc.dvh);
12961 }
12962
12963 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
12964
12965 /* The message is with the communicator now, so return the CORE send
12966 window credit for it -- see #credit_client().
12967
12968 It used to be returned here only for an unboxed message or a reliable
12969 communicator, and otherwise not until the *peer* acknowledged the
12970 message below. That makes a window into a delivery confirmation: over
12971 an unreliable communicator every reliability-boxed or fragmented
12972 message holds one of the client's #SEND_WINDOW_SIZE slots for as long
12973 as its ACK takes, and a lost ACK holds it for the whole retransmission
12974 chain. Four of those and CORE cannot send to that peer at all -- not
12975 payload, but also not its HEARTBEATs and not one message of its key
12976 exchange. So the session times out for want of a heartbeat that is
12977 sitting in a queue, and the handshake that would rebuild it cannot go
12978 out either; CORE only recovers when a reconnect resets the window
12979 wholesale. Acknowledgements still drive retransmission below, they
12980 just no longer gate the client. */
12981 credit_client (sc.best);
12982
12983 /* Check if this transmission somehow conclusively finished handing 'pm'
12984 even without any explicit ACKs */
12985 if ((PMT_CORE == pm->pmt) ||
12986 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
12987 {
12989 }
12990 else
12991 {
12992 struct GNUNET_TIME_Relative wait_duration;
12993 unsigned int wait_multiplier;
12994
12995 if (PMT_FRAGMENT_BOX == pm->pmt)
12996 {
12997 struct PendingMessage *root;
12998
12999 root = pm->frag_parent;
13000 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
13001 root = root->frag_parent;
13002
13003 if ((0 == root->frag_off) || (0 == root->frag_count))
13004 {
13005 wait_multiplier = 4;
13006 }
13007 else
13008 {
13009 double wm = ceil ((double) root->bytes_msg
13010 / ((double) root->frag_off
13011 / (double) root->frag_count)) * 4.0;
13012
13013 if ((! (wm >= 1.0)) || (wm > 1024.0))
13014 wm = 4.0; /* NaN, infinity or absurd: fall back to the default */
13015 wait_multiplier = (unsigned int) wm;
13016 }
13017 }
13018 else
13019 {
13020 // No fragments, we use 4 RTT before retransmitting.
13021 wait_multiplier = 4;
13022 }
13023
13024 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
13025 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
13026
13028 "Wait multiplier %u\n",
13029 wait_multiplier);
13030
13031 /* Message not finished, waiting for acknowledgement.
13032 Update time by which we might retransmit 's' based on queue
13033 characteristics (i.e. RTT); it takes one RTT for the message to
13034 arrive and the ACK to come back in the best case; but the other
13035 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
13036 retransmitting.
13037
13038 OPTIMIZE: Note that in the future this heuristic should likely
13039 be improved further (measure RTT stability, consider message
13040 urgency and size when delaying ACKs, etc.) */
13041
13042 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
13043 queue->pd.aged_rtt.rel_value_us)
13044 wait_duration = queue->pd.aged_rtt;
13045 else
13046 {
13047 wait_duration = DEFAULT_ACK_WAIT_DURATION;
13048 wait_multiplier = 4;
13049 }
13050 {
13053 wait_duration, wait_multiplier));
13055 wait_duration, wait_multiplier);
13057 "Waiting %s for ACK until %s\n",
13062 GNUNET_TIME_relative_multiply (wait_duration,
13063 wait_multiplier))
13064 );
13065 }
13066 }
13067 /* finally, re-schedule queue transmission task itself */
13069 queue,
13071}
13072
13073
13080static void
13082 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
13083{
13084 struct TransportClient *tc = cls;
13085
13086 if (CT_COMMUNICATOR != tc->type)
13087 {
13088 GNUNET_break (0);
13090 return;
13091 }
13092 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
13093 queue = queue->next_client)
13094 {
13095 struct Neighbour *neighbour = queue->neighbour;
13096
13097 if ((ntohl (dqm->qid) != queue->qid) ||
13098 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
13099 continue;
13101 "Dropped queue %s to peer %s\n",
13102 queue->address,
13103 GNUNET_i2s (&neighbour->pid));
13104 free_queue (queue);
13106 return;
13107 }
13108 /* Not finding the queue is a race, not a protocol violation: we may have
13109 freed it ourselves already, or the communicator may be tearing down a
13110 queue we never fully learned about. Do NOT drop the client over it --
13111 that runs #client_disconnect_cb(), which frees *every* queue this
13112 communicator owns, so one stale QUEUE_TEARDOWN would disconnect us from
13113 every peer it serves at once. Compare #handle_send_message_ack(), which
13114 tolerates the same lookup miss. */
13116 "QUEUE_TEARDOWN for unknown queue QID %u to peer %s ignored\n",
13117 ntohl (dqm->qid),
13118 GNUNET_i2s (&dqm->receiver));
13120 "# QUEUE_TEARDOWN dropped: queue unknown",
13121 1,
13122 GNUNET_NO);
13124}
13125
13126
13127static void
13129 struct TransportClient *tc)
13130{
13131 struct PendingMessage *pm;
13132
13133 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
13134 qe->queue->queue_tail,
13135 qe);
13136 qe->queue->queue_length--;
13137 tc->details.communicator.total_queue_length--;
13139 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
13140 qe->queue->address,
13141 qe->queue->qid,
13142 GNUNET_i2s (&qe->queue->neighbour->pid),
13143 qe->queue->queue_length,
13144 tc->details.communicator.total_queue_length);
13145
13146 /* if applicable, resume transmissions that waited on ACK */
13148 tc->details.communicator.total_queue_length)
13149 {
13150 /* Communicator dropped below threshold, resume all queues
13151 incident with this client! */
13153 GST_stats,
13154 "# Transmission throttled due to communicator queue limit",
13155 -1,
13156 GNUNET_NO);
13157 for (struct Queue *queue = tc->details.communicator.queue_head;
13158 NULL != queue;
13159 queue = queue->next_client)
13160 {
13162 queue,
13164 }
13165 }
13166 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
13167 {
13168 /* queue dropped below threshold; only resume this one queue */
13170 "# Transmission throttled due to queue queue limit",
13171 -1,
13172 GNUNET_NO);
13174 qe->queue,
13176 }
13177 else if (1 == qe->queue->q_capacity)
13178 {
13179 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
13181 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
13182 PRIu64 ".\n",
13183 qe->queue->qid,
13184 qe->queue->q_capacity);
13185 /* message queue has capacity; only resume this one queue */
13186 /* queue dropped below threshold; only resume this one queue */
13188 "# Transmission throttled due to message queue capacity",
13189 -1,
13190 GNUNET_NO);
13192 qe->queue,
13194 }
13195
13196 if (NULL != (pm = qe->pm))
13197 {
13198 struct VirtualLink *vl;
13199
13200 // GNUNET_assert (qe == pm->qe);
13201 pm->qe = NULL;
13202 /* If waiting for this communicator may have blocked transmission
13203 of pm on other queues for this neighbour, force schedule
13204 transmit on queue for queues of the neighbour */
13205 if (NULL == pm->frag_parent)
13206 {
13207 vl = pm->vl;
13208 if ((NULL != vl) &&
13209 (NULL != vl->pending_msg_head) &&
13210 (vl->pending_msg_head == pm))
13212 }
13213 }
13214 GNUNET_free (qe);
13215}
13216
13217
13224static void
13226 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
13227{
13228 struct TransportClient *tc = cls;
13229 struct QueueEntry *qe;
13230 struct Queue *failed_queue = NULL;
13231
13232 if (CT_COMMUNICATOR != tc->type)
13233 {
13234 GNUNET_break (0);
13236 return;
13237 }
13238
13239 /* find our queue entry matching the ACK */
13240 qe = NULL;
13242 "Looking for queue for PID %s\n",
13243 GNUNET_i2s (&sma->receiver));
13244 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
13245 queue = queue->next_client)
13246 {
13247 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
13248 continue;
13250 "Found PID %s\n",
13251 GNUNET_i2s (&queue->neighbour->pid));
13252
13253
13254 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
13255 qep = qep->next)
13256 {
13257 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
13258 sma->qid))
13259 continue;
13261 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
13262 PRIu64 " Ack QID %u\n",
13263 qep->mid,
13264 queue->qid,
13265 GNUNET_ntohll (sma->mid),
13266 ntohl (sma->qid));
13267 qe = qep;
13268 if ((NULL != qe->pm) && (qe->pm->qe != qe))
13270 "For pending message %" PRIu64 " we had retransmissions.\n",
13271 qe->pm->logging_uuid);
13272 break;
13273 }
13274 }
13275 if (GNUNET_OK != (int) ntohl (sma->status))
13276 {
13277 /* The communicator could not hand the message to the peer. The only
13278 thing that produces this today is #handle_send_msg()'s "queue no
13279 longer exists" branch in `transport_api_communication.c', i.e. the
13280 communicator has already torn the queue down on its side and the
13281 QUEUE_TEARDOWN is merely still in flight (or was lost).
13282
13283 Ignoring the status, as we used to, makes this self-sustaining:
13284 #free_queue_entry() releases the pending message and immediately
13285 reschedules transmission, #transmit_on_queue() picks the very same
13286 queue again -- transport still has it -- and we get another failure.
13287 Every round adds an envelope to the client MQ that is already
13288 congested, which is what shows up at the other end as
13289
13290 communicator INFO Transmission failed, queue no longer exists.
13291
13292 repeating at scheduler speed, and (because the service is busy
13293 servicing that loop) as
13294
13295 communicator WARNING Dropping message: transport is too slow,
13296 queue length N exceeded
13297
13298 on every *other* communicator. Treat the failure as the queue
13299 teardown it is and stop selecting this queue. */
13301 "Communicator could not send MID %" PRIu64
13302 " on QID %u to %s; dropping that queue\n",
13303 GNUNET_ntohll (sma->mid),
13304 ntohl (sma->qid),
13305 GNUNET_i2s (&sma->receiver));
13307 "# queues dropped (communicator send failed)",
13308 1,
13309 GNUNET_NO);
13310 if (NULL != qe)
13311 failed_queue = qe->queue;
13312 else
13313 for (struct Queue *queue = tc->details.communicator.queue_head;
13314 NULL != queue;
13315 queue = queue->next_client)
13316 if ((ntohl (sma->qid) == queue->qid) &&
13317 (0 == GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver)))
13318 {
13319 failed_queue = queue;
13320 break;
13321 }
13322 if (NULL != failed_queue)
13323 {
13324 /* #free_queue() releases every `struct QueueEntry' still on it --
13325 including @a qe -- and detaches their pending messages, so they are
13326 retried on whatever other queue this neighbour has. */
13327 free_queue (failed_queue);
13329 return;
13330 }
13331 }
13332 if (NULL == qe)
13333 {
13335 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
13336 GNUNET_ntohll (sma->mid),
13337 ntohl (sma->qid));
13338 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
13339 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
13340 /* this should never happen */
13341 // GNUNET_break (0);
13342 // GNUNET_SERVICE_client_drop (tc->client);
13344 return;
13345 }
13348}
13349
13350
13356static void
13358 const struct GNUNET_TRANSPORT_BurstFinished *bf)
13359{
13360 struct TransportClient *tc = cls;
13361
13362 (void) bf;
13365}
13366
13367
13377static int
13379 const struct GNUNET_PeerIdentity *pid,
13380 void *value)
13381{
13382 struct TransportClient *tc = cls;
13383 struct Neighbour *neighbour = value;
13384
13385 GNUNET_assert (CT_MONITOR == tc->type);
13386 for (struct Queue *q = neighbour->queue_head; NULL != q;
13387 q = q->next_neighbour)
13388 {
13389 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
13390 .cs = q->cs,
13391 .num_msg_pending = q->num_msg_pending,
13392 .num_bytes_pending = q->num_bytes_pending };
13393
13394 notify_monitor (tc, pid, q->address, q->nt, &me);
13395 }
13396 return GNUNET_OK;
13397}
13398
13399
13406static void
13409{
13410 struct TransportClient *tc = cls;
13411
13412 if (CT_NONE != tc->type)
13413 {
13414 GNUNET_break (0);
13416 return;
13417 }
13418 tc->type = CT_MONITOR;
13419 tc->details.monitor.peer = start->peer;
13420 tc->details.monitor.one_shot = ntohl (start->one_shot);
13424}
13425
13426
13431{
13436
13441};
13442
13443
13452static char *
13454 unsigned int *num_queues)
13455{
13456 char *ret = GNUNET_strdup ("");
13457
13458 *num_queues = 0;
13459 if (NULL == n)
13460 return ret;
13461 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
13462 {
13463 const char *prefix = q->tc->details.communicator.address_prefix;
13464 size_t plen = strlen (prefix);
13465 const char *pos;
13466 char *tmp;
13467
13468 (*num_queues)++;
13469 if (0 == plen)
13470 continue;
13471 /* Several queues to one neighbour routinely share a communicator;
13472 name each one once. */
13473 for (pos = strstr (ret, prefix);
13474 NULL != pos;
13475 pos = strstr (pos + 1, prefix))
13476 if (((pos == ret) || (',' == pos[-1])) &&
13477 (('\0' == pos[plen]) || (',' == pos[plen])))
13478 break;
13479 if (NULL != pos)
13480 continue;
13481 GNUNET_asprintf (&tmp, "%s%s%s", ret, ('\0' == ret[0]) ? "" : ",", prefix);
13482 GNUNET_free (ret);
13483 ret = tmp;
13484 }
13485 return ret;
13486}
13487
13488
13497static enum GNUNET_GenericReturnValue
13498report_link (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
13499{
13500 struct LinkListContext *llc = cls;
13501 struct VirtualLink *vl = value;
13503 struct GNUNET_MQ_Envelope *env;
13504 unsigned int pending = 0;
13505 unsigned int num_queues = 0;
13506 unsigned int distance = 0;
13507 struct Neighbour *hop;
13508 char *ccs;
13509 size_t clen;
13510
13511 if ((GNUNET_YES != llc->include_unconfirmed) &&
13512 (GNUNET_YES != vl->confirmed))
13513 return GNUNET_OK;
13514 for (struct PendingMessage *pm = vl->pending_msg_head;
13515 NULL != pm;
13516 pm = pm->next_vl)
13517 pending++;
13518 if (NULL != vl->n)
13519 {
13520 hop = vl->n;
13521 }
13522 else
13523 {
13524 /* Report the best (shortest) of the paths we currently know, and the
13525 communicators that carry its first hop. */
13526 struct DistanceVectorHop *best = NULL;
13527
13528 distance = UINT_MAX;
13529 if (NULL != vl->dv)
13530 for (struct DistanceVectorHop *pos = vl->dv->dv_head;
13531 NULL != pos;
13532 pos = pos->next_dv)
13533 if (pos->distance < distance)
13534 {
13535 distance = pos->distance;
13536 best = pos;
13537 }
13538 if (NULL == best)
13539 distance = 0; /* no paths left; report the link as adjacent */
13540 hop = (NULL != best) ? best->next_hop : NULL;
13541 }
13542 ccs = communicator_list (hop, &num_queues);
13543 clen = strlen (ccs) + 1;
13544 env = GNUNET_MQ_msg_extra (resp,
13545 clen,
13547 memcpy (&resp[1], ccs, clen);
13548 GNUNET_free (ccs);
13549 resp->target = *pid;
13550 resp->confirmed = htonl ((uint32_t) vl->confirmed);
13551 resp->route = htonl ((uint32_t) ((NULL != vl->n)
13554 resp->distance = htonl ((uint32_t) distance);
13555 resp->num_queues = htonl ((uint32_t) num_queues);
13556 resp->core_recv_window = htonl ((int32_t) vl->core_recv_window);
13557 resp->stalled = htonl ((uint32_t) vl->cmc_count);
13558 resp->pending = htonl (pending);
13559 resp->fc_retransmit_count = htonl ((uint32_t) vl->fc_retransmit_count);
13578 GNUNET_MQ_send (llc->tc->mq, env);
13579 return GNUNET_OK;
13580}
13581
13582
13591static void
13593 void *cls,
13595{
13596 struct TransportClient *tc = cls;
13597 struct LinkListContext llc = {
13598 .tc = tc,
13599 .include_unconfirmed = (int) ntohl (lr->include_unconfirmed)
13600 };
13601 struct GNUNET_MQ_Envelope *env;
13602 struct GNUNET_MessageHeader *end;
13603
13604 if (CT_NONE != tc->type)
13605 {
13606 GNUNET_break (0);
13608 return;
13609 }
13610 if (GNUNET_YES == GNUNET_is_zero (&lr->peer))
13611 {
13613 }
13614 else
13615 {
13616 struct VirtualLink *vl = lookup_virtual_link (&lr->peer);
13617
13618 if (NULL != vl)
13619 report_link (&llc, &lr->peer, vl);
13620 }
13623 GNUNET_MQ_send (tc->mq, env);
13625}
13626
13627
13635static struct TransportClient *
13637{
13638 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13639 {
13640 if (CT_COMMUNICATOR != tc->type)
13641 continue;
13642 if (NULL == tc->details.communicator.address_prefix)
13643 continue; /* receive-only communicator */
13644 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
13645 return tc;
13646 }
13647 GNUNET_log (
13649 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
13650 prefix);
13651 return NULL;
13652}
13653
13654
13662static void
13663suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
13664{
13665 static uint32_t idgen = 0;
13666 struct TransportClient *tc;
13667 char *prefix;
13668 struct GNUNET_TRANSPORT_CreateQueue *cqm;
13669 struct GNUNET_MQ_Envelope *env;
13670 size_t alen;
13671
13673 if (NULL == prefix)
13674 {
13675 GNUNET_break (0); /* We got an invalid address!? */
13676 return;
13677 }
13679 if (NULL == tc)
13680 {
13682 "# Suggestions ignored due to missing communicator",
13683 1,
13684 GNUNET_NO);
13686 "Cannot connect to %s at `%s', no matching communicator present\n",
13687 GNUNET_i2s (pid),
13688 address);
13690 return;
13691 }
13692 /* forward suggestion for queue creation to communicator */
13694 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
13695 (unsigned int) idgen,
13696 prefix,
13697 GNUNET_i2s (pid),
13698 address);
13700 alen = strlen (address) + 1;
13701 env =
13703 cqm->request_id = htonl (idgen++);
13704 cqm->receiver = *pid;
13705 memcpy (&cqm[1], address, alen);
13706 GNUNET_MQ_send (tc->mq, env);
13707}
13708
13709
13717static void
13719{
13721 struct GNUNET_TIME_Absolute monotonic_time;
13722
13723 if (NULL != vs->revalidation_task)
13724 {
13725 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
13726 vs->revalidation_task = NULL;
13727 }
13728 /*memcpy (&hkey,
13729 &hc,
13730 sizeof (hkey));*/
13732 "Remove key %s for address %s map size %u contains %u\n",
13733 GNUNET_h2s (&vs->hc),
13734 vs->address,
13737 &vs->hc));
13739
13741 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
13742 vs->last_challenge_use.abs_value_us)
13743 {
13744 vs->first_challenge_use = monotonic_time;
13745 }
13746 vs->last_challenge_use = monotonic_time;
13747 tvc.header.type =
13749 tvc.header.size = htons (sizeof(tvc));
13750 tvc.reserved = htonl (0);
13751 tvc.challenge = vs->challenge;
13752 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
13754 "Sending address validation challenge %s to %s\n",
13756 GNUNET_i2s (&q->neighbour->pid));
13757 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
13758}
13759
13760
13766static void
13768{
13769 struct ValidationState *vs;
13770 struct Queue *q;
13772 GST_cfg);
13773
13774 (void) cls;
13775 validation_task = NULL;
13777 /* drop validations past their expiration */
13778 while (
13779 (NULL != vs) &&
13781 {
13783 "Validation response %s cleaned up\n",
13784 GNUNET_sh2s (&vs->challenge.value));
13787 }
13788 if (NULL == vs)
13789 {
13791 "Address validation task not scheduled anymore, nothing to do\n");
13792 return; /* woopsie, no more addresses known, should only
13793 happen if we're really a lonely peer */
13794 }
13795 q = find_queue (&vs->pid, vs->address);
13796 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
13797 {
13799 "To early to start next address validation for challenge %s\n",
13800 GNUNET_sh2s (&vs->challenge.value));
13801 /* Do NOT just return: @e validation_task was set to NULL above and
13802 nothing re-arms it by itself. #update_next_challenge_time() only
13803 schedules us again when it is called with a *changed* time for some
13804 validation state, so bailing out here leaves a non-empty
13805 #validation_heap with no task attached: address (re)validation and
13806 the #suggest_to_connect() retries that go with it stop for *every*
13807 peer until some unrelated event happens to come along. A peer that
13808 just lost its only connection has no such events left. */
13811 now,
13812 vs->first_challenge_use),
13814 NULL);
13815 return;
13816 }
13817 if (NULL == q)
13818 {
13819 vs->awaiting_queue = GNUNET_YES;
13820 suggest_to_connect (&vs->pid, vs->address);
13821 }
13822 else
13824 /* Finally, reschedule next attempt */
13825 vs->challenge_backoff =
13826 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
13829 "Address validation task will run again in %s\n",
13830 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
13831 GNUNET_YES));
13834 vs->challenge_backoff));
13835}
13836
13837
13842{
13846 struct Queue *q;
13847
13851 unsigned int quality_count;
13852
13856 unsigned int num_queues;
13857
13862 unsigned int k;
13863};
13864
13865
13877static int
13879 const struct GNUNET_PeerIdentity *pid,
13880 void *value)
13881{
13882 struct QueueQualityContext *ctx = cls;
13883 struct Neighbour *n = value;
13884 int do_inc;
13885
13886 (void) pid;
13887 do_inc = GNUNET_NO;
13888 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
13889 {
13890 ctx->num_queues++;
13891 if (0 == ctx->k--)
13892 ctx->q = q;
13893 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
13894 statistics and consider those as well here? */
13895 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
13896 do_inc = GNUNET_YES;
13897 }
13898 if (GNUNET_YES == do_inc)
13899 ctx->quality_count++;
13900 return GNUNET_OK;
13901}
13902
13903
13915static void
13916start_dv_learn (void *cls);
13917
13918
13926static void
13928 struct LearnLaunchEntry *lle,
13929 struct QueueQualityContext qqc)
13930{
13931 if (0 == qqc.num_queues)
13932 {
13934 "# DV learn aborted: no queue left",
13935 1,
13936 GNUNET_NO);
13937 return;
13938 }
13939 qqc.quality_count = 0;
13941 qqc.num_queues = 0;
13942 qqc.q = NULL;
13945 &qqc);
13946 if (NULL == qqc.q)
13947 {
13949 "# DV learn aborted: no queue left",
13950 1,
13951 GNUNET_NO);
13952 return;
13953 }
13954
13955 /* Do this as close to transmission time as possible! */
13957
13958 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
13959 /* reschedule this job, randomizing the time it runs (but no
13960 actual backoff!) */
13961 if (NULL != dvlearn_task)
13966 NULL);
13967}
13968
13969
13981static void
13983{
13984 struct LearnLaunchEntry *lle;
13985 struct QueueQualityContext qqc;
13986 struct TransportDVLearnMessage dvl;
13987 const struct GNUNET_PeerIdentity *my_identity;
13988
13989 (void) cls;
13990 dvlearn_task = NULL;
13991 if ((GNUNET_YES == in_shutdown) || (NULL == pils))
13992 return;
13994 return; /* lost all connectivity, cannot do learning */
13996 if (NULL == my_identity)
13997 {
13998 /* PILS has not handed us an identity yet. The first queue arriving
13999 schedules us with add_now(), which routinely wins that race; retry
14000 instead of taking the service down. */
14004 NULL);
14005 return;
14006 }
14008 qqc.quality_count = 0;
14009 qqc.num_queues = 0;
14013 &qqc);
14015 {
14016 struct GNUNET_TIME_Relative delay;
14017 unsigned int factor;
14018
14019 /* scale our retries by how far we are above the threshold */
14023 "At connection quality %u, will launch DV learn in %s\n",
14024 qqc.quality_count,
14027 return;
14028 }
14029 /* remove old entries in #dvlearn_map if it has grown too big */
14030 while (MAX_DV_LEARN_PENDING <=
14032 {
14033 lle = lle_tail;
14036 &lle->challenge.value,
14037 lle));
14039 GNUNET_free (lle);
14040 }
14041 /* setup data structure for learning */
14042 lle = GNUNET_new (struct LearnLaunchEntry);
14044 sizeof(lle->challenge));
14046 "Starting launch DV learn with challenge %s\n",
14047 GNUNET_sh2s (&lle->challenge.value));
14052 &lle->challenge.value,
14053 lle,
14056 dvl.header.size = htons (sizeof(dvl));
14057 dvl.num_hops = htons (0);
14058 dvl.bidirectional = htons (0);
14060 dvl.monotonic_time =
14062 // We will set the below again later
14063 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
14064 dvl.challenge = lle->challenge;
14065 dvl.initiator = *my_identity;
14066 {
14067 struct DvInitPS dvip = {
14068 .purpose.purpose = htonl (
14070 .purpose.size = htonl (sizeof(dvip)),
14071 .monotonic_time = dvl.monotonic_time,
14072 .challenge = lle->challenge
14073 };
14074
14075 if (GNUNET_OK != sign_by_my_identity (&dvip.purpose, &dvl.init_sig))
14076 return;
14077 }
14078 transmit_dv_init (dvl, lle, qqc);
14079}
14080
14081
14091static char *
14093{
14094 const char *dash;
14095 const char *colon;
14096
14097 if (NULL == address)
14098 return NULL;
14099 dash = strchr (address, '-');
14100 if (NULL == dash)
14101 return NULL;
14102 colon = strchr (dash, ':');
14103 if (NULL == colon)
14104 return NULL;
14105 return GNUNET_strndup (dash + 1,
14106 colon - (dash + 1));
14107}
14108
14109
14119static int
14121 const struct GNUNET_PeerIdentity *pid,
14122 void *value)
14123{
14124 struct Queue *q = cls;
14125 struct ValidationState *vs = value;
14126 char *address_without_port_vs;
14127 char *address_without_port_q;
14128 char *prefix_vs;
14129 char *prefix_q;
14130 int success = GNUNET_YES;
14131
14132 // TODO Check if this is really necessary.
14133 address_without_port_vs = get_address_without_port (vs->address);
14134 address_without_port_q = get_address_without_port (q->address);
14135 prefix_vs = GNUNET_HELLO_address_to_prefix (vs->address);
14136 prefix_q = GNUNET_HELLO_address_to_prefix (q->address);
14137
14139 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
14140 GNUNET_i2s (pid),
14141 (NULL == address_without_port_vs) ? "<unparsable>"
14142 : address_without_port_vs,
14143 (NULL == address_without_port_q) ? "<unparsable>"
14144 : address_without_port_q);
14145 (void) pid;
14146 /* Only the port may differ: the address we asked to connect to is
14147 `PROTO-IP:0' for a NATed peer, while the queue that then materializes
14148 sits at `PROTO-IP:port'. The communicator must match all the same --
14149 a challenge for a `tcp-' address is not answered by a `udp-' queue. */
14150 if ((GNUNET_YES == vs->awaiting_queue) &&
14151 (NULL != address_without_port_vs) &&
14152 (NULL != address_without_port_q) &&
14153 (NULL != prefix_vs) &&
14154 (NULL != prefix_q) &&
14155 (0 == strcmp (prefix_vs, prefix_q)) &&
14156 (0 == strcmp (address_without_port_vs, address_without_port_q)))
14157 {
14158
14159 vs->awaiting_queue = GNUNET_NO;
14161 success = GNUNET_NO;
14162 }
14163
14164 GNUNET_free (address_without_port_vs);
14165 GNUNET_free (address_without_port_q);
14166 GNUNET_free (prefix_vs);
14167 GNUNET_free (prefix_q);
14168 return success;
14169}
14170
14171
14180static void
14182 const struct GNUNET_PEERSTORE_Record *record,
14183 const char *emsg)
14184{
14185 struct Neighbour *n = cls;
14186 struct GNUNET_TIME_AbsoluteNBO *mtbe;
14187
14188 (void) emsg;
14189 if (NULL == record)
14190 {
14191 /* we're done with #neighbour_dv_monotime_cb() invocations,
14192 continue normal processing */
14193 n->get = NULL;
14195 return;
14196 }
14197 if (0 == record->value_size)
14198 {
14200 GNUNET_break (0);
14201 return;
14202 }
14203 mtbe = record->value;
14208}
14209
14210
14211static void
14213 const struct GNUNET_PeerIdentity *pid,
14214 const char *uri)
14215{
14216 struct Queue *queue = cls;
14217 struct sockaddr_in v4;
14218 const char *slash;
14219 char *address_uri;
14220 char *prefix;
14221 char *uri_without_port;
14222 char *address_uri_without_port;
14223
14224 slash = strrchr (uri, '/');
14225 if ((NULL == slash) || (slash - uri < 2))
14226 {
14227 GNUNET_break_op (0); /* @a uri comes from a remote HELLO */
14228 return;
14229 }
14230 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
14231 slash++;
14232 GNUNET_asprintf (&address_uri,
14233 "%s-%s",
14234 prefix,
14235 slash);
14236
14238 "1 not global natted_address %u %s %s %s\n",
14239 queue->is_global_natted,
14240 uri,
14241 queue->address,
14242 slash);
14243
14244 uri_without_port = get_address_without_port (address_uri);
14245 if ((NULL == uri_without_port) ||
14246 (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr)))
14247 {
14249 GNUNET_free (address_uri);
14250 GNUNET_free (uri_without_port);
14251 return;
14252 }
14253
14255 "2 not global natted_address %u %s %s\n",
14256 queue->is_global_natted,
14257 uri,
14258 queue->address);
14259
14260 if (GNUNET_NO == queue->is_global_natted)
14261 {
14263 GNUNET_free (address_uri);
14264 GNUNET_free (uri_without_port);
14265 return;
14266 }
14267
14269 "3 not global natted_address %u %s %s\n",
14270 queue->is_global_natted,
14271 uri,
14272 queue->address);
14273
14274 if (0 == strcmp (uri_without_port, address_uri))
14275 {
14277 GNUNET_free (address_uri);
14278 GNUNET_free (uri_without_port);
14279 return;
14280 }
14281
14283 "4 not global natted_address %u %s %s\n",
14284 queue->is_global_natted,
14285 uri,
14286 queue->address);
14287
14288 address_uri_without_port = get_address_without_port (queue->address);
14289 if ((NULL != address_uri_without_port) &&
14290 (0 == strcmp (uri_without_port, address_uri_without_port)))
14291 {
14292 queue->is_global_natted = GNUNET_NO;
14293 }
14294
14296 "not global natted_address %u %s %s %s %s %s %u\n",
14297 queue->is_global_natted,
14298 uri,
14299 queue->address,
14300 uri_without_port,
14301 address_uri_without_port,
14302 prefix,
14303 GNUNET_NO);
14305 GNUNET_free (address_uri);
14306 GNUNET_free (address_uri_without_port);
14307 GNUNET_free (uri_without_port);
14308}
14309
14310
14323
14324
14325static enum GNUNET_GenericReturnValue
14327 const struct GNUNET_PeerIdentity *pid,
14328 void *value)
14329{
14330 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
14331 struct TransportGlobalNattedAddress *tgna = value;
14332 char *addr = (char *) &tgna[1];
14333
14334 /* NOTE: @a addr is NOT 0-terminated. */
14336 "Checking tgna %p with addr %.*s and length %u compare length %lu\n",
14337 tgna,
14338 (int) ntohl (tgna->address_length),
14339 addr,
14340 ntohl (tgna->address_length),
14341 strlen (tgna_cls->addr));
14342 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
14343 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
14344 {
14345 tgna_cls->tgna = tgna;
14346 return GNUNET_NO;
14347 }
14348 return GNUNET_YES;
14349}
14350
14351
14352static void
14354{
14356 "Error in PEERSTORE monitoring for checking global natted\n");
14357}
14358
14359
14360static void
14362{
14364 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
14365}
14366
14367
14368static void
14370 const struct GNUNET_PEERSTORE_Record *record,
14371 const char *emsg)
14372{
14373 struct Queue *queue = cls;
14374 struct Neighbour *neighbour = queue->neighbour;
14375 struct GNUNET_HELLO_Parser *parser;
14376 const struct GNUNET_MessageHeader *hello;
14378 size_t address_len_without_port;
14379
14380 if (NULL != emsg)
14381 {
14383 "Got failure from PEERSTORE: %s\n",
14384 emsg);
14386 return;
14387 }
14388 if (NULL == record)
14389 {
14390 GNUNET_break (0);
14392 return;
14393 }
14394 /* @a hello was published by a remote peer and may be malformed. */
14395 hello = hello_from_record (record);
14396 if (NULL == hello)
14397 {
14399 return;
14400 }
14401 queue->is_global_natted = GNUNET_YES;
14402 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
14403 if (NULL == parser)
14404 {
14406 "HELLO cannot be parsed!\n");
14408 return;
14409 }
14411 "before not global natted %u\n",
14412 queue->is_global_natted);
14415 queue);
14417 "after not global natted %u\n",
14418 queue->is_global_natted);
14419 GNUNET_HELLO_parser_free (parser);
14420
14421 tgna_cls.addr = get_address_without_port (queue->address);
14422 if (NULL == tgna_cls.addr)
14423 {
14424 GNUNET_break (0);
14426 return;
14427 }
14428 address_len_without_port = strlen (tgna_cls.addr);
14429 /*{
14430 char buf[address_len_without_port + 1];
14431
14432 GNUNET_memcpy (&buf, addr, address_len_without_port);
14433 buf[address_len_without_port] = '\0';
14434 GNUNET_free (addr);
14435 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
14436 }*/
14437 tgna_cls.tgna = NULL;
14439 &neighbour->pid,
14441 &tgna_cls);
14442 if (NULL != tgna_cls.tgna)
14444 " tgna_cls.tgna tgna %p %lu %u %u\n",
14445 tgna_cls.tgna,
14446 neighbour->size_of_global_addresses,
14447 ntohl (tgna_cls.tgna->address_length),
14448 neighbour->number_of_addresses);
14449 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
14450 {
14451 struct TransportGlobalNattedAddress *tgna;
14452
14453 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
14454 + address_len_without_port);
14455 tgna->address_length = htonl (address_len_without_port);
14456 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
14458 &neighbour->pid,
14459 tgna,
14461 neighbour->number_of_addresses++;
14462 /* MUST match what is subtracted on removal (and what
14463 #add_global_addresses() actually copies), or the accounting drifts. */
14464 neighbour->size_of_global_addresses += address_len_without_port;
14466 "Created tgna %p with address %s and length %lu\n",
14467 tgna,
14468 tgna_cls.addr,
14469 address_len_without_port + 1);
14470 }
14471 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
14472 {
14474 &neighbour->pid,
14475 tgna_cls.tgna);
14476 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
14478 );
14479 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
14480 ;
14481 GNUNET_assert (0 < neighbour->number_of_addresses);
14482 neighbour->number_of_addresses--;
14484 "removed tgna %p\n",
14485 tgna_cls.tgna);
14486 GNUNET_free (tgna_cls.tgna);
14487 }
14489 GNUNET_free (tgna_cls.addr);
14490}
14491
14492
14499static void
14501 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
14502{
14503 struct TransportClient *tc = cls;
14504 struct Queue *queue;
14505 struct Neighbour *neighbour;
14506 const char *addr;
14507 uint16_t addr_len;
14508
14509 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
14510 {
14511 /* MTU so small as to be useless for transmissions,
14512 required for #fragment_message()! */
14513 GNUNET_break_op (0);
14515 return;
14516 }
14517 /* This may simply be a queue update. Match on the peer as well as the
14518 QID: the communicator's key for a queue is the pair, and
14519 #handle_send_msg() on its side looks both of them up. Matching on the
14520 QID alone let an ADD_QUEUE for a *different* peer be folded into an
14521 existing queue, leaving @e neighbour pointing at the old peer -- after
14522 which every SEND_MSG we put on it carries a receiver the communicator
14523 cannot match, and comes straight back as "queue no longer exists". */
14524 for (queue = tc->details.communicator.queue_head;
14525 NULL != queue;
14526 queue = queue->next_client)
14527 {
14528 if (queue->qid != ntohl (aqm->qid))
14529 continue;
14530 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &aqm->receiver))
14531 continue;
14532 break;
14533 }
14534
14535 if (NULL != queue)
14536 {
14537 neighbour = queue->neighbour;
14538 }
14539 else
14540 {
14541 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
14542
14543 neighbour = lookup_neighbour (&aqm->receiver);
14544 if (NULL == neighbour)
14545 {
14546 neighbour = GNUNET_new (struct Neighbour);
14548 GNUNET_YES);
14549 neighbour->pid = aqm->receiver;
14550 /* Give a fresh neighbour a full window to say something. */
14551 neighbour->last_inbound = GNUNET_TIME_absolute_get ();
14554 neighbours,
14555 &neighbour->pid,
14556 neighbour,
14558 neighbour->get =
14560 "transport",
14561 &neighbour->pid,
14564 neighbour);
14565 }
14566 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
14567 addr = (const char *) &aqm[1];
14569 "New queue %s to %s available with QID %u and q_len %" PRIu64
14570 " and mtu %u\n",
14571 addr,
14572 GNUNET_i2s (&aqm->receiver),
14573 ntohl (aqm->qid),
14574 GNUNET_ntohll (aqm->q_len),
14575 ntohl (aqm->mtu));
14576 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
14577 queue->tc = tc;
14578 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
14579 next_neighbour)
14580 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
14581 validated_until);
14582 /* Inherit the validity of the sibling queues, but only while it is
14583 still in the future -- copying an already expired timestamp is
14584 pointless (and the condition used to be inverted). */
14585 if (0 != GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
14586 {
14588 "New queue with QID %u inherit validated until\n",
14589 ntohl (aqm->qid));
14590 queue->validated_until = validated_until;
14591 }
14592 queue->address = (const char *) &queue[1];
14593 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
14594 queue->qid = ntohl (aqm->qid);
14595 queue->neighbour = neighbour;
14597 queue->unlimited_length = GNUNET_YES;
14598 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
14599 memcpy (&queue[1], addr, addr_len);
14600 /* notify monitors about new queue */
14601 {
14602 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
14603
14604 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
14605 }
14607 neighbour->queue_head,
14608 neighbour->queue_tail,
14609 queue);
14611 tc->details.communicator.queue_head,
14612 tc->details.communicator.queue_tail,
14613 queue);
14614
14615 }
14616 queue->mtu = ntohl (aqm->mtu);
14617 queue->nt = ntohl (aqm->nt);
14618 queue->cs = ntohl (aqm->cs);
14619 queue->idle = GNUNET_YES;
14620
14621 if (NULL == queue->mo)
14622 {
14623 /* Only for a NEW queue: on a queue update this used to start a second
14624 monitor and leak the first one. */
14625 struct sockaddr_in v4;
14626 char *addr_without = get_address_without_port (queue->address);
14627 if ((NULL != addr_without) &&
14628 (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr)))
14629 {
14631 "start not global natted\n");
14633 GNUNET_YES,
14634 "peerstore",
14635 &neighbour->pid,
14637 &
14639 NULL,
14640 &
14642 NULL,
14644 queue);
14645 }
14646 GNUNET_free (addr_without);
14647 }
14648 /* check if valdiations are waiting for the queue */
14650 &aqm->receiver))
14653 &aqm->receiver,
14655 queue);
14656 /* Always (also) validate the address of the queue itself. A pending
14657 validation served above may well be for a *different* address string:
14658 #check_validation_request_pending() matches on the IP only, so a
14659 validation state waiting for the NAT address `PROTO-IP:0' is happily
14660 satisfied by a queue at `PROTO-IP:12345'. If we stopped here,
14661 #handle_validation_response() would later look for a queue at
14662 `PROTO-IP:0' -- which never exists -- and drop the successful
14663 validation on the floor without ever creating the virtual link. That
14664 is exactly what happens to the second of two peers behind the same
14665 NAT, as both of them advertise the very same `PROTO-IP:0'. */
14666 start_address_validation (&aqm->receiver, queue->address);
14667 /* look for traffic for this queue */
14668 // TODO Check whether this makes any sense at all.
14669 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
14670 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
14671 /* might be our first queue, try launching DV learning */
14672 if (NULL == dvlearn_task)
14675}
14676
14677
14684static void
14686 const struct
14688{
14689 struct TransportClient *tc = cls;
14690 struct Queue *target_queue = NULL;
14691
14692 if (CT_COMMUNICATOR != tc->type)
14693 {
14694 /* Without this we walk `details.communicator.queue_head' for a client
14695 whose union holds something else entirely. */
14696 GNUNET_break (0);
14698 return;
14699 }
14701 "Received queue update message for %u with q_len %llu and mtu %u\n",
14702 ntohl (msg->qid),
14703 (unsigned long long) GNUNET_ntohll (msg->q_len),
14704 ntohl (msg->mtu));
14705 for (target_queue = tc->details.communicator.queue_head;
14706 NULL != target_queue;
14707 target_queue = target_queue->next_client)
14708 {
14709 if (ntohl (msg->qid) == target_queue->qid)
14710 break;
14711 }
14712 if (NULL == target_queue)
14713 {
14715 "Queue to update no longer exists! Discarding update.\n");
14717 return;
14718 }
14719
14720 target_queue->nt = ntohl (msg->nt);
14721 target_queue->mtu = ntohl (msg->mtu);
14722 target_queue->cs = ntohl (msg->cs);
14723 target_queue->priority = ntohl (msg->priority);
14724 /* The update message indicates how many messages
14725 * the queue should be able to handle.
14726 */
14728 target_queue->unlimited_length = GNUNET_YES;
14729 else
14730 target_queue->unlimited_length = GNUNET_NO;
14731 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
14732 if (0 < target_queue->q_capacity)
14734 target_queue,
14737}
14738
14739
14747static void
14749 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
14750{
14751 struct TransportClient *tc = cls;
14752
14753 if (CT_COMMUNICATOR != tc->type)
14754 {
14755 GNUNET_break (0);
14757 return;
14758 }
14760 "# Suggestions succeeded at communicator",
14761 1,
14762 GNUNET_NO);
14764 "Request #%u for communicator to create queue succeeded\n",
14765 (unsigned int) ntohs (cqr->request_id));
14767}
14768
14769
14778static void
14780 void *cls,
14781 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
14782{
14783 struct TransportClient *tc = cls;
14784
14785 if (CT_COMMUNICATOR != tc->type)
14786 {
14787 GNUNET_break (0);
14789 return;
14790 }
14792 "Request #%u for communicator to create queue failed\n",
14793 (unsigned int) ntohl (cqr->request_id));
14795 "# Suggestions failed in queue creation at communicator",
14796 1,
14797 GNUNET_NO);
14799}
14800
14801
14809static void
14811{
14812 struct TransportClient *tc = cls;
14813 struct PeerRequest *pr;
14814
14815 if (CT_APPLICATION != tc->type)
14816 {
14817 GNUNET_break (0);
14819 return;
14820 }
14821 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
14822 &msg->peer);
14823 if (NULL == pr)
14824 {
14825 GNUNET_break (0);
14827 return;
14828 }
14829 (void) stop_peer_request (tc, &pr->pid, pr);
14831}
14832
14833
14834static void
14836 const struct GNUNET_PeerIdentity *pid,
14837 const char *uri)
14838{
14839 struct Queue *q;
14840 int pfx_len;
14841 const char *eou;
14842 char *address;
14843 (void) cls;
14844
14845 eou = strstr (uri,
14846 "://");
14847 pfx_len = eou - uri;
14848 eou += 3;
14850 "%.*s-%s",
14851 pfx_len,
14852 uri,
14853 eou);
14854
14856 "hello for client %s\n",
14857 address);
14858
14859 q = find_queue (pid, address);
14860 if (NULL == q)
14861 {
14863 }
14864 else
14867}
14868
14869
14877static void
14879 const struct GNUNET_PEERSTORE_Record *record,
14880 const char *emsg)
14881{
14882 const struct GNUNET_PeerIdentity *my_identity;
14883 struct PeerRequest *pr = cls;
14884 struct GNUNET_HELLO_Parser *parser;
14885 const struct GNUNET_MessageHeader *hello;
14886
14887 if (NULL != emsg)
14888 {
14890 "Got failure from PEERSTORE: %s\n",
14891 emsg);
14893 return;
14894 }
14895 if (NULL == record)
14896 {
14897 GNUNET_break (0);
14899 return;
14900 }
14902 if (NULL == my_identity)
14903 {
14905 "No identity given yet!\n");
14907 return;
14908 }
14909 hello = hello_from_record (record);
14910 if (NULL == hello)
14911 {
14912 /* MUST still ask for the next record: a bad one is not a reason to
14913 stall this monitor forever. */
14915 return;
14916 }
14917 if (0 == GNUNET_memcmp (&record->peer, my_identity))
14918 {
14920 return;
14921 }
14922 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
14923 if (NULL == parser)
14924 {
14926 "HELLO cannot be parsed!\n");
14928 return;
14929 }
14931 "HELLO for `%s' could be parsed, iterating addresses...!\n",
14935 NULL);
14936 GNUNET_HELLO_parser_free (parser);
14937 /* MUST ask for the next record, or this monitor stalls after one HELLO */
14939}
14940
14941
14942static void
14944{
14946 "Error in PEERSTORE monitoring\n");
14947}
14948
14949
14950static void
14952{
14954 "Done with initial PEERSTORE iteration during monitoring\n");
14955}
14956
14957
14965static void
14967{
14968 struct TransportClient *tc = cls;
14969 const struct GNUNET_PeerIdentity *my_identity;
14970 struct PeerRequest *pr;
14971
14972 if (CT_NONE == tc->type)
14973 {
14974 tc->type = CT_APPLICATION;
14975 tc->details.application.requests =
14977 }
14978 if (CT_APPLICATION != tc->type)
14979 {
14980 GNUNET_break (0);
14982 return;
14983 }
14985 if (NULL == my_identity)
14986 {
14988 "Still waiting for own identity!\n");
14990 return;
14991 }
14993 "Client suggested we talk to %s with preference %d at rate %u\n",
14994 GNUNET_i2s (&msg->peer),
14995 (int) ntohl (msg->pk),
14996 (int) ntohl (msg->bw.value__));
14997 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
14998 {
15000 "Client suggested connection to ourselves, ignoring...\n");
15002 return;
15003 }
15004 pr = GNUNET_new (struct PeerRequest);
15005 pr->tc = tc;
15006 pr->pid = msg->peer;
15007 pr->bw = msg->bw;
15008 pr->pk = ntohl (msg->pk);
15010 tc->details.application.requests,
15011 &pr->pid,
15012 pr,
15014 {
15015 GNUNET_break (0);
15016 GNUNET_free (pr);
15018 return;
15019 }
15020 pr->nc =
15022 GNUNET_YES,
15023 "peerstore",
15024 NULL,
15027 NULL,
15029 NULL,
15031 pr);
15033}
15034
15035
15044static int
15046 const struct RequestHelloValidationMessage *m)
15047{
15048 (void) cls;
15050 return GNUNET_OK;
15051}
15052
15053
15061static void
15063 const struct RequestHelloValidationMessage *m)
15064{
15065 struct TransportClient *tc = cls;
15066 struct Queue *q;
15067
15068 q = find_queue (&m->peer, (const char *) &m[1]);
15069 if (NULL == q)
15070 {
15071 suggest_to_connect (&m->peer, (const char *) &m[1]);
15072 }
15073 else
15074 start_address_validation (&m->peer, (const char *) &m[1]);
15076}
15077
15078
15087static int
15089 const struct GNUNET_PeerIdentity *pid,
15090 void *value)
15091{
15092 struct Neighbour *neighbour = value;
15093
15094 (void) cls;
15095 (void) pid;
15096 GNUNET_break (0); // should this ever happen?
15097 free_neighbour (neighbour, GNUNET_YES);
15098
15099 return GNUNET_OK;
15100}
15101
15102
15117static int
15119 const struct GNUNET_PeerIdentity *pid,
15120 void *value)
15121{
15122 struct VirtualLink *vl = value;
15123
15124 (void) cls;
15125 (void) pid;
15126 free_virtual_link (vl);
15127
15128 return GNUNET_OK;
15129}
15130
15131
15140static int
15142 const struct GNUNET_PeerIdentity *pid,
15143 void *value)
15144{
15145 struct DistanceVector *dv = value;
15146
15147 (void) cls;
15148 (void) pid;
15149 free_dv_route (dv);
15150
15151 return GNUNET_OK;
15152}
15153
15154
15163static int
15165 const struct GNUNET_PeerIdentity *pid,
15166 void *value)
15167{
15168 struct ValidationState *vs = value;
15169
15170 (void) cls;
15171 (void) pid;
15173 return GNUNET_OK;
15174}
15175
15176
15185static int
15186free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
15187{
15188 struct PendingAcknowledgement *pa = value;
15189
15190 (void) cls;
15191 (void) key;
15193 return GNUNET_OK;
15194}
15195
15196
15205static int
15207 const struct GNUNET_PeerIdentity *pid,
15208 void *value)
15209{
15210 struct AcknowledgementCummulator *ac = value;
15211
15212 (void) cls;
15213 (void) pid;
15215 GNUNET_free (ac);
15216 return GNUNET_OK;
15217}
15218
15219
15226static void
15227do_shutdown (void *cls)
15228{
15229 static int shutdown_done;
15230 struct LearnLaunchEntry *lle;
15231 struct PilsRequest *pr;
15232 (void) cls;
15233
15235 "shutdown logic\n");
15236 if (GNUNET_YES == shutdown_done)
15237 return; /* reachable both from #shutdown_task() and #client_disconnect_cb() */
15238 shutdown_done = GNUNET_YES;
15239 if (NULL != client_grace_task)
15240 {
15242 client_grace_task = NULL;
15243 }
15244 if (NULL != nh)
15245 {
15247 nh = NULL;
15248 }
15250 &free_neighbour_cb, NULL);
15251 /* Freeing a neighbour takes its virtual link with it, so whatever is
15252 left here is ownerless: a link we created from an inbound FLOW_CONTROL
15253 message that never got confirmed, kept alive only by its @e
15254 unconfirmed_timeout_task. #GNUNET_SCHEDULER_shutdown() does not run
15255 that task, so leaving the link in place left the task armed against a
15256 map we destroy further down -- it fired afterwards and
15257 #free_virtual_link() called GNUNET_CONTAINER_multipeermap_remove() on
15258 NULL. Drop them here, while every structure they touch is still
15259 alive. */
15262 NULL);
15263 if (NULL != validation_task)
15264 {
15266 validation_task = NULL;
15267 }
15268 if (NULL != dvlearn_task)
15269 {
15271 dvlearn_task = NULL;
15272 }
15273 if (NULL != burst_task)
15274 {
15276 burst_task = NULL;
15277 }
15278 if (NULL != burst_timeout_task)
15279 {
15281 burst_timeout_task = NULL;
15282 }
15285 dvlearn_map = NULL;
15288 dv_routes = NULL;
15289 if (NULL != GST_stats)
15290 {
15292 GST_stats = NULL;
15293 }
15294 if (NULL != GST_my_hello)
15295 {
15297 GST_my_hello = NULL;
15298 }
15301 NULL);
15303 ack_cummulators = NULL;
15306 NULL);
15308 pending_acks = NULL;
15311 neighbours = NULL;
15314 links = NULL;
15317 NULL);
15319 backtalkers = NULL;
15322 NULL);
15324 validation_map = NULL;
15326 validation_heap = NULL;
15328 revalidation_map = NULL;
15329 while (NULL != ir_head)
15331 GNUNET_assert (0 == ir_total);
15332 while (NULL != (lle = lle_head))
15333 {
15335 GNUNET_free (lle);
15336 }
15337 while (NULL != (pr = pils_requests_head))
15338 {
15341 pr);
15342 if (NULL != pr->op)
15343 GNUNET_PILS_cancel (pr->op);
15344 GNUNET_free (pr);
15345 }
15346 if (NULL != pils_feed_task)
15347 {
15349 pils_feed_task = NULL;
15350 }
15351 if (NULL != pils)
15352 {
15354 pils = NULL;
15355 }
15356 if (NULL != peerstore)
15357 {
15359 "Disconnecting from PEERSTORE service\n");
15361 peerstore = NULL;
15362 }
15364}
15365
15366
15367static const char*
15369{
15370 switch (type)
15371 {
15372 case CT_CORE:
15373 return "CORE";
15374 case CT_MONITOR:
15375 return "MONITOR";
15376 case CT_COMMUNICATOR:
15377 return "COMMUNICATOR";
15378 case CT_APPLICATION:
15379 return "APPLICATION";
15380 default:
15381 return "UNKNOWN";
15382 }
15383}
15384
15385
15393static void
15395{
15396 client_grace_task = NULL;
15397 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
15398 {
15400 "Client did not disconnect within the shutdown grace period, "
15401 "dropping it: %s\n",
15402 get_client_type_name (tc->type));
15403 }
15404 /* We use #GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, so the service will NOT
15405 drop clients for us. Without this we would wait forever for them to
15406 leave on their own and never reach #do_shutdown(). */
15408 /* Dropping the clients ran #client_disconnect_cb() for each of them, so
15409 #do_shutdown() has normally run by now; it is idempotent, and this
15410 covers the case where there was nothing left to drop. */
15411 do_shutdown (cls);
15412}
15413
15414
15415static void
15416shutdown_task (void *cls)
15417{
15419
15421 "Shutdown task executed\n");
15422 if (NULL != clients_head)
15423 {
15424 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
15425 {
15427 "Waiting for client to disconnect: %s\n",
15428 get_client_type_name (tc->type));
15429 }
15430 /* Give them a chance to shut down cleanly; #client_disconnect_cb() calls
15431 #do_shutdown() once the last one is gone, and #do_shutdown() cancels
15432 this task. */
15436 cls);
15437 return;
15438 }
15439 do_shutdown (cls);
15440}
15441
15442
15447
15448static void
15449update_hello_from_pid_change_cb (void *cls, int success)
15450{
15451 struct UpdateHelloFromPidCtx *pc = cls;
15452
15453 /* NOTE: @a success is GNUNET_OK even when #hello_add_iter() decided not to
15454 store anything because PEERSTORE already holds a HELLO that expires
15455 later; the API reports the desired state, not whether it wrote. So this
15456 says "we have a current HELLO on record", not "we just wrote one". */
15457 if (GNUNET_OK != success)
15459 "Failed to store our new hello with peerstore\n");
15460 else
15462 "Our hello is current in peerstore\n");
15463 GNUNET_free (pc);
15464}
15465
15466
15467void
15469 const struct GNUNET_PeerIdentity *pid,
15470 const char *uri)
15471{
15473 "%s\n", uri);
15474}
15475
15476
15486static void
15488 const struct GNUNET_HELLO_Parser *parser,
15489 const struct GNUNET_HashCode *hash)
15490{
15491 const struct GNUNET_PeerIdentity *my_identity;
15492 struct GNUNET_MQ_Envelope *env;
15493 const struct GNUNET_MessageHeader *msg;
15494 struct UpdateHelloFromPidCtx *sc;
15495 struct GNUNET_HELLO_Builder *nbuilder;
15496 struct GNUNET_PeerIdentity npid;
15497
15500
15501 if (NULL == GST_my_hello)
15504 "My current identity is `%s'\n",
15516 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
15517 &npid);
15518 if (GNUNET_NO ==
15520 {
15522 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
15524 "Proposed address list:\n");
15527 "Current address list:\n");
15529 GNUNET_HELLO_builder_free (nbuilder);
15530 return;
15531 }
15533 GST_my_hello = nbuilder;
15535 "My new identity is `%s'\n",
15541 msg,
15543 sc);
15544 GNUNET_free (env);
15545}
15546
15547
15555static void
15556run (void *cls,
15557 const struct GNUNET_CONFIGURATION_Handle *c,
15559{
15560 (void) cls;
15561 /* setup globals */
15565 GST_cfg = c;
15573 GNUNET_YES);
15578 // TODO check for all uses of GST_my_hello that it is not used uninitialized
15580 "transport",
15581 "USE_BURST_NAT");
15582 if (GNUNET_SYSERR == use_burst)
15584 "Could not configure burst nat use. Default to no.\n");
15590 "transport",
15591 0,
15592 0,
15593 NULL,
15594 0,
15595 NULL,
15596 NULL,
15597 NULL);
15598 if (NULL == peerstore)
15599 {
15600 GNUNET_break (0);
15602 return;
15603 }
15606 NULL); // FIXME we need to wait for
15607 // our first peer id before
15608 // we can start the service
15609 // completely - PILS in turn
15610 // waits for the first
15611 // addresses from the
15612 // communicators in order to
15613 // be able to generate a
15614 // peer id
15615 if (NULL == pils)
15616 {
15617 GNUNET_break (0);
15619 return;
15620 }
15621 /* Decapsulate DV box ephemeral keys ourselves. #handle_dv_box() needs
15622 the key material while it still has the box, which points into the
15623 communicator's inbound message and is gone the moment the handler
15624 returns -- so the asynchronous answer arrived to a dangling @a dvb. */
15625 if (GNUNET_OK !=
15628 _ ("Failed to load our private key, "
15629 "cannot open DV boxes addressed to us\n"));
15630}
15631
15632
15638 "transport",
15640 &run,
15643 NULL,
15644 /* communication with applications */
15645 GNUNET_MQ_hd_fixed_size (suggest,
15648 NULL),
15649 GNUNET_MQ_hd_fixed_size (suggest_cancel,
15652 NULL),
15653 GNUNET_MQ_hd_var_size (request_hello_validation,
15656 NULL),
15657 /* communication with core */
15658 GNUNET_MQ_hd_fixed_size (client_start,
15660 struct StartMessage,
15661 NULL),
15662 GNUNET_MQ_hd_var_size (client_send,
15664 struct OutboundMessage,
15665 NULL),
15666 GNUNET_MQ_hd_fixed_size (client_recv_ok,
15668 struct RecvOkMessage,
15669 NULL),
15670 /* communication with communicators */
15671 GNUNET_MQ_hd_var_size (communicator_available,
15674 NULL),
15675 GNUNET_MQ_hd_var_size (communicator_backchannel,
15678 NULL),
15679 GNUNET_MQ_hd_var_size (add_address,
15682 NULL),
15683 GNUNET_MQ_hd_fixed_size (del_address,
15686 NULL),
15687 GNUNET_MQ_hd_var_size (incoming_msg,
15690 NULL),
15691 GNUNET_MQ_hd_fixed_size (queue_create_ok,
15694 NULL),
15695 GNUNET_MQ_hd_fixed_size (queue_create_fail,
15698 NULL),
15699 GNUNET_MQ_hd_var_size (add_queue_message,
15702 NULL),
15703 GNUNET_MQ_hd_fixed_size (update_queue_message,
15706 NULL),
15707 GNUNET_MQ_hd_fixed_size (del_queue_message,
15710 NULL),
15711 GNUNET_MQ_hd_fixed_size (send_message_ack,
15714 NULL),
15715 GNUNET_MQ_hd_fixed_size (burst_finished,
15718 NULL),
15719 /* communication with monitors */
15720 GNUNET_MQ_hd_fixed_size (monitor_start,
15723 NULL),
15724 GNUNET_MQ_hd_fixed_size (link_list_request,
15727 NULL),
15729
15730
15731/* 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 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.
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?
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.
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.
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.
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 the communicator has another queue with higher prio ready for sending.
#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...
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 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 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)
We have received a struct ExpressPreferenceMessage from an application client.
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 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.
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 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.
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:1020
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:1039
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:967
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:1395
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:996
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:688
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:1126
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:1206
#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.
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_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_pa
Pointers for the DLL of all pending acknowledgements.
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_pa
Pointers for the DLL of all pending acknowledgements.
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