GNUnet 0.28.1-dev.6-3-gbc381df64
 
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
277#define MIN_ACK_WAIT_DURATION \
278 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10)
279
285#define DV_QUALITY_RTT_THRESHOLD \
286 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
287
292#define DV_PATH_VALIDITY_TIMEOUT \
293 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
294
299#define BACKCHANNEL_INACTIVITY_TIMEOUT \
300 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
301
306#define DV_PATH_DISCOVERY_FREQUENCY \
307 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
308
312#define EPHEMERAL_VALIDITY \
313 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
314
318#define REASSEMBLY_EXPIRATION \
319 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
320
327#define MAX_REASSEMBLY_CONTEXTS 32
328
333#define FAST_VALIDATION_CHALLENGE_FREQ \
334 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
335
339#define MAX_VALIDATION_CHALLENGE_FREQ \
340 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
341
347#define WANTED_VALIDATION_CHALLENGE_FREQ \
348 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
349
354#define SUGGEST_RETRY_MIN \
355 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
356
363#define SUGGEST_RETRY_MAX \
364 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
365
371#define ACK_CUMMULATOR_TIMEOUT \
372 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
373
378#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
379
384#define DV_LEARN_QUALITY_THRESHOLD 100
385
389#define MAX_ADDRESS_VALID_UNTIL \
390 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
391
395#define ADDRESS_VALIDATION_LIFETIME \
396 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
397
414#define NEIGHBOUR_LIVENESS_TIMEOUT \
415 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
416
445#define FC_KEEPALIVE_INTERVAL \
446 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, \
447 2)
448
454#define MIN_ADDRESS_REFRESH_INTERVAL \
455 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
456
463#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
464
471#define VALIDATION_RTT_BUFFER_FACTOR 3
472
479#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
480
486#define QUEUE_LENGTH_LIMIT 32
487
491#define QUEUE_ENTRY_TIMEOUT \
492 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
493
498#define RTT_DIFF \
499 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
500
507#define SHUTDOWN_CLIENT_GRACE_PERIOD \
508 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
509
511
516{
522};
523
524
535
540{
545
546 /* Followed by *another* message header which is the message to
547 the communicator */
548
549 /* Followed by a 0-terminated name of the communicator */
550};
551
552
590
591
597{
602
608
620
621 /* Followed by a `struct GNUNET_MessageHeader` with a message
622 for the target peer */
623};
624
625
652
653
672
673
682{
687
693
694 /* followed by any number of `struct TransportCummulativeAckPayloadP`
695 messages providing ACKs */
696};
697
698
734
735
779
780
819
820
838
839
854{
859
865
875
882
896
902
907
912
913 /* Followed by @e num_hops `struct DVPathEntryP` values,
914 excluding the initiator of the DV trace; the last entry is the
915 current sender; the current peer must not be included. */
916};
917
918
942{
947
952
960
967
973
980
987
994
995 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
996 excluding the @e origin and the current peer, the last must be
997 the ultimate target; if @e num_hops is zero, the receiver of this
998 message is the ultimate target. */
999
1000 /* Followed by encrypted, variable-size payload, which
1001 must begin with a `struct TransportDVBoxPayloadP` */
1002
1003 /* Followed by the actual message, which itself must not be a
1004 a DV_LEARN or DV_BOX message! */
1005};
1006
1007
1035
1036
1059
1060
1100
1102{
1107
1108 /* Followed by @e address_length bytes of the address. */
1109};
1110
1120{
1125
1134
1140
1147
1157
1167
1172
1177
1182
1188
1189 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1190};
1191
1193
1194/* GNUNET_NETWORK_STRUCT_BEGIN/_END expand to nothing; only the per-member
1195 GNUNET_PACKED keeps these layouts free of compiler padding. Pin the sizes
1196 so that adding an unpacked or non-fixed-width member cannot silently put
1197 padding bytes -- i.e. uninitialised stack -- on the wire again. */
1199
1208
1209
1214{
1219
1224
1229
1234
1238 CT_APPLICATION = 4
1240
1241
1275
1276
1303
1304
1310{
1314 uint64_t bytes_sent;
1315
1321};
1322
1323
1346
1347
1351struct TransportClient;
1352
1356struct Neighbour;
1357
1362struct DistanceVector;
1363
1368struct Queue;
1369
1373struct PendingMessage;
1374
1378struct DistanceVectorHop;
1379
1388struct VirtualLink;
1389
1390
1447
1448
1464
1465
1470{
1475
1480
1485
1489 uint16_t size;
1490
1497 uint16_t isize;
1498};
1499
1500
1505{
1511
1516
1521
1529 uint8_t *bitfield;
1530
1535
1541
1545 uint16_t msg_size;
1546
1551 uint16_t msg_missing;
1552
1553 /* Followed by @e msg_size bytes of the (partially) defragmented original
1554 * message */
1555
1556 /* Followed by @e bitfield data */
1557};
1558
1559
1569{
1574
1581
1588
1593
1599
1605
1610 unsigned int cmc_count;
1611
1618
1623
1628
1633
1638
1646
1652
1658
1663
1668
1673
1678 unsigned int confirmed;
1679
1683 struct Neighbour *n;
1684
1689
1696
1703
1712
1718
1724
1729
1735
1744
1752
1759
1768
1781
1787
1794
1805
1810 uint32_t fc_seq_gen;
1811
1817 uint32_t last_fc_seq;
1818
1831
1836};
1837
1838
1922
1923
2003
2004
2063
2064
2075{
2080
2085
2089 struct Queue *queue;
2090
2095
2099 uint64_t mid;
2100
2105};
2106
2107
2112struct Queue
2113{
2118
2123
2128
2133
2138
2143
2148
2153
2158
2163
2167 const char *address;
2168
2172 unsigned int unlimited_length;
2173
2179
2188
2193
2199
2204 uint64_t mid_gen;
2205
2209 uint32_t qid;
2210
2214 uint32_t mtu;
2215
2220
2225
2229 unsigned int queue_length;
2230
2234 uint64_t q_capacity;
2235
2239 uint32_t priority;
2240
2245
2250
2255 int idle;
2256
2261};
2262
2263
2354
2355
2382
2383
2387struct PeerRequest
2388{
2393
2398
2403
2409
2415
2422
2427};
2428
2429
2455
2456
2483struct PendingMessage
2484{
2489
2494
2499
2504
2510
2516
2521
2526
2532
2538
2543
2553
2558
2563
2568
2573
2578
2583
2589
2595
2600
2606
2611
2615 uint16_t bytes_msg;
2616
2620 uint16_t frag_off;
2621
2626
2631
2635 uint16_t frag_count;
2636
2641
2650
2651 /* Followed by @e bytes_msg to transmit */
2652};
2653
2654
2671
2672
2713
2714
2720
2721
2801
2802
2807{
2812
2817
2822
2827
2832
2833 union
2834 {
2838 struct
2839 {
2845
2851
2855 struct
2856 {
2863
2869
2870
2874 struct
2875 {
2881
2886
2891
2897
2903
2910
2915
2920
2925
2927
2931 struct
2932 {
2940};
2941
2942
2948{
2954
2962
2968
2975 struct GNUNET_TIME_Absolute first_challenge_use;
2976
2983 struct GNUNET_TIME_Absolute last_challenge_use;
2984
2992 struct GNUNET_TIME_Absolute next_challenge;
2993
3002 struct GNUNET_TIME_Relative challenge_backoff;
3003
3008 struct GNUNET_TIME_Relative validation_rtt;
3009
3017 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
3018
3022 struct GNUNET_HashCode hc;
3023
3027 struct GNUNET_SCHEDULER_Task *revalidation_task;
3028
3032 char *address;
3033
3039 struct GNUNET_CONTAINER_HeapNode *hn;
3040
3046
3052 uint32_t last_window_consum_limit;
3053
3058 int awaiting_queue;
3059};
3060
3061
3119
3124
3128static unsigned int ring_buffer_head;
3129
3133static unsigned int is_ring_buffer_full;
3134
3139
3143static unsigned int ring_buffer_dv_head;
3144
3148static unsigned int is_ring_buffer_dv_full;
3149
3154
3159
3164
3169
3176
3182
3187
3193
3199
3205
3211
3217
3223
3229
3235
3240
3244static struct LearnLaunchEntry *lle_head = NULL;
3245
3249static struct LearnLaunchEntry *lle_tail = NULL;
3250
3257
3262
3267
3272
3276struct PilsRequest
3277{
3281 struct PilsRequest *prev;
3282
3286 struct PilsRequest *next;
3287
3291 struct GNUNET_PILS_Operation *op;
3292};
3293
3298
3303
3328static enum GNUNET_GenericReturnValue
3330 struct GNUNET_CRYPTO_EddsaSignature *sig)
3331{
3333
3335 if (NULL == my_private_key)
3336 {
3337 /* #run() enables local key access, so this means the key on disk does
3338 not match the identity PILS announced, or no identity is known yet. */
3340 "No private key for our peer identity, cannot sign\n");
3342 "# signatures failed (no private key)",
3343 1,
3344 GNUNET_NO);
3345 return GNUNET_SYSERR;
3346 }
3347 return GNUNET_CRYPTO_eddsa_sign_ (my_private_key, purpose, sig);
3348}
3349
3350
3355
3360
3365
3370
3377
3382
3386static unsigned int ir_total;
3387
3391static unsigned long long logging_uuid_gen;
3392
3397
3407
3412static int in_shutdown;
3413
3418
3425
3427
3429
3440static unsigned int
3442{
3443 struct GNUNET_TIME_Absolute now;
3444
3445 now = GNUNET_TIME_absolute_get ();
3446 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3447}
3448
3449
3455static void
3457{
3459 GNUNET_assert (ir_total > 0);
3460 ir_total--;
3461 if (NULL != ir->nc)
3463 ir->nc = NULL;
3464 GNUNET_free (ir);
3465}
3466
3467
3473static void
3475{
3476 struct Queue *q = pa->queue;
3477 struct PendingMessage *pm = pa->pm;
3478 struct DistanceVectorHop *dvh = pa->dvh;
3479
3481 "free_pending_acknowledgement\n");
3482 if (NULL != q)
3483 {
3484 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3485 pa->queue = NULL;
3486 }
3487 if (NULL != pm)
3488 {
3490 "remove pa from message\n");
3492 "remove pa from message %" PRIu64 "\n",
3493 pm->logging_uuid);
3495 "remove pa from message %u\n",
3496 pm->pmt);
3498 "remove pa from message %s\n",
3500 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3501 pa->pm = NULL;
3502 }
3503 if (NULL != dvh)
3504 {
3505 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3506 pa->dvh = NULL;
3507 }
3510 &pa->ack_uuid.value,
3511 pa));
3512 GNUNET_free (pa);
3513}
3514
3515
3524static void
3526{
3527 struct PendingMessage *frag;
3528
3529 while (NULL != (frag = root->head_frag))
3530 {
3531 struct PendingAcknowledgement *pa;
3532
3533 free_fragment_tree (frag);
3534 /* Release them: a `struct PendingAcknowledgement' whose @e pm is gone
3535 can never do anything useful again -- handle_acknowledged() would
3536 just free it -- but it stays in #pending_acks, and only an ACK that
3537 may never come takes it out. Merely detaching it here leaked one
3538 entry per fragment that was not acknowledged before its message went
3539 away, which on a lossy link is unbounded growth. */
3540 while (NULL != (pa = frag->pa_head))
3542 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3543 if (NULL != frag->qe)
3544 {
3545 GNUNET_assert (frag == frag->qe->pm);
3546 frag->qe->pm = NULL;
3547 }
3549 "Free frag %p\n",
3550 frag);
3551 GNUNET_free (frag);
3552 }
3553}
3554
3555
3563static void
3565{
3566 struct TransportClient *tc = pm->client;
3567 struct VirtualLink *vl = pm->vl;
3568 struct PendingAcknowledgement *pa;
3569
3571 "Freeing pm %p\n",
3572 pm);
3573 if (NULL != tc)
3574 {
3576 tc->details.core.pending_msg_head,
3577 tc->details.core.pending_msg_tail,
3578 pm);
3579 }
3580 if ((NULL != vl) && (NULL == pm->frag_parent))
3581 {
3583 "Removing pm %" PRIu64 "\n",
3584 pm->logging_uuid);
3586 vl->pending_msg_head,
3587 vl->pending_msg_tail,
3588 pm);
3589 }
3590 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3591 {
3592 struct PendingMessage *root = pm->frag_parent;
3593
3594 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3595 root = root->frag_parent;
3596
3597 root->frag_count--;
3598 }
3599 /* Same as in #free_fragment_tree(): the message these acknowledgements
3600 belong to is going away, so they are garbage rather than orphans. */
3601 while (NULL != (pa = pm->pa_head))
3603
3604 free_fragment_tree (pm);
3605 if (NULL != pm->qe)
3606 {
3607 GNUNET_assert (pm == pm->qe->pm);
3608 pm->qe->pm = NULL;
3609 }
3610 if (NULL != pm->bpm)
3611 {
3612 free_fragment_tree (pm->bpm);
3613 /* @e bpm is released with GNUNET_free() rather than through
3614 #free_pending_message(), so nothing here ever unlinked the
3615 acknowledgements attached to the box itself -- only those of its
3616 fragments, via the call above. They kept @e pm pointing into the
3617 block we are about to release, and #handle_acknowledged() follows
3618 that pointer when the ACK finally arrives. */
3619 while (NULL != (pa = pm->bpm->pa_head))
3621 if (NULL != pm->bpm->qe)
3622 {
3623 struct QueueEntry *qe = pm->bpm->qe;
3624
3625 qe->pm = NULL;
3626 }
3627 GNUNET_free (pm->bpm);
3628 }
3629
3630 GNUNET_free (pm);
3632 "Freeing pm done\n");
3633}
3634
3635
3641static void
3653
3654
3660static void
3662{
3663 struct VirtualLink *vl = cls;
3664 struct ReassemblyContext *rc;
3665
3666 vl->reassembly_timeout_task = NULL;
3667 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3668 {
3670 .rel_value_us)
3671 {
3673 continue;
3674 }
3679 vl);
3680 return;
3681 }
3682}
3683
3684
3693static int
3694free_reassembly_cb (void *cls, uint32_t key, void *value)
3695{
3696 struct ReassemblyContext *rc = value;
3697
3698 (void) cls;
3699 (void) key;
3701 return GNUNET_OK;
3702}
3703
3704
3711static void
3713 unsigned int free_cmc);
3714
3715
3723static void
3725 struct CommunicatorMessageContext *cmc);
3726
3727
3734static void
3735free_burst_cls (struct GNUNET_StartBurstCls *sb_cls);
3736
3737
3755static void
3757 const struct GNUNET_PeerIdentity *pid)
3758{
3759 struct GNUNET_MQ_Envelope *env;
3760 struct SendOkMessage *so_msg;
3761
3762 if (NULL == tc)
3763 return;
3765 so_msg->peer = *pid;
3766 GNUNET_MQ_send (tc->mq, env);
3767}
3768
3769
3782static void
3784{
3785 if ((NULL == pm->client) || (GNUNET_YES == pm->client_credited))
3786 return;
3788 send_ok_to_client (pm->client, &pm->vl->target);
3789}
3790
3791
3797static void
3799{
3800 struct PendingMessage *pm;
3801 struct CoreSentContext *csc;
3802 struct CommunicatorMessageContext *cmc;
3803
3805 "free virtual link %p\n",
3806 vl);
3807
3808 /* Communicators that are blocked on CORE flow control for this link MUST
3809 be resumed here. Otherwise their `struct CommunicatorMessageContext's
3810 leak and -- worse -- those clients never get their
3811 GNUNET_SERVICE_client_continue() and stall forever. */
3812 while (NULL != (cmc = vl->cmc_head))
3813 release_stalled_cmc (vl, cmc);
3814 if (NULL != vl->core_fc_stall_task)
3815 {
3817 vl->core_fc_stall_task = NULL;
3818 }
3819
3820 if (NULL != vl->reassembly_map)
3821 {
3824 NULL);
3826 vl->reassembly_map = NULL;
3828 vl->reassembly_heap = NULL;
3829 }
3830 if (NULL != vl->reassembly_timeout_task)
3831 {
3833 vl->reassembly_timeout_task = NULL;
3834 }
3835 while (NULL != (pm = vl->pending_msg_head))
3836 {
3837 /* These never got transmitted, so #completed_pending_message() will not
3838 run for them and nobody else answers their SEND either. Return the
3839 window credit anyway: CORE keeps its `struct Neighbour' -- and thus
3840 the window -- until it sees our DISCONNECT, and #handle_client_send()
3841 deliberately tolerates a SEND for a link that is already gone, so a
3842 client can easily still be sending while we free this. */
3843 credit_client (pm);
3845 }
3848 if (NULL != vl->visibility_task)
3849 {
3851 vl->visibility_task = NULL;
3852 }
3853 if (NULL != vl->fc_retransmit_task)
3854 {
3856 vl->fc_retransmit_task = NULL;
3857 }
3858 while (NULL != (csc = vl->csc_head))
3859 {
3861 GNUNET_assert (vl == csc->vl);
3862 csc->vl = NULL;
3863 }
3864 if (NULL != vl->unconfirmed_timeout_task)
3865 {
3867 vl->unconfirmed_timeout_task = NULL;
3868 }
3869 if (NULL != vl->ic)
3870 {
3871 /* the closure of this iteration is @e sb_cls, released just below */
3873 vl->ic = NULL;
3874 }
3875 if (NULL != vl->sb_cls)
3876 {
3877 /* Cancels #burst_task if that task's closure is ours: it would
3878 otherwise run on this (freed) link. */
3879 free_burst_cls (vl->sb_cls);
3880 GNUNET_assert (NULL == vl->sb_cls);
3881 }
3882 GNUNET_free (vl->burst_addr);
3883 GNUNET_break (NULL == vl->n);
3884 GNUNET_break (NULL == vl->dv);
3885 GNUNET_free (vl);
3886}
3887
3888
3894static void
3896{
3897 if (NULL != vs->revalidation_task)
3898 {
3899 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3900 vs->revalidation_task = NULL;
3901 }
3902 /*memcpy (&hkey,
3903 &hc,
3904 sizeof (hkey));*/
3906 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3907 GNUNET_h2s (&vs->hc),
3908 vs->address,
3911 &vs->hc));
3914 GNUNET_YES ==
3917 vs->hn = NULL;
3918 if (NULL != vs->sc)
3919 {
3921 "store cancel\n");
3923 vs->sc = NULL;
3924 }
3925 GNUNET_free (vs->address);
3926 GNUNET_free (vs);
3927}
3928
3929
3936static struct Neighbour *
3941
3942
3949static struct VirtualLink *
3951{
3953}
3954
3955
3988
3989
3998static void
4000{
4001 struct Neighbour *n = dvh->next_hop;
4002 struct DistanceVector *dv = dvh->dv;
4003 struct PendingAcknowledgement *pa;
4004
4005 while (NULL != (pa = dvh->pa_head))
4006 {
4008 pa->dvh = NULL;
4009 }
4010 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
4012 GNUNET_free (dvh);
4013}
4014
4015
4022static void
4023check_link_down (void *cls);
4024
4025
4031static void
4033{
4035 "Informing CORE clients about disconnect from %s\n",
4036 GNUNET_i2s (pid));
4037 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4038 {
4039 struct GNUNET_MQ_Envelope *env;
4040 struct DisconnectInfoMessage *dim;
4041
4042 if (CT_CORE != tc->type)
4043 continue;
4045 dim->peer = *pid;
4046 GNUNET_MQ_send (tc->mq, env);
4047 }
4048}
4049
4050
4051static void
4052try_to_bring_link_up (const struct GNUNET_PeerIdentity *pid);
4053
4054
4077static void
4079{
4080 struct GNUNET_PeerIdentity target = vl->target;
4081
4082 for (struct PendingMessage *pm = vl->pending_msg_head;
4083 NULL != pm;
4084 pm = pm->next_vl)
4085 credit_client (pm);
4087 free_virtual_link (vl);
4088 /* Start getting it back now. Only #handle_validation_response() can
4089 rebuild it, and a successful validation parks @e revalidation_task just
4090 short of #ADDRESS_VALIDATION_LIFETIME -- four hours away. */
4091 try_to_bring_link_up (&target);
4092}
4093
4094
4101static void
4103{
4104 struct DistanceVectorHop *dvh;
4105 struct VirtualLink *vl;
4106
4107 while (NULL != (dvh = dv->dv_head))
4109
4111 GNUNET_YES ==
4113 if (NULL != (vl = dv->vl))
4114 {
4115 GNUNET_assert (dv == vl->dv);
4116 vl->dv = NULL;
4117 if (NULL == vl->n)
4118 {
4120 }
4121 else
4122 {
4123 /* @e visibility_task is NULL while #check_link_down() itself runs, and
4124 #GNUNET_SCHEDULER_cancel() dereferences its argument. */
4125 if (NULL != vl->visibility_task)
4128 }
4129 dv->vl = NULL;
4130 }
4131
4132 if (NULL != dv->timeout_task)
4133 {
4135 dv->timeout_task = NULL;
4136 }
4137 GNUNET_free (dv->km);
4138 GNUNET_free (dv);
4139}
4140
4141
4155static void
4157 const struct GNUNET_PeerIdentity *peer,
4158 const char *address,
4160 const struct MonitorEvent *me)
4161{
4162 struct GNUNET_MQ_Envelope *env;
4164 size_t addr_len = strlen (address) + 1;
4165
4167 addr_len,
4169 md->nt = htonl ((uint32_t) nt);
4170 md->peer = *peer;
4171 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
4172 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
4173 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
4174 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
4175 md->cs = htonl ((uint32_t) me->cs);
4176 md->num_msg_pending = htonl (me->num_msg_pending);
4177 md->num_bytes_pending = htonl (me->num_bytes_pending);
4178 memcpy (&md[1], address, addr_len);
4179 GNUNET_MQ_send (tc->mq, env);
4180}
4181
4182
4192static void
4194 const char *address,
4196 const struct MonitorEvent *me)
4197{
4198 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4199 {
4200 if (CT_MONITOR != tc->type)
4201 continue;
4202 if (tc->details.monitor.one_shot)
4203 continue;
4204 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
4205 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
4206 continue;
4208 }
4209}
4210
4211
4221static void *
4223 struct GNUNET_SERVICE_Client *client,
4224 struct GNUNET_MQ_Handle *mq)
4225{
4226 struct TransportClient *tc;
4227
4228 (void) cls;
4229 tc = GNUNET_new (struct TransportClient);
4230 tc->client = client;
4231 tc->mq = mq;
4234 "Client %p of type %u connected\n",
4235 tc,
4236 tc->type);
4237 return tc;
4238}
4239
4240
4241static enum GNUNET_GenericReturnValue
4243 const struct GNUNET_PeerIdentity *pid,
4244 void *value)
4245{
4246 struct TransportGlobalNattedAddress *tgna = value;
4247 (void) cls;
4248
4249 GNUNET_free (tgna);
4250
4251 return GNUNET_OK;
4252}
4253
4254
4261static void
4262free_neighbour (struct Neighbour *neighbour,
4263 enum GNUNET_GenericReturnValue drop_link)
4264{
4265 struct DistanceVectorHop *dvh;
4266 struct VirtualLink *vl;
4267
4268 GNUNET_assert (NULL == neighbour->queue_head);
4271 &neighbour->pid,
4272 neighbour));
4274 "Freeing neighbour\n");
4277 NULL);
4279 while (NULL != (dvh = neighbour->dv_head))
4280 {
4281 struct DistanceVector *dv = dvh->dv;
4282
4284 if (NULL == dv->dv_head)
4285 free_dv_route (dv);
4286 }
4287 if (NULL != neighbour->get)
4288 {
4290 neighbour->get = NULL;
4291 }
4292 if (NULL != neighbour->sc)
4293 {
4295 "store cancel\n");
4296 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
4297 neighbour->sc = NULL;
4298 }
4299 if (NULL != (vl = neighbour->vl))
4300 {
4301 GNUNET_assert (neighbour == vl->n);
4302 vl->n = NULL;
4303 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
4304 {
4306 }
4307 else
4308 {
4309 /* See #free_dv_route(): may be NULL under #check_link_down(). */
4310 if (NULL != vl->visibility_task)
4313 }
4314 neighbour->vl = NULL;
4315 }
4316 GNUNET_free (neighbour);
4317}
4318
4319
4326static void
4328 const struct GNUNET_PeerIdentity *pid)
4329{
4330 struct GNUNET_MQ_Envelope *env;
4331 struct ConnectInfoMessage *cim;
4332
4333 GNUNET_assert (CT_CORE == tc->type);
4335 cim->id = *pid;
4336 GNUNET_MQ_send (tc->mq, env);
4337}
4338
4339
4345static void
4347{
4349 "Informing CORE clients about connection to %s\n",
4350 GNUNET_i2s (pid));
4351 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
4352 {
4353 if (CT_CORE != tc->type)
4354 continue;
4356 }
4357}
4358
4359
4367static void
4368transmit_on_queue (void *cls);
4369
4370
4379static unsigned int
4381{
4382 for (struct Queue *s = queue_head; NULL != s;
4383 s = s->next_neighbour)
4384 {
4385 if (s == queue)
4386 continue;
4387 if (s->tc->details.communicator.address_prefix !=
4388 queue->tc->details.communicator.address_prefix)
4389 {
4391 "queue address %s qid %u compare with queue: address %s qid %u\n",
4392 queue->address,
4393 queue->qid,
4394 s->address,
4395 s->qid);
4396 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
4397 (QUEUE_LENGTH_LIMIT > s->queue_length) )
4398 return GNUNET_YES;
4400 "Lower prio\n");
4401 }
4402 }
4403 return GNUNET_NO;
4404}
4405
4406
4413static void
4415
4416
4424static void
4426 struct Queue *queue,
4428{
4430
4431 if (queue->validated_until.abs_value_us < now.abs_value_us)
4432 return;
4434 queue->neighbour->queue_head))
4435 return;
4436
4437 if (queue->tc->details.communicator.total_queue_length >=
4439 {
4441 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
4442 queue->address,
4443 queue->qid);
4445 GST_stats,
4446 "# Transmission throttled due to communicator queue limit",
4447 1,
4448 GNUNET_NO);
4449 queue->idle = GNUNET_NO;
4450 /* @e total_queue_length is shared by every peer this communicator serves,
4451 so at the limit we can send to none of them, and the only things that
4452 lower it again are an ACK from the communicator, #free_queue() and
4453 #free_timedout_queue_entry(). If we got here because a peer stopped
4454 acknowledging, no ACK is coming; and we just declined to arm
4455 @e transmit_task, so #queue_send_msg() -- the *only* place that arms
4456 the sweeper -- will not run either. That leaves nothing at all to
4457 recover the count, and the communicator stays mute towards every peer
4458 until some unrelated queue happens to go down. Keep the sweeper
4459 going. */
4461 return;
4462 }
4463 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
4464 {
4466 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
4467 queue->address,
4468 queue->qid);
4470 "# Transmission throttled due to queue queue limit",
4471 1,
4472 GNUNET_NO);
4473 queue->idle = GNUNET_NO;
4474 /* Same reasoning as above, for the per-queue limit. */
4476 return;
4477 }
4478 if (0 == queue->q_capacity)
4479 {
4481 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
4482 PRIu64 ".\n",
4483 queue->address,
4484 queue->qid,
4485 queue->q_capacity);
4487 "# Transmission throttled due to message queue capacity",
4488 1,
4489 GNUNET_NO);
4490 queue->idle = GNUNET_NO;
4491 return;
4492 }
4493 /* queue might indeed be ready, schedule it */
4494 if (NULL != queue->transmit_task)
4495 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4496 queue->transmit_task =
4498 queue);
4500 "Considering transmission on queue `%s' QID %llu to %s\n",
4501 queue->address,
4502 (unsigned long long) queue->qid,
4503 GNUNET_i2s (&queue->neighbour->pid));
4504}
4505
4506
4507static void
4509 const char *address);
4510
4511
4518static void
4520{
4521 struct VirtualLink *vl = cls;
4522 struct DistanceVector *dv = vl->dv;
4523 struct Neighbour *n = vl->n;
4524 struct GNUNET_TIME_Absolute dvh_timeout;
4525 struct GNUNET_TIME_Absolute q_timeout;
4526
4528 "Checking if link is down\n");
4529 vl->visibility_task = NULL;
4530 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4531 if (NULL != dv)
4532 {
4533 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4534 pos = pos->next_dv)
4535 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4536 pos->path_valid_until);
4537 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4538 {
4539 vl->dv->vl = NULL;
4540 vl->dv = NULL;
4541 }
4542 }
4543 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4544 /* NOTE: @e n may be NULL here: #free_neighbour() clears vl->n and then
4545 schedules us when the link still has a DV route. */
4546 if (NULL != n)
4547 {
4548 struct GNUNET_TIME_Absolute liveness_deadline;
4549
4550 /* A successful validation is good for #ADDRESS_VALIDATION_LIFETIME (four
4551 hours). Do not take a communicator's word for that long: cap what the
4552 queues are worth by how recently this neighbour actually said anything
4553 to us. Otherwise a communicator that stops working without sending a
4554 QUEUE_TEARDOWN keeps this link -- and CORE's idea of the connection --
4555 alive until the validation expires. */
4556 liveness_deadline = GNUNET_TIME_absolute_add (n->last_inbound,
4558 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4559 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4560 if (GNUNET_TIME_absolute_cmp (liveness_deadline, <, q_timeout))
4561 {
4562 if (0 ==
4564 {
4565 /* Only reachable if a communicator failed to tear its queue down. */
4567 "Neighbour %s was silent for %s while its communicator "
4568 "kept claiming the queue works; treating link as down\n",
4569 GNUNET_i2s (&vl->target),
4572 GNUNET_YES));
4574 "# links dropped (neighbour silent)",
4575 1,
4576 GNUNET_NO);
4577 }
4578 q_timeout = liveness_deadline;
4579 }
4580 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
4581 {
4582 vl->n->vl = NULL;
4583 vl->n = NULL;
4584 }
4585 }
4586 if ((NULL == vl->n) && (NULL == vl->dv))
4587 {
4589 /* @e n (if any) outlives the link, and so do its queues: the liveness cap
4590 above drops a link whose addresses are still well inside
4591 #ADDRESS_VALIDATION_LIFETIME. In that state nothing would ever ask for
4592 a fresh challenge -- @e revalidation_task does not fire until the four
4593 hour validity is nearly over, and the HELLO path reaches
4594 #start_address_validation() only to find an address that still counts
4595 as valid. Since #handle_validation_response() is the only thing that
4596 can rebuild this link and tell CORE about the peer again, ask for that
4597 validation now, or CORE never hears about this peer again. */
4598 if (NULL != n)
4599 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4600 start_address_validation (&n->pid, q->address);
4601 return;
4602 }
4603 vl->visibility_task =
4604 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4606 vl);
4607}
4608
4609
4615static void
4617{
4618 struct Neighbour *neighbour = queue->neighbour;
4619 struct TransportClient *tc = queue->tc;
4620 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4622 struct QueueEntry *qe;
4623 int maxxed;
4624 struct PendingAcknowledgement *pa;
4625 struct VirtualLink *vl;
4626
4628 "Cleaning up queue %u\n", queue->qid);
4629 if (NULL != queue->mo)
4630 {
4632 queue->mo = NULL;
4633 }
4634 if (NULL != queue->transmit_task)
4635 {
4636 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4637 queue->transmit_task = NULL;
4638 }
4639 while (NULL != (pa = queue->pa_head))
4640 {
4641 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4642 pa->queue = NULL;
4643 }
4644
4646 neighbour->queue_head,
4647 neighbour->queue_tail,
4648 queue);
4650 tc->details.communicator.queue_head,
4651 tc->details.communicator.queue_tail,
4652 queue);
4654 tc->details.communicator.total_queue_length);
4656 "Cleaning up queue with length %u\n",
4657 queue->queue_length);
4658 while (NULL != (qe = queue->queue_head))
4659 {
4660 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4661 queue->queue_length--;
4662 tc->details.communicator.total_queue_length--;
4663 if (NULL != qe->pm)
4664 {
4665 GNUNET_assert (qe == qe->pm->qe);
4666 qe->pm->qe = NULL;
4667 }
4668 GNUNET_free (qe);
4669 }
4670 GNUNET_assert (0 == queue->queue_length);
4671 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4672 tc->details.communicator.total_queue_length))
4673 {
4674 /* Communicator dropped below threshold, resume all _other_ queues */
4676 GST_stats,
4677 "# Transmission throttled due to communicator queue limit",
4678 -1,
4679 GNUNET_NO);
4680 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4681 s = s->next_client)
4683 s,
4685 }
4686 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4688
4689 vl = lookup_virtual_link (&neighbour->pid);
4690 if ((NULL != vl) && (neighbour == vl->n))
4691 {
4692 /* See #free_dv_route(): may be NULL under #check_link_down(), which is
4693 also what clears it -- so the call below needs no re-arm here. */
4694 if (NULL != vl->visibility_task)
4696 vl->visibility_task = NULL;
4697 check_link_down (vl);
4698 }
4699 if (NULL == neighbour->queue_head)
4700 {
4701 free_neighbour (neighbour, GNUNET_NO);
4702 }
4703}
4704
4705
4713static void
4715
4716
4722static void
4724{
4725 struct TransportClient *tc = ale->tc;
4726
4727 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4728 tc->details.communicator.addr_tail,
4729 ale);
4730 /* Cancels @e sc, @e shc and the pending PILS signature request, all of
4731 which would otherwise run their callbacks on this freed entry. */
4733 if (NULL != ale->sc)
4734 {
4736 "store cancel\n");
4738 ale->sc = NULL;
4739 }
4740 if (NULL != ale->shc)
4741 {
4743 ale->shc = NULL;
4744 }
4745 if (NULL != ale->st)
4746 {
4748 ale->st = NULL;
4749 }
4750 if (NULL != ale->signed_address)
4752 GNUNET_free (ale);
4753}
4754
4755
4764static int
4766 const struct GNUNET_PeerIdentity *pid,
4767 void *value)
4768{
4769 struct TransportClient *tc = cls;
4770 struct PeerRequest *pr = value;
4771
4772 if (NULL != pr->retry_task)
4773 {
4774 GNUNET_SCHEDULER_cancel (pr->retry_task);
4775 pr->retry_task = NULL;
4776 }
4777 if (NULL != pr->nc)
4779 pr->nc = NULL;
4781 GNUNET_YES ==
4782 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4783 pid,
4784 pr));
4785 GNUNET_free (pr);
4786
4787 return GNUNET_OK;
4788}
4789
4790
4791static void
4792do_shutdown (void *cls);
4793
4794
4804static enum GNUNET_GenericReturnValue
4806 const struct GNUNET_PeerIdentity *pid,
4807 void *value)
4808{
4809 const struct TransportClient *tc = cls;
4810 struct VirtualLink *vl = value;
4811
4812 (void) pid;
4813 for (struct CommunicatorMessageContext *cmc = vl->cmc_head;
4814 NULL != cmc;
4815 cmc = cmc->next)
4816 if (tc == cmc->tc)
4817 cmc->tc = NULL;
4818 return GNUNET_OK;
4819}
4820
4821
4831static enum GNUNET_GenericReturnValue
4833 const struct GNUNET_PeerIdentity *pid,
4834 void *value)
4835{
4836 const struct TransportClient *tc = cls;
4837 struct Backtalker *b = value;
4838
4839 (void) pid;
4840 if ((NULL != b->cmc) && (tc == b->cmc->tc))
4841 b->cmc->tc = NULL;
4842 return GNUNET_OK;
4843}
4844
4845
4864static void
4866{
4869 (void *) tc);
4872 (void *) tc);
4873 for (unsigned int i = 0; i < RING_BUFFER_SIZE; i++)
4874 if ((NULL != ring_buffer[i]) &&
4875 (tc == ring_buffer[i]->cmc->tc))
4876 ring_buffer[i]->cmc->tc = NULL;
4877}
4878
4879
4888static void
4890 struct GNUNET_SERVICE_Client *client,
4891 void *app_ctx)
4892{
4893 struct TransportClient *tc = app_ctx;
4894
4895 (void) cls;
4896 (void) client;
4898 switch (tc->type)
4899 {
4900 case CT_NONE:
4902 "Unknown Client %p disconnected, cleaning up.\n",
4903 tc);
4904 break;
4905
4906 case CT_CORE: {
4907 struct PendingMessage *pm;
4909 "CORE Client %p disconnected, cleaning up.\n",
4910 tc);
4911
4912
4913 while (NULL != (pm = tc->details.core.pending_msg_head))
4914 {
4916 tc->details.core.pending_msg_head,
4917 tc->details.core.pending_msg_tail,
4918 pm);
4919 pm->client = NULL;
4920 }
4921 }
4922 break;
4923
4924 case CT_MONITOR:
4926 "MONITOR Client %p disconnected, cleaning up.\n",
4927 tc);
4928
4929 break;
4930
4931 case CT_COMMUNICATOR: {
4932 struct Queue *q;
4933 struct AddressListEntry *ale;
4934
4936 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4937 tc);
4938
4939 /* MUST come first: freeing the queues below can tear a virtual link
4940 down, and #free_virtual_link() releases the cmcs parked on it. */
4942 if (NULL != tc->details.communicator.free_queue_entry_task)
4944 tc->details.communicator.free_queue_entry_task);
4945 while (NULL != (q = tc->details.communicator.queue_head))
4946 free_queue (q);
4947 while (NULL != (ale = tc->details.communicator.addr_head))
4949 GNUNET_free (tc->details.communicator.address_prefix);
4950 }
4951 break;
4952
4953 case CT_APPLICATION:
4955 "APPLICATION Client %p disconnected, cleaning up.\n",
4956 tc);
4957
4958 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4960 tc);
4961 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4962 break;
4963 }
4964 GNUNET_free (tc);
4965 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4966 {
4968 "Our last client disconnected\n");
4969 do_shutdown (cls);
4970 }
4971}
4972
4973
4983static int
4985 const struct GNUNET_PeerIdentity *pid,
4986 void *value)
4987{
4988 struct TransportClient *tc = cls;
4989 struct VirtualLink *vl = value;
4990
4991 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4992 return GNUNET_OK;
4993
4995 "Telling new CORE client about existing connection to %s\n",
4996 GNUNET_i2s (pid));
4998 return GNUNET_OK;
4999}
5000
5001
5007static void
5009 unsigned
5010 int free_cmc);
5011
5012static enum GNUNET_GenericReturnValue
5014 const struct GNUNET_PeerIdentity *pid,
5015 void *value)
5016{
5017 struct VirtualLink *vl = value;
5018 struct CommunicatorMessageContext *cmc;
5019
5020 /* resume communicators */
5021 while (NULL != (cmc = vl->cmc_tail))
5022 release_stalled_cmc (vl, cmc);
5023 if (NULL != vl->core_fc_stall_task)
5024 {
5026 vl->core_fc_stall_task = NULL;
5027 }
5028 /* A CORE client that just attached has nothing outstanding, so give it a
5029 full window. The RECV_OKs that would have returned the credit spent by
5030 its predecessor died with that client, and #handle_client_recv_ok() is
5031 the only thing that ever raises this counter -- so without the reset
5032 every message on this link takes the "CORE ran out of window" path from
5033 here on, and only #core_fc_stalled() (after CORE_FC_STALL_TIMEOUT, and
5034 once per round) ever lets any through. */
5036 return GNUNET_OK;
5037}
5038
5039
5048static void
5049handle_client_start (void *cls, const struct StartMessage *start)
5050{
5051 // const struct GNUNET_PeerIdentity *my_identity;
5052 struct TransportClient *tc = cls;
5053 // uint32_t options;
5054 //
5055 // my_identity = GNUNET_PILS_get_identity (pils);
5056 // GNUNET_assert (my_identity);
5057 //
5058 // FIXME ignore the check of the peer ids for now.
5059 // (also deprecate the old way of obtaining our own peer ID)
5060 // options = ntohl (start->options);
5061 // if ((0 != (1 & options)) &&
5062 // (0 != GNUNET_memcmp (&start->self, my_identity)))
5063 // {
5064 // /* client thinks this is a different peer, reject */
5065 // GNUNET_break (0);
5066 // GNUNET_SERVICE_client_drop (tc->client);
5067 // return;
5068 // }
5069 if (CT_NONE != tc->type)
5070 {
5071 GNUNET_break (0);
5073 return;
5074 }
5075 tc->type = CT_CORE;
5077 "New CORE client with PID %s registered\n",
5078 GNUNET_i2s (&start->self));
5081 tc);
5084 NULL);
5086}
5087
5088
5095static int
5096check_client_send (void *cls, const struct OutboundMessage *obm)
5097{
5098 struct TransportClient *tc = cls;
5099 uint16_t size;
5100 const struct GNUNET_MessageHeader *obmm;
5101
5102 if (CT_CORE != tc->type)
5103 {
5104 GNUNET_break (0);
5105 return GNUNET_SYSERR;
5106 }
5107 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
5108 if (size < sizeof(struct GNUNET_MessageHeader))
5109 {
5110 GNUNET_break (0);
5111 return GNUNET_SYSERR;
5112 }
5113 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5114 if (size != ntohs (obmm->size))
5115 {
5116 GNUNET_break (0);
5117 return GNUNET_SYSERR;
5118 }
5119 return GNUNET_OK;
5120}
5121
5122
5130static void
5132{
5133 struct TransportClient *tc = pm->client;
5134 struct VirtualLink *vl = pm->vl;
5135
5137 "client send response\n");
5138 if (NULL != tc)
5139 {
5141 "Confirming transmission of <%" PRIu64 "> to %s\n",
5142 pm->logging_uuid,
5143 GNUNET_i2s (&vl->target));
5144 credit_client (pm);
5145 }
5147}
5148
5149
5159static unsigned int
5162 struct DistanceVectorHop **hops_array,
5163 unsigned int hops_array_length)
5164{
5165 uint64_t choices[hops_array_length];
5166 uint64_t num_dv;
5167 unsigned int dv_count;
5168
5169 /* Pick random vectors, but weighted by distance, giving more weight
5170 to shorter vectors */
5171 num_dv = 0;
5172 dv_count = 0;
5173 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5174 pos = pos->next_dv)
5175 {
5176 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
5177 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
5178 .rel_value_us == 0))
5179 continue; /* pos unconfirmed and confirmed required */
5180 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
5181 dv_count++;
5182 }
5183 if (0 == dv_count)
5184 return 0;
5185 if (dv_count <= hops_array_length)
5186 {
5187 dv_count = 0;
5188 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5189 pos = pos->next_dv)
5190 hops_array[dv_count++] = pos;
5191 return dv_count;
5192 }
5193 for (unsigned int i = 0; i < hops_array_length; i++)
5194 {
5195 int ok = GNUNET_NO;
5196 while (GNUNET_NO == ok)
5197 {
5198 choices[i] =
5199 GNUNET_CRYPTO_random_u64 (num_dv);
5200 ok = GNUNET_YES;
5201 for (unsigned int j = 0; j < i; j++)
5202 if (choices[i] == choices[j])
5203 {
5204 ok = GNUNET_NO;
5205 break;
5206 }
5207 }
5208 }
5209 dv_count = 0;
5210 num_dv = 0;
5211 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5212 pos = pos->next_dv)
5213 {
5214 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
5215
5216 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
5217 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
5218 .rel_value_us == 0))
5219 continue; /* pos unconfirmed and confirmed required */
5220 for (unsigned int i = 0; i < hops_array_length; i++)
5221 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
5222 hops_array[dv_count++] = pos;
5223 num_dv += delta;
5224 }
5225 return dv_count;
5226}
5227
5228
5235static int
5237 void *cls,
5239{
5240 struct TransportClient *tc = cls;
5241 uint16_t size;
5242
5243 if (CT_NONE != tc->type)
5244 {
5245 GNUNET_break (0);
5246 return GNUNET_SYSERR;
5247 }
5248 tc->type = CT_COMMUNICATOR;
5249 size = ntohs (cam->header.size) - sizeof(*cam);
5250 if (0 == size)
5251 return GNUNET_OK; /* receive-only communicator */
5253 return GNUNET_OK;
5254}
5255
5256
5268static void
5270{
5271 struct GNUNET_MQ_Envelope *env;
5273
5274 if (GNUNET_YES == cmc->ack_sent)
5275 return;
5276 cmc->ack_sent = GNUNET_YES;
5277 if (NULL == cmc->tc)
5278 return; /* communicator is gone, see #detach_cmcs_from_client() */
5279 if (0 == ntohl (cmc->im.fc_on))
5280 return; /* communicator did not ask for flow control */
5282 "Acknowledge message with flow control id %" PRIu64 "\n",
5283 cmc->im.fc_id);
5285 ack->reserved = htonl (0);
5286 ack->fc_id = cmc->im.fc_id;
5287 ack->sender = cmc->im.neighbour_sender;
5288 GNUNET_MQ_send (cmc->tc->mq, env);
5289}
5290
5291
5302static void
5304{
5305 if (GNUNET_YES == cmc->client_resumed)
5306 return;
5308 if (NULL == cmc->tc)
5309 return; /* communicator is gone, see #detach_cmcs_from_client() */
5311}
5312
5313
5322static void
5324 unsigned
5325 int free_cmc)
5326{
5327 send_cmc_ack (cmc);
5328 resume_cmc_client (cmc);
5329 if (GNUNET_YES == free_cmc)
5330 {
5331 GNUNET_free (cmc);
5332 }
5333}
5334
5335
5336static void
5345
5346
5347static void
5352
5353
5363static void
5364handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
5365{
5366 struct TransportClient *tc = cls;
5367 struct VirtualLink *vl;
5368 uint32_t delta;
5369 struct CommunicatorMessageContext *cmc;
5370
5371 if (CT_CORE != tc->type)
5372 {
5373 GNUNET_break (0);
5375 return;
5376 }
5377 vl = lookup_virtual_link (&rom->peer);
5378 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5379 {
5381 "# RECV_OK dropped: virtual link unknown",
5382 1,
5383 GNUNET_NO);
5385 return;
5386 }
5387 delta = ntohl (rom->increase_window_delta);
5388 vl->core_recv_window += delta;
5390 "CORE ack receiving message, increased CORE recv window to %d\n",
5391 vl->core_recv_window);
5393 if (vl->core_recv_window <= 0)
5394 return;
5395 /* release the flow control credit we withheld from the communicators */
5396 while (NULL != (cmc = vl->cmc_tail))
5397 release_stalled_cmc (vl, cmc);
5398 if (NULL != vl->core_fc_stall_task)
5399 {
5401 vl->core_fc_stall_task = NULL;
5402 }
5403}
5404
5405
5412static void
5414 void *cls,
5416{
5417 const struct GNUNET_PeerIdentity *my_identity;
5418 struct TransportClient *tc = cls;
5419 uint16_t size;
5420
5421 size = ntohs (cam->header.size) - sizeof(*cam);
5422 if (0 == size)
5423 {
5425 "Receive-only communicator connected\n");
5426 /* Receive-only communicator: it has no address prefix, but we still
5427 MUST resume the client or we will never read from it again. Use an
5428 empty prefix so that the various strcmp()s do not see NULL. */
5429 tc->details.communicator.address_prefix = GNUNET_strdup ("");
5431 return;
5432 }
5433 tc->details.communicator.address_prefix =
5434 GNUNET_strdup ((const char *) &cam[1]);
5435 tc->details.communicator.cc = ntohl (cam->cc);
5436 tc->details.communicator.can_burst = ntohl (cam->can_burst);
5438 if (NULL != my_identity)
5439 {
5441 "Communicator for peer %s with prefix '%s' connected %s\n",
5443 tc->details.communicator.address_prefix,
5444 tc->details.communicator.can_burst ? "can burst" :
5445 "can not burst");
5446 }
5447 else
5448 {
5450 "Communicator for local peer with prefix '%s' connected %s\n",
5451 tc->details.communicator.address_prefix,
5452 tc->details.communicator.can_burst ? "can burst" :
5453 "can not burst");
5454 }
5456}
5457
5458
5466static int
5468 void *cls,
5470{
5471 const struct GNUNET_MessageHeader *inbox;
5472 const char *is;
5473 uint16_t msize;
5474 uint16_t isize;
5475
5476 (void) cls;
5477 msize = ntohs (cb->header.size) - sizeof(*cb);
5478 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
5479 /* MUST bound the buffer before dereferencing @a inbox. */
5480 if (msize <= sizeof(struct GNUNET_MessageHeader))
5481 {
5482 GNUNET_break (0);
5483 return GNUNET_SYSERR;
5484 }
5485 isize = ntohs (inbox->size);
5486 if (isize >= msize)
5487 {
5488 GNUNET_break (0);
5489 return GNUNET_SYSERR;
5490 }
5491 is = (const char *) inbox;
5492 is += isize;
5493 msize -= isize;
5494 GNUNET_assert (0 < msize);
5495 if ('\0' != is[msize - 1])
5496 {
5497 GNUNET_break (0);
5498 return GNUNET_SYSERR;
5499 }
5500 return GNUNET_OK;
5501}
5502
5503
5518static enum GNUNET_GenericReturnValue
5533
5534
5535static void
5537 struct TransportClient *tc);
5538
5539
5540static void
5542{
5543 struct TransportClient *tc = cls;
5545
5547 "freeing timedout queue entries\n");
5548
5549 tc->details.communicator.free_queue_entry_task = NULL;
5550 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
5551 queue = queue->next_client)
5552 {
5553 struct QueueEntry *qep = queue->queue_head;
5554
5556 "checking QID %u for timedout queue entries\n",
5557 queue->qid);
5558 while (NULL != qep)
5559 {
5560 struct QueueEntry *pos = qep;
5562 pos->creation_timestamp, now);
5563 qep = qep->next;
5564
5566 "diff to now %s \n",
5569 {
5571 "Freeing timed out QueueEntry with MID %" PRIu64
5572 " and QID %u\n",
5573 pos->mid,
5574 queue->qid);
5576 "# QueueEntries timed out",
5577 1,
5578 GNUNET_NO);
5579 free_queue_entry (pos, tc);
5580 }
5581 }
5582 }
5583 /* Entries younger than #QUEUE_ENTRY_TIMEOUT are still to be reclaimed, and
5584 this task used to be a one-shot armed only by #queue_send_msg(). So the
5585 sweep that was supposed to bound how long an unacknowledged entry holds
5586 its slot only ever ran while *new* messages were being queued -- exactly
5587 not the case once the throttles in #schedule_transmit_on_queue() have
5588 stopped transmission. Keep going as long as anything is outstanding. */
5590}
5591
5592
5593static void
5595{
5596 if (NULL != tc->details.communicator.free_queue_entry_task)
5597 return;
5598 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
5599 queue = queue->next_client)
5600 {
5601 if (NULL == queue->queue_head)
5602 continue;
5603 tc->details.communicator.free_queue_entry_task =
5606 tc);
5607 return;
5608 }
5609}
5610
5611
5621static void
5623 struct PendingMessage *pm,
5624 const void *payload,
5625 size_t payload_size)
5626{
5627 struct Neighbour *n = queue->neighbour;
5629 struct GNUNET_MQ_Envelope *env;
5630 struct PendingAcknowledgement *pa;
5631
5632 GNUNET_log (
5634 "Queueing %u bytes of payload for transmission <%" PRIu64
5635 "> on queue %llu to %s\n",
5636 (unsigned int) payload_size,
5637 (NULL == pm) ? 0 : pm->logging_uuid,
5638 (unsigned long long) queue->qid,
5639 GNUNET_i2s (&queue->neighbour->pid));
5640 env = GNUNET_MQ_msg_extra (smt,
5641 payload_size,
5643 smt->qid = htonl (queue->qid);
5644 smt->mid = GNUNET_htonll (queue->mid_gen);
5645 smt->receiver = n->pid;
5646 memcpy (&smt[1], payload, payload_size);
5647 {
5648 /* Pass the env to the communicator of queue for transmission. */
5649 struct QueueEntry *qe;
5650
5651 qe = GNUNET_new (struct QueueEntry);
5652 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
5653 qe->mid = queue->mid_gen;
5655 "Create QueueEntry with MID %" PRIu64
5656 " and QID %u and prefix %s\n",
5657 qe->mid,
5658 queue->qid,
5659 queue->tc->details.communicator.address_prefix);
5660 queue->mid_gen++;
5661 qe->queue = queue;
5662 if (NULL != pm)
5663 {
5664 qe->pm = pm;
5665 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
5666 // GNUNET_assert (NULL == pm->qe);
5667 if (NULL != pm->qe)
5668 {
5670 "Retransmitting message <%" PRIu64
5671 "> remove pm from qe with MID: %llu \n",
5673 (unsigned long long) pm->qe->mid);
5674 pm->qe->pm = NULL;
5675 }
5676 pm->qe = qe;
5677 }
5678 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
5679 if (0 == queue->q_capacity)
5680 {
5681 // Messages without FC or fragments can get here.
5682 if (NULL != pm)
5683 {
5685 "Message %" PRIu64
5686 " (pm type %u) was not send because queue has no capacity.\n",
5688 pm->pmt);
5689 pm->qe = NULL;
5690 }
5691 GNUNET_free (env);
5692 GNUNET_free (qe);
5693 return;
5694 }
5695 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
5696 queue->queue_length++;
5697 queue->tc->details.communicator.total_queue_length++;
5698 if (GNUNET_NO == queue->unlimited_length)
5699 queue->q_capacity--;
5701 "Queue %s with qid %u has capacity %" PRIu64 "\n",
5702 queue->address,
5703 queue->qid,
5704 queue->q_capacity);
5706 queue->tc->details.communicator.total_queue_length)
5707 queue->idle = GNUNET_NO;
5708 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
5709 queue->idle = GNUNET_NO;
5710 if (0 == queue->q_capacity)
5711 queue->idle = GNUNET_NO;
5712
5713 if (GNUNET_NO == queue->idle)
5715 if (NULL != pm)
5716 {
5717 /* NOTE: @e next_pa was never the link of this list -- nothing ever
5718 assigned it, so it was NULL on every entry. The MDLL that
5719 #prepare_pending_acknowledgement() inserts into is keyed `pm', and
5720 thus threaded through @e next_pm. Walking @e next_pa dereferenced
5721 NULL the moment the head was not the entry we wanted. */
5722 for (pa = pm->pa_head; NULL != pa; pa = pa->next_pm)
5723 if (pm == pa->pm)
5724 {
5725 pa->num_send++;
5726 break;
5727 }
5728 }
5729 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
5731 "Sending message MID %" PRIu64
5732 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
5733 PRIu64 "\n",
5734 GNUNET_ntohll (smt->mid),
5735 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
5736 ntohs (smt->header.size),
5737 (unsigned long) payload_size,
5738 queue->tc->mq,
5739 queue->address,
5740 queue->qid,
5741 (NULL == pm) ? 0 : pm->logging_uuid);
5742 GNUNET_MQ_send (queue->tc->mq, env);
5743 }
5744}
5745
5746
5757static struct GNUNET_TIME_Relative
5759 const struct GNUNET_MessageHeader *hdr,
5761{
5762 struct GNUNET_TIME_Absolute now;
5763 unsigned int candidates;
5764 unsigned int sel1;
5765 unsigned int sel2;
5766 struct GNUNET_TIME_Relative rtt;
5767
5768 /* Pick one or two 'random' queues from n (under constraints of options) */
5769 now = GNUNET_TIME_absolute_get ();
5770 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
5771 weight in the future; weight could be assigned by observed
5772 bandwidth (note: not sure if we should do this for this type
5773 of control traffic though). */
5774 candidates = 0;
5775 for (struct Queue *pos = n->queue_head; NULL != pos;
5776 pos = pos->next_neighbour)
5777 {
5778 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5779 (pos->validated_until.abs_value_us > now.abs_value_us))
5780 candidates++;
5781 }
5782 if (0 == candidates)
5783 {
5784 /* This can happen rarely if the last confirmed queue timed
5785 out just as we were beginning to process this message. */
5787 "Could not route message of type %u to %s: no valid queue\n",
5788 ntohs (hdr->type),
5789 GNUNET_i2s (&n->pid));
5791 "# route selection failed (all no valid queue)",
5792 1,
5793 GNUNET_NO);
5795 }
5796
5798 sel1 = GNUNET_CRYPTO_random_u32 (candidates);
5799 if (0 == (options & RMO_REDUNDANT))
5800 sel2 = candidates; /* picks none! */
5801 else
5802 sel2 = GNUNET_CRYPTO_random_u32 (candidates);
5803 candidates = 0;
5804 for (struct Queue *pos = n->queue_head; NULL != pos;
5805 pos = pos->next_neighbour)
5806 {
5807 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5808 (pos->validated_until.abs_value_us > now.abs_value_us))
5809 {
5810 if ((sel1 == candidates) || (sel2 == candidates))
5811 {
5813 "Routing message of type %u to %s using %s (#%u)\n",
5814 ntohs (hdr->type),
5815 GNUNET_i2s (&n->pid),
5816 pos->address,
5817 (sel1 == candidates) ? 1 : 2);
5818 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5819 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5820 }
5821 candidates++;
5822 }
5823 }
5824 return rtt;
5825}
5826
5827
5838typedef void (*DVMessageHandler) (void *cls,
5839 struct Neighbour *next_hop,
5840 const struct GNUNET_MessageHeader *hdr,
5842
5857static struct GNUNET_TIME_Relative
5859 unsigned int num_dvhs,
5860 struct DistanceVectorHop **dvhs,
5861 const struct GNUNET_MessageHeader *hdr,
5862 DVMessageHandler use,
5863 void *use_cls,
5865 enum GNUNET_GenericReturnValue without_fc)
5866{
5867 const struct GNUNET_PeerIdentity *my_identity;
5868 struct TransportDVBoxMessage box_hdr;
5869 struct TransportDVBoxPayloadP *payload_hdr;
5870 uint16_t body_len_hbo = ntohs (hdr->size);
5871 unsigned char pt[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5873 unsigned char ct[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5875 struct GNUNET_TIME_Relative rtt;
5877
5878 payload_hdr = (struct TransportDVBoxPayloadP*) pt;
5881
5882 /* Encrypt payload */
5883 memset (&box_hdr, 0, sizeof (box_hdr));
5885 box_hdr.total_hops = htons (0);
5886 box_hdr.without_fc = htonl (without_fc);
5887 // update_ephemeral (dv);
5888 if ((0 ==
5889 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5890 || (NULL == dv->km))
5891 {
5892 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5893 &dv->ephemeral_key,
5894 (struct GNUNET_ShortHashCode*) &km);
5895 GNUNET_free (dv->km); /* do not leak the previous key material */
5896 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5897 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5898 if (GNUNET_OK != sign_ephemeral (dv))
5899 {
5900 /* Without a matching signature the box is undecryptable noise to the
5901 receiver; do not spend the bandwidth. Expire the ephemeral so the
5902 next attempt re-derives and re-signs rather than reusing it. */
5903 dv->ephemeral_validity = GNUNET_TIME_UNIT_ZERO_ABS;
5905 }
5906 }
5907 else
5908 {
5909 /* The ephemeral key is still valid, so reuse the cached key material.
5910 Without this @a km stayed UNINITIALISED stack memory and the
5911 receiver could not decrypt the box. */
5912 GNUNET_memcpy (&km, dv->km, sizeof(struct GNUNET_ShortHashCode));
5913 }
5914 box_hdr.ephemeral_key = dv->ephemeral_key;
5915 payload_hdr->sender_sig = dv->sender_sig;
5916 memcpy (&payload_hdr[1], hdr, body_len_hbo);
5918 sizeof(box_hdr.iv));
5919 payload_hdr->sender = *my_identity;
5920 payload_hdr->monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5921 GNUNET_CRYPTO_aead_encrypt (sizeof pt,
5922 pt,
5923 0,
5924 NULL,
5925 &km,
5926 &box_hdr.iv,
5927 ct,
5928 &box_hdr.mac);
5930 /* For each selected path, take the pre-computed header and body
5931 and add the path in the middle of the message; then send it. */
5932 for (unsigned int i = 0; i < num_dvhs; i++)
5933 {
5934 struct DistanceVectorHop *dvh = dvhs[i];
5935 unsigned int num_hops = dvh->distance + 1;
5936 char buf[sizeof(struct TransportDVBoxMessage)
5937 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5938 + sizeof(struct TransportDVBoxPayloadP)
5939 + body_len_hbo] GNUNET_ALIGN;
5940 struct GNUNET_PeerIdentity *dhops;
5941
5942 box_hdr.header.size = htons (sizeof(buf));
5943 box_hdr.orig_size = htons (sizeof(buf));
5944 box_hdr.num_hops = htons (num_hops);
5945 memcpy (buf, &box_hdr, sizeof(box_hdr));
5946 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5947 memcpy (dhops,
5948 dvh->path,
5949 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5950 dhops[dvh->distance] = dv->target;
5951 if (GNUNET_EXTRA_LOGGING > 0)
5952 {
5953 char *path;
5954
5956 for (unsigned int j = 0; j < num_hops; j++)
5957 {
5958 char *tmp;
5959
5960 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5961 GNUNET_free (path);
5962 path = tmp;
5963 }
5965 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5966 ntohs (hdr->type),
5967 GNUNET_i2s (&dv->target),
5968 i + 1,
5969 num_dvhs,
5970 path);
5971 GNUNET_free (path);
5972 }
5973 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5974 memcpy (&dhops[num_hops], ct, sizeof(ct));
5975 use (use_cls,
5976 dvh->next_hop,
5977 (const struct GNUNET_MessageHeader *) buf,
5978 options);
5979 }
5980 return rtt;
5981}
5982
5983
5993static void
5995 struct Neighbour *next_hop,
5996 const struct GNUNET_MessageHeader *hdr,
5998{
5999 (void) cls;
6000 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
6001}
6002
6003
6015static struct GNUNET_TIME_Relative
6017// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
6018 const struct GNUNET_MessageHeader *hdr,
6020{
6021 // struct VirtualLink *vl;
6022 struct Neighbour *n;
6023 struct DistanceVector *dv;
6024 struct GNUNET_TIME_Relative rtt1;
6025 struct GNUNET_TIME_Relative rtt2;
6026 const struct GNUNET_PeerIdentity *target = &vl->target;
6027
6029 "Trying to route message of type %u to %s without fc\n",
6030 ntohs (hdr->type),
6031 GNUNET_i2s (target));
6032
6033 // TODO Do this elsewhere. vl should be given as parameter to method.
6034 // vl = lookup_virtual_link (target);
6035 /* An unconfirmed link is allowed here: it has no @e n and no @e dv of its
6036 own, so the "confirmed required" branch below resolves the route from
6037 #neighbours / #dv_routes. Refusing to route at all is what deadlocks a
6038 pair of peers, see #consider_sending_fc(). */
6039 GNUNET_assert (NULL != vl);
6040 n = vl->n;
6041 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
6042 /* An unconfirmed link has neither @e n nor @e dv of its own, so resolve
6043 the route from #neighbours / #dv_routes. This used to be done only
6044 while #RMO_UNCONFIRMED_ALLOWED was *not* set -- exactly backwards: with
6045 the flag set (the caller that needs it most) we would find no route at
6046 all and drop the message. Whether an unvalidated queue or an
6047 unvalidated path may then be used is still decided by @a options, in
6048 #route_via_neighbour() and #pick_random_dv_hops(). */
6049 if (NULL == n)
6050 n = lookup_neighbour (target);
6051 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
6053 if ((NULL == n) && (NULL == dv))
6054 {
6056 "Cannot route message of type %u to %s: no route\n",
6057 ntohs (hdr->type),
6058 GNUNET_i2s (target));
6060 "# Messages dropped in routing: no acceptable method",
6061 1,
6062 GNUNET_NO);
6064 }
6066 "Routing message of type %u to %s with options %X\n",
6067 ntohs (hdr->type),
6068 GNUNET_i2s (target),
6069 (unsigned int) options);
6070 /* If both dv and n are possible and we must choose:
6071 flip a coin for the choice between the two; for now 50/50 */
6072 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
6073 {
6074 if (0 == GNUNET_CRYPTO_random_u32 (2))
6075 n = NULL;
6076 else
6077 dv = NULL;
6078 }
6079 if ((NULL != n) && (NULL != dv))
6080 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
6081 enough for redundancy, so clear the flag. */
6084 if (NULL != n)
6085 {
6087 "Try to route message of type %u to %s without fc via neighbour\n",
6088 ntohs (hdr->type),
6089 GNUNET_i2s (target));
6090 rtt1 = route_via_neighbour (n, hdr, options);
6091 }
6092 if (NULL != dv)
6093 {
6094 struct DistanceVectorHop *hops[2];
6095 unsigned int res;
6096
6098 options,
6099 hops,
6100 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
6101 if (0 == res)
6102 {
6104 "Failed to route message, could not determine DV path\n");
6105 return rtt1;
6106 }
6108 "encapsulate_for_dv 1\n");
6109 rtt2 = encapsulate_for_dv (dv,
6110 res,
6111 hops,
6112 hdr,
6114 NULL,
6116 GNUNET_YES);
6117 }
6118 return GNUNET_TIME_relative_min (rtt1, rtt2);
6119}
6120
6121
6122static void
6123consider_sending_fc (void *cls);
6124
6131static void
6133{
6134 struct VirtualLink *vl = cls;
6135 vl->fc_retransmit_task = NULL;
6136 consider_sending_fc (cls);
6137}
6138
6139
6140static char *
6141get_address_without_port (const char *address);
6142
6143
6145{
6146 size_t off;
6147
6153 size_t size;
6154
6155 char *tgnas;
6156};
6157
6158
6159static enum GNUNET_GenericReturnValue
6161 const struct GNUNET_PeerIdentity *pid,
6162 void *value)
6163{
6164 struct AddGlobalAddressesContext *ctx = cls;
6165 struct TransportGlobalNattedAddress *tgna = value;
6166 char *addr = (char *) &tgna[1];
6167 size_t alen = ntohl (tgna->address_length);
6168 size_t need = sizeof (struct TransportGlobalNattedAddress) + alen;
6169
6170 /* NOTE: the address is NOT 0-terminated, it must be printed with an
6171 explicit precision. */
6173 "sending address %.*s length %lu\n",
6174 (int) alen,
6175 addr,
6176 (unsigned long) alen);
6177 if (ctx->off + need > ctx->size)
6178 {
6179 GNUNET_break (0);
6180 return GNUNET_NO;
6181 }
6182 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, need);
6183 ctx->off += need;
6184
6185 return GNUNET_OK;
6186}
6187
6188
6189static struct GNUNET_TIME_Relative
6190calculate_rtt (struct DistanceVector *dv);
6191
6192
6199static void
6201{
6202 struct VirtualLink *vl = cls;
6203 struct GNUNET_TIME_Absolute monotime;
6204 struct TransportFlowControlMessage *fc;
6206 struct GNUNET_TIME_Relative rtt;
6207 struct GNUNET_TIME_Relative rtt_average;
6208 struct Neighbour *n = vl->n;
6209 size_t addresses_size;
6210
6211 /* Most of our callers are not the retransmit task but inbound events:
6212 handle_flow_control() ends in check_vl_transmission(), which calls us
6213 once per flow-control-stalled message, and the peer's answer to what we
6214 send here arrives as another handle_flow_control(). On a link whose
6215 head message does not fit the window that is a ping-pong with nothing
6216 to damp it -- the backoff and the MIN_FC_RETRANSMIT_DELAY floor at the
6217 bottom of this function only ever governed @e fc_retransmit_task, which
6218 these callers bypass. If the chain is armed and we just sent one, let
6219 the task do it. */
6220 if ((NULL != vl->fc_retransmit_task) &&
6222 < MIN_FC_RETRANSMIT_DELAY.rel_value_us))
6223 {
6225 "Not sending FC to %s: one went out less than %s ago\n",
6226 GNUNET_i2s (&vl->target),
6229 GNUNET_YES));
6230 return;
6231 }
6232 if ((GNUNET_YES != vl->confirmed) &&
6233 (NULL == lookup_neighbour (&vl->target)) &&
6235 {
6236 /* Unconfirmed AND no way to reach the peer at all -- nothing to send on.
6237 An unconfirmed link that *does* have a route must still answer,
6238 see below.
6239
6240 Do NOT just return: #task_consider_sending_fc() cleared
6241 @e fc_retransmit_task before calling us, and the only other place that
6242 arms it is #handle_flow_control() -- which only does so when it is
6243 already non-NULL. Leaving without re-arming therefore ends the
6244 keepalive chain for this link permanently, and #check_link_down()
6245 tears it down #NEIGHBOUR_LIVENESS_TIMEOUT later. */
6247 "Not sending FC to %s: link unconfirmed and no route\n",
6248 GNUNET_i2s (&vl->target));
6249 if (NULL == vl->fc_retransmit_task)
6253 vl);
6254 return;
6255 }
6256 addresses_size = 0;
6257 if (NULL != n && 0 < n->number_of_addresses)
6258 {
6259 addresses_size =
6260 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
6261 ->size_of_global_addresses;
6262 if (addresses_size >
6263 UINT16_MAX - sizeof (struct TransportFlowControlMessage))
6264 {
6265 /* htons() below would silently truncate `header.size', leaving a
6266 message whose declared length does not match its contents. */
6267 GNUNET_break (0);
6268 addresses_size = 0;
6269 }
6270 }
6271 if (0 != addresses_size)
6272 {
6273 char *tgnas = GNUNET_malloc (addresses_size);
6275 ctx.off = 0;
6276 ctx.size = addresses_size;
6277 ctx.tgnas = tgnas;
6278
6280 + addresses_size);
6281 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
6282 + addresses_size);
6283 fc->size_of_addresses = htonl ((uint32_t) n->size_of_global_addresses);
6284 fc->number_of_addresses = htonl (n->number_of_addresses);
6287 &ctx);
6290 }
6291 else
6292 {
6293 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
6294 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
6295 }
6296
6298 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
6299 it always! */
6300 /* For example, we should probably ONLY do this if a bit more than
6301 an RTT has passed, or if the window changed "significantly" since
6302 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
6303 need an estimate for the bandwidth-delay-product for the entire
6304 VL, as that determines "significantly". We have the delay, but
6305 the bandwidth statistics need to be added for the VL!*/(void) duration;
6306
6307 if (NULL != vl->dv)
6308 rtt_average = calculate_rtt (vl->dv);
6309 else
6310 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
6311 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
6313 "Sending FC seq %u to %s with new window %llu %lu %u\n",
6314 (unsigned int) vl->fc_seq_gen,
6315 GNUNET_i2s (&vl->target),
6316 (unsigned long long) vl->incoming_fc_window_size,
6317 (unsigned long) rtt_average.rel_value_us,
6318 vl->sync_ready);
6320 vl->last_fc_transmission = monotime;
6321 fc->sync_ready = htonl ((uint32_t) vl->sync_ready);
6323 fc->seq = htonl (vl->fc_seq_gen++);
6324 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
6327 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
6328 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
6329 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
6330 /* On an unconfirmed link the only queues and paths we have are, by
6331 definition, unvalidated ones -- that is what "unconfirmed" means.
6332 Requiring a validated route here is what deadlocks the pair: the peer
6333 has a confirmed link to us and flow-controls us, we cannot answer, so
6334 its @e outbound_fc_window_size stays at zero and it cannot send us a
6335 single byte -- not its CORE handshake, not DHT traffic -- while its
6336 `gnunet-transport' shows an established link with messages pending
6337 forever. It reached us over that queue, so answering on it is sound. */
6339 &fc->header,
6340 (GNUNET_YES == vl->confirmed)
6343 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
6344 {
6347 "FC retransmission to %s failed, will retry in %s\n",
6348 GNUNET_i2s (&vl->target),
6351 }
6352 else
6353 {
6354 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
6355 vl->last_fc_rtt = rtt;
6356 }
6357 if (NULL != vl->fc_retransmit_task)
6359 /* Never re-arm with (near) zero delay: @a rtt is zero whenever we have no
6360 RTT sample yet, which turned this into a tight send loop. */
6362 {
6363 /* Back off while the peer stays silent. Retransmitting at the plain RTT
6364 for #MAX_FC_RETRANSMIT_COUNT rounds is a flood on a link that is not
6365 being answered -- and a peer that cannot answer keeps *every* one of
6366 its links in exactly that state, which is enough traffic to make
6367 transport fall behind its communicators. */
6369
6370 for (unsigned int i = 0;
6371 (i < vl->fc_retransmit_count) && (rtt.rel_value_us < cap.rel_value_us);
6372 i++)
6373 rtt = GNUNET_TIME_relative_multiply (rtt, 2);
6374 rtt = GNUNET_TIME_relative_min (rtt, cap);
6375 }
6376 vl->fc_retransmit_task =
6379 vl->fc_retransmit_count++;
6380 GNUNET_free (fc);
6381}
6382
6383
6400static void
6402{
6403 struct Neighbour *n = vl->n;
6404 struct DistanceVector *dv = vl->dv;
6405 struct GNUNET_TIME_Absolute now;
6406 struct VirtualLink *vl_next_hop;
6407 int elig;
6408
6410 "check_vl_transmission to target %s\n",
6411 GNUNET_i2s (&vl->target));
6412 /* Check that we have an eligible pending message!
6413 (cheaper than having #transmit_on_queue() find out!) */
6414 elig = GNUNET_NO;
6415 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
6416 pm = pm->next_vl)
6417 {
6419 "check_vl_transmission loop\n");
6420 if (NULL != pm->qe)
6421 continue; /* not eligible, is in a queue! */
6422 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
6424 {
6426 "Stalled message %" PRIu64
6427 " transmission on VL %s due to flow control: %llu < %llu\n",
6428 pm->logging_uuid,
6429 GNUNET_i2s (&vl->target),
6430 (unsigned long long) vl->outbound_fc_window_size,
6431 (unsigned long long) (pm->bytes_msg
6434 return; /* We have a message, but flow control says "nope" */
6435 }
6437 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
6438 GNUNET_i2s (&vl->target));
6439 /* Notify queues at direct neighbours that we are interested */
6440 now = GNUNET_TIME_absolute_get ();
6441 if (NULL != n)
6442 {
6443 for (struct Queue *queue = n->queue_head; NULL != queue;
6444 queue = queue->next_neighbour)
6445 {
6446 if ((GNUNET_YES == queue->idle) &&
6447 (queue->validated_until.abs_value_us > now.abs_value_us))
6448 {
6450 "Direct neighbour %s not stalled\n",
6451 GNUNET_i2s (&n->pid));
6453 queue,
6455 elig = GNUNET_YES;
6456 }
6457 else
6459 "Neighbour Queue QID: %u (%u) busy or invalid\n",
6460 queue->qid,
6461 queue->idle);
6462 }
6463 }
6464 /* Notify queues via DV that we are interested */
6465 if (NULL != dv)
6466 {
6467 /* Do DV with lower scheduler priority, which effectively means that
6468 IF a neighbour exists and is available, we prefer it. */
6469 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6470 pos = pos->next_dv)
6471 {
6472 struct Neighbour *nh_iter = pos->next_hop;
6473
6474
6475 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
6476 continue; /* skip this one: path not validated */
6477 else
6478 {
6479 /* The next hop is a neighbour we have queues to; it need not have
6480 a virtual link of its own, and then there is no window of it to
6481 respect either. */
6482 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
6483 if ((NULL != vl_next_hop) &&
6484 (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
6485 vl_next_hop->outbound_fc_window_size))
6486 {
6488 "Stalled message %" PRIu64
6489 " transmission on next hop %s due to flow control: %llu < %llu\n",
6490 pm->logging_uuid,
6491 GNUNET_i2s (&vl_next_hop->target),
6492 (unsigned long
6493 long) vl_next_hop->outbound_fc_window_size,
6494 (unsigned long long) (pm->bytes_msg
6495 + vl_next_hop->
6496 outbound_fc_window_size_used));
6497 consider_sending_fc (vl_next_hop);
6498 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
6499 }
6500 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
6501 queue = queue->next_neighbour)
6502 if ((GNUNET_YES == queue->idle) &&
6503 (queue->validated_until.abs_value_us > now.abs_value_us))
6504 {
6506 "Next hop neighbour %s not stalled\n",
6507 GNUNET_i2s (&nh_iter->pid));
6509 queue,
6511 elig = GNUNET_YES;
6512 }
6513 else
6515 "DV Queue QID: %u (%u) busy or invalid\n",
6516 queue->qid,
6517 queue->idle);
6518 }
6519 }
6520 }
6521 if (GNUNET_YES == elig)
6523 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
6524 pm->logging_uuid,
6525 pm->bytes_msg,
6526 GNUNET_i2s (&vl->target),
6527 (unsigned long long) vl->outbound_fc_window_size,
6528 (unsigned long long) (pm->bytes_msg
6530 break;
6531 }
6532}
6533
6534
6541static void
6542handle_client_send (void *cls, const struct OutboundMessage *obm)
6543{
6544 struct TransportClient *tc = cls;
6545 struct PendingMessage *pm;
6546 const struct GNUNET_MessageHeader *obmm;
6547 uint32_t bytes_msg;
6548 struct VirtualLink *vl;
6550
6551 GNUNET_assert (CT_CORE == tc->type);
6552 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
6553 bytes_msg = ntohs (obmm->size);
6554 pp = ntohl (obm->priority);
6555 vl = lookup_virtual_link (&obm->peer);
6556 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6557 {
6559 "Don't have %s as a neighbour (anymore).\n",
6560 GNUNET_i2s (&obm->peer));
6561 /* Failure: don't have this peer as a neighbour (anymore).
6562 Might have gone down asynchronously, so this is NOT
6563 a protocol violation by CORE. Still count the event,
6564 as this should be rare. */
6565 /* Precisely because this is not a protocol violation we leave the
6566 client's `struct Neighbour' -- and its send window -- in place, so we
6567 owe it the SEND_OK for the message we are dropping here. Without it
6568 the window shrinks by one every time this happens and never grows
6569 back; after #SEND_WINDOW_SIZE such drops #mq_send_impl() parks every
6570 further message for this peer forever ("Flow control delays
6571 transmission to CORE until we see SEND_OK") and CORE goes mute
6572 towards a peer it still believes it is connected to -- while
6573 continuing to receive from it, so its own idle timeout is what
6574 eventually reports the peer down. */
6575 send_ok_to_client (tc, &obm->peer);
6578 "# messages dropped (neighbour unknown)",
6579 1,
6580 GNUNET_NO);
6581 return;
6582 }
6583
6584 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
6586 "1 created pm %p storing vl %p\n",
6587 pm,
6588 vl);
6590 pm->prefs = pp;
6591 pm->client = tc;
6592 pm->vl = vl;
6593 pm->bytes_msg = bytes_msg;
6594 memcpy (&pm[1], obmm, bytes_msg);
6596 "Sending message of type %u with %u bytes as <%" PRIu64
6597 "> to %s\n",
6598 ntohs (obmm->type),
6599 bytes_msg,
6600 pm->logging_uuid,
6601 GNUNET_i2s (&obm->peer));
6603 tc->details.core.pending_msg_head,
6604 tc->details.core.pending_msg_tail,
6605 pm);
6607 vl->pending_msg_head,
6608 vl->pending_msg_tail,
6609 pm);
6612}
6613
6614
6624static void
6626 void *cls,
6628{
6629 struct Neighbour *n;
6630 struct VirtualLink *vl;
6631 struct TransportClient *tc = cls;
6632 const struct GNUNET_MessageHeader *inbox =
6633 (const struct GNUNET_MessageHeader *) &cb[1];
6634 uint16_t isize = ntohs (inbox->size);
6635 const char *is = ((const char *) &cb[1]) + isize;
6636 size_t slen = strlen (is) + 1;
6637 char
6638 mbuf[slen + isize
6639 + sizeof(struct
6643
6644 /* 0-termination of 'is' was checked already in
6645 #check_communicator_backchannel() */
6647 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
6648 GNUNET_i2s (&cb->pid),
6649 is,
6650 ntohs (inbox->type),
6651 ntohs (inbox->size));
6652 /* encapsulate and encrypt message */
6653 be->header.type =
6655 be->header.size = htons (sizeof(mbuf));
6656 memcpy (&be[1], inbox, isize);
6657 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
6658 + isize],
6659 is,
6660 strlen (is) + 1);
6661 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
6662 vl = lookup_virtual_link (&cb->pid);
6663 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6664 {
6666 }
6667 else
6668 {
6669 /* Use route via neighbour */
6670 n = lookup_neighbour (&cb->pid);
6671 if (NULL != n)
6673 n,
6674 &be->header,
6675 RMO_NONE);
6676 }
6678}
6679
6680
6688static int
6690 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6691{
6692 struct TransportClient *tc = cls;
6693
6694 if (CT_COMMUNICATOR != tc->type)
6695 {
6696 GNUNET_break (0);
6697 return GNUNET_SYSERR;
6698 }
6700 return GNUNET_OK;
6701}
6702
6703
6709static void
6710store_pi (void *cls);
6711
6712
6717{
6718
6723
6728
6729
6734};
6735
6736
6743static void
6745{
6746 struct PilsAddressSignContext *pc = ale->pc;
6747
6748 if (NULL == pc)
6749 return;
6750 ale->pc = NULL;
6751 /* Each stage of the chain passes @a pc as its closure, so every handle
6752 that could still deliver one has to go before @a pc is released. */
6753 if (NULL != ale->sc)
6754 {
6756 ale->sc = NULL;
6757 }
6758 if (NULL != ale->shc)
6759 {
6761 ale->shc = NULL;
6762 }
6763 if (NULL != pc->req)
6764 {
6765 if (NULL != pc->req->op)
6766 GNUNET_PILS_cancel (pc->req->op);
6769 pc->req);
6770 GNUNET_free (pc->req);
6771 pc->req = NULL;
6772 }
6773 GNUNET_free (pc);
6774}
6775
6776
6777static void
6778shc_cont (void *cls, int success)
6779{
6780 struct PilsAddressSignContext *pc = cls;
6781
6782 GNUNET_assert (NULL == pc->req);
6783 /* The store completed; the handle is dead and must not be cancelled
6784 later by #free_address_list_entry(). */
6785 pc->ale->shc = NULL;
6786 pc->ale->pc = NULL;
6787 if (GNUNET_OK != success)
6788 {
6790 "Failed to store our address `%s' with peerstore\n",
6791 pc->ale->address);
6792 if (NULL == pc->ale->st)
6793 {
6795 &store_pi,
6796 pc->ale);
6797 }
6798 }
6799 GNUNET_free (pc);
6800}
6801
6802
6806static void
6808 const struct GNUNET_PeerIdentity *pid,
6809 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6810{
6811 struct PilsAddressSignContext *pc = cls;
6812 struct GNUNET_MQ_Envelope *env;
6813 const struct GNUNET_MessageHeader *msg;
6814
6815 pc->req->op = NULL;
6818 pc->req);
6819 GNUNET_free (pc->req);
6820 pc->req = NULL;
6823 pid,
6824 sig,
6825 pc->et);
6828 "store_pi 1\n");
6830 msg,
6831 shc_cont,
6832 pc);
6833 GNUNET_free (env);
6834}
6835
6836
6843static void
6844peerstore_store_own_cb (void *cls, int success)
6845{
6846 struct PilsAddressSignContext *pc = cls;
6847
6848 pc->ale->sc = NULL;
6849 if (GNUNET_YES != success)
6851 "Failed to store our own address `%s' in peerstore!\n",
6852 pc->ale->address);
6853 else
6855 "Successfully stored our own address `%s' in peerstore!\n",
6856 pc->ale->address);
6857 /* refresh period is 1/4 of expiration time, that should be plenty
6858 without being excessive. */
6859 if (NULL == pc->ale->st)
6860 {
6861 /* @e expiration comes straight off the wire in ADD_ADDRESS and is not
6862 validated anywhere, so a communicator reporting a very short (or
6863 zero) lifetime would have us re-sign the HELLO and store it again on
6864 the next scheduler pass, forever. That is an EdDSA signature and a
6865 PEERSTORE round trip per iteration. */
6866 pc->ale->st =
6870 GNUNET_TIME_relative_divide (pc->ale->expiration,
6871 4ULL)),
6872 &store_pi,
6873 pc->ale);
6874 }
6875
6876 /* Now we have to update our HELLO! */
6878 pc->req = GNUNET_new (struct PilsRequest);
6881 pc->req);
6882 pc->req->op = GNUNET_PILS_sign_hello (pils,
6884 pc->et,
6886 pc);
6887}
6888
6889
6897static void
6899 const struct GNUNET_PeerIdentity *pid,
6900 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6901{
6902 char *sig_str;
6903 void *result;
6904 size_t result_size;
6905
6906 sig_str = NULL;
6907 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6908 result_size =
6909 1 + GNUNET_asprintf (
6910 (char **) &result,
6911 "%s;%llu;%u;%s",
6912 sig_str,
6913 (unsigned long long) pc->et.abs_value_us,
6914 (unsigned int) pc->ale->nt,
6915 pc->ale->address);
6916 GNUNET_free (sig_str);
6917
6919 "Build our HELLO URI `%s'\n",
6920 (char*) result);
6921
6922 GNUNET_free (pc->ale->signed_address);
6923 pc->ale->signed_address = result;
6924 pc->ale->signed_address_len = result_size;
6926
6927 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6929 "transport",
6930 pid,
6932 result,
6933 result_size,
6934 expiration,
6937 pc);
6938}
6939
6940
6961
6962
6976void
6978 struct AddressListEntry *ale,
6979 struct GNUNET_TIME_Absolute mono_time)
6980{
6981 struct SignedAddress sa;
6982 struct PilsAddressSignContext *pc;
6984 const struct GNUNET_PeerIdentity *my_identity;
6985
6987 sa.purpose.size = htonl (sizeof(sa));
6988 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6989 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6990 /* Only ever one chain per entry: the previous one (if any) still holds a
6991 pointer to @a ale and must be torn down first. */
6994 if ((NULL == my_identity) ||
6995 (GNUNET_OK != sign_by_my_identity (&sa.purpose, &sig)))
6996 {
6997 /* Nothing else re-arms @e st: #store_pi() cleared it before calling us,
6998 and the only other thing that sets it is #peerstore_store_own_cb(),
6999 which is on the far side of the store we just failed to start. So a
7000 single failure to sign used to end the refresh cycle for this address
7001 for the rest of the process' life. */
7002 if (NULL == ale->st)
7003 {
7006 &store_pi,
7007 ale);
7008 }
7009 return;
7010 }
7012 pc->ale = ale;
7013 pc->et = mono_time;
7014 ale->pc = pc;
7016}
7017
7018
7024static void
7025store_pi (void *cls)
7026{
7027 struct AddressListEntry *ale = cls;
7028 const char *dash;
7029 char *address_uri;
7030 char *prefix;
7031 unsigned int add_success;
7032
7033 if ((GNUNET_YES == in_shutdown) || (NULL == pils))
7034 {
7035 ale->st = NULL;
7036 return;
7037 }
7038 if (NULL == GNUNET_PILS_get_identity (pils))
7039 {
7040 /* Do NOT poll at 1kHz: that burns CPU and keeps the scheduler task
7041 list non-empty, which prevents the service from ever exiting. */
7044 &store_pi,
7045 ale);
7046 return;
7047 }
7050 dash = strchr (ale->address, '-');
7051 GNUNET_assert (NULL != dash);
7052 dash++;
7053 GNUNET_asprintf (&address_uri,
7054 "%s://%s",
7055 prefix,
7056 dash);
7058 ale->st = NULL;
7060 "Storing our address `%s' in peerstore until %s!\n",
7061 ale->address,
7064 address_uri);
7065 /* NOTE: #GNUNET_HELLO_builder_add_address() answers GNUNET_NO for an
7066 address that is already in the builder, and on every call after the
7067 first one for a given address that is exactly what happens: nothing
7068 ever removes an address from @a GST_my_hello except
7069 #handle_del_address(). This function is the *refresh* cycle --
7070 #peerstore_store_own_cb() re-arms it at a quarter of the address'
7071 expiration -- so bailing out on GNUNET_NO here stopped the refresh
7072 after precisely one round. Our own HELLO then expired
7073 (#GNUNET_HELLO_ADDRESS_EXPIRATION, twelve hours) and was never
7074 renewed: peers can no longer learn how to reach us, and a link that
7075 drops after that never comes back. Only GNUNET_SYSERR -- a malformed
7076 URI, which retrying cannot fix -- is a reason not to store. */
7077 if (GNUNET_SYSERR == add_success)
7078 {
7080 "Not storing our address `%s': not a valid HELLO URI\n",
7081 address_uri);
7082 GNUNET_free (address_uri);
7083 return;
7084 }
7085 GNUNET_log ((GNUNET_NO == add_success) ?
7087 "%s our address `%s' in PEERSTORE\n",
7088 (GNUNET_NO == add_success) ? "Refreshing" : "Storing",
7089 address_uri);
7090 // FIXME hello_mono_time used here?? What about expiration in ale?
7091 pils_sign_address (ale,
7093 // TODO keep track of op and potentially cancel/clean
7094 GNUNET_free (address_uri);
7095}
7096
7097
7098static struct AddressListEntry *
7102 const char *address,
7103 uint32_t aid,
7104 size_t slen)
7105{
7106 struct AddressListEntry *ale;
7107 char *address_without_port;
7108
7109 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
7110 ale->tc = tc;
7111 ale->address = (const char *) &ale[1];
7112 ale->expiration = expiration;
7113 ale->aid = aid;
7114 ale->nt = nt;
7115 memcpy (&ale[1], address, slen);
7116 address_without_port = get_address_without_port (ale->address);
7118 "Is this %s a local address (%s)\n",
7119 (NULL == address_without_port) ? "<unparsable>"
7120 : address_without_port,
7121 ale->address);
7122 if ((NULL == address_without_port) ||
7123 (0 != strcmp ("127.0.0.1", address_without_port)))
7124 {
7125 if (NULL != ale->st)
7126 {
7128 }
7129 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
7130 }
7131 GNUNET_free (address_without_port);
7132
7133 return ale;
7134}
7135
7136
7137static void
7139{
7140
7142 "Feeding addresses to PILS\n");
7143 pils_feed_task = NULL;
7144
7146 GST_my_hello);
7147}
7148
7149
7156static void
7158 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
7159{
7160 struct TransportClient *tc = cls;
7161 struct AddressListEntry *ale;
7162 size_t slen;
7163 char *address;
7164
7165 /* 0-termination of &aam[1] was checked in #check_add_address */
7167 "Communicator added address `%s'!\n",
7168 (const char *) &aam[1]);
7169 slen = ntohs (aam->header.size) - sizeof(*aam);
7170 address = GNUNET_malloc (slen);
7171 memcpy (address, &aam[1], slen);
7172 ale = create_address_entry (tc,
7174 ntohl (aam->nt),
7175 address,
7176 aam->aid,
7177 slen);
7178 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
7179 tc->details.communicator.addr_tail,
7180 ale);
7181 {
7182 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
7183 NULL != iter;
7184 iter = iter->next)
7185 {
7186 char *address_uri;
7187 const char *dash = strchr (iter->address, '-');
7188 char *prefix = GNUNET_HELLO_address_to_prefix (iter->address);
7189 GNUNET_assert (NULL != dash);
7190 dash++;
7191 GNUNET_asprintf (&address_uri,
7192 "%s://%s",
7193 prefix,
7194 dash);
7197 GNUNET_free (address_uri);
7198 }
7199 if (NULL != pils_feed_task)
7203 NULL);
7204 }
7207}
7208
7209
7216static void
7218 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
7219{
7220 struct TransportClient *tc = cls;
7221 struct AddressListEntry *alen;
7222
7223 if (CT_COMMUNICATOR != tc->type)
7224 {
7225 GNUNET_break (0);
7227 return;
7228 }
7229 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
7230 NULL != ale;
7231 ale = alen)
7232 {
7233 alen = ale->next;
7234 if (dam->aid != ale->aid)
7235 continue;
7236 GNUNET_assert (ale->tc == tc);
7238 "Communicator deleted address `%s'!\n",
7239 ale->address);
7241 ale->address);
7242 if (NULL != pils_feed_task)
7246 NULL);
7249 return;
7250 }
7252 "Communicator removed address we did not even have.\n");
7254 // GNUNET_SERVICE_client_drop (tc->client);
7255}
7256
7257
7265static void
7267
7268
7276static void
7278{
7279 struct CoreSentContext *ctx = cls;
7280 struct VirtualLink *vl = ctx->vl;
7281
7282 if (NULL == vl)
7283 {
7284 /* lost the link in the meantime, ignore */
7285 GNUNET_free (ctx);
7286 return;
7287 }
7290 vl->incoming_fc_window_size_ram -= ctx->size;
7291 vl->incoming_fc_window_size_used += ctx->isize;
7293 GNUNET_free (ctx);
7294}
7295
7296
7318static void
7320{
7321 struct VirtualLink *vl = cls;
7322 struct CommunicatorMessageContext *cmc;
7323
7324 vl->core_fc_stall_task = NULL;
7326 "CORE did not acknowledge messages from %s within %s; "
7327 "releasing the flow control credit anyway\n",
7328 GNUNET_i2s (&vl->target),
7330 GNUNET_YES));
7332 "# CORE flow control stalls",
7333 1,
7334 GNUNET_NO);
7335 while (NULL != (cmc = vl->cmc_tail))
7336 release_stalled_cmc (vl, cmc);
7339}
7340
7341
7342static void
7344 const struct GNUNET_MessageHeader *mh,
7345 struct CommunicatorMessageContext *cmc,
7346 unsigned int free_cmc)
7347{
7348 uint16_t size = ntohs (mh->size);
7349 int have_core;
7350
7351 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
7352 {
7354 "# CORE messages dropped (FC arithmetic overflow)",
7355 1,
7356 GNUNET_NO);
7358 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
7359 (unsigned int) ntohs (mh->type),
7360 (unsigned int) ntohs (mh->size));
7361 if (GNUNET_YES == free_cmc)
7363 return;
7364 }
7366 {
7368 "# CORE messages dropped (FC window overflow)",
7369 1,
7370 GNUNET_NO);
7372 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
7373 (unsigned int) ntohs (mh->type),
7374 (unsigned int) ntohs (mh->size));
7375 if (GNUNET_YES == free_cmc)
7377 return;
7378 }
7379
7380 /* Forward to all CORE clients */
7381 have_core = GNUNET_NO;
7382 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
7383 {
7384 struct GNUNET_MQ_Envelope *env;
7385 struct InboundMessage *im;
7386 struct CoreSentContext *ctx;
7387
7388 if (CT_CORE != tc->type)
7389 continue;
7392 ctx = GNUNET_new (struct CoreSentContext);
7393 ctx->vl = vl;
7394 ctx->size = size;
7395 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
7396 have_core = GNUNET_YES;
7399 im->peer = cmc->im.sender;
7400 memcpy (&im[1], mh, size);
7401 GNUNET_MQ_send (tc->mq, env);
7403 }
7404 if (GNUNET_NO == have_core)
7405 {
7407 "Dropped message to CORE: no CORE client connected!\n");
7408 /* Nevertheless, count window as used, as it is from the
7409 perspective of the other peer! */
7411 /* TODO-M1 */
7413 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
7414 (unsigned int) ntohs (mh->type),
7415 (unsigned int) ntohs (mh->size));
7416 if (GNUNET_YES == free_cmc)
7418 return;
7419 }
7421 "Delivered message from %s of type %u to CORE recv window %d\n",
7422 GNUNET_i2s (&cmc->im.sender),
7423 ntohs (mh->type),
7425 if (vl->core_recv_window > 0)
7426 {
7427 if (GNUNET_YES == free_cmc)
7429 return;
7430 }
7431 /* CORE ran out of receive window for *this* link. Withhold the
7432 per-message ACK -- that is what expresses the backpressure -- but
7433 resume the client immediately. The client is the communicator
7434 *process*, which carries every peer we reach through it, and a
7435 communicator we stop reading from does not stop receiving: it starts
7436 discarding, see "transport is too slow" in
7437 #GNUNET_TRANSPORT_communicator_receive(). Discarding is precisely
7438 what we cannot afford here, because among the messages dropped are
7439 the ones CORE needs in order to reopen the window it is waiting on. */
7440 if (GNUNET_YES == free_cmc)
7441 {
7442 resume_cmc_client (cmc);
7444 vl->cmc_count++;
7445 /* Nothing stalls the producer any more, so bound the list ourselves. */
7446 while (MAX_STALLED_CMCS < vl->cmc_count)
7448 /* ... and do not withhold the ACKs forever: see #core_fc_stalled(). */
7449 if (NULL == vl->core_fc_stall_task)
7453 vl);
7454 }
7455}
7456
7457
7466static void
7468{
7469 struct CommunicatorMessageContext *cmc = cls;
7470 // struct CommunicatorMessageContext *cmc_copy =
7471 // GNUNET_new (struct CommunicatorMessageContext);
7472 struct GNUNET_MessageHeader *mh_copy;
7473 struct RingBufferEntry *rbe;
7474 struct VirtualLink *vl;
7475 uint16_t size = ntohs (mh->size);
7476
7478 "Handling raw message of type %u with %u bytes\n",
7479 (unsigned int) ntohs (mh->type),
7480 (unsigned int) ntohs (mh->size));
7481
7482 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
7483 (size < sizeof(struct GNUNET_MessageHeader)))
7484 {
7485 /* @a mh was unwrapped from what a *remote peer* sent us, so a bad size
7486 is that peer's protocol violation and says nothing about the
7487 communicator that carried it. Dropping the client here disconnects
7488 the communicator process and with it every neighbour reachable
7489 through it -- see the rationale in #demultiplex_with_cmc(). */
7490 GNUNET_break_op (0);
7492 "# CORE messages dropped (bad size)",
7493 1,
7494 GNUNET_NO);
7495 finish_cmc_handling (cmc);
7496 return;
7497 }
7498 vl = lookup_virtual_link (&cmc->im.sender);
7499 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
7500 {
7501 /* FIXME: sender is giving us messages for CORE but we don't have
7502 the link up yet! I *suspect* this can happen right now (i.e.
7503 sender has verified us, but we didn't verify sender), but if
7504 we pass this on, CORE would be confused (link down, messages
7505 arrive). We should investigate more if this happens often,
7506 or in a persistent manner, and possibly do "something" about
7507 it. Thus logging as error for now. */
7508
7509 mh_copy = GNUNET_malloc (size);
7510 rbe = GNUNET_new (struct RingBufferEntry);
7511 rbe->cmc = cmc;
7512 /*cmc_copy->tc = cmc->tc;
7513 cmc_copy->im = cmc->im;*/
7514 GNUNET_memcpy (mh_copy, mh, size);
7515
7516 rbe->mh = mh_copy;
7517
7519 {
7520 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
7521 GNUNET_free (rbe_old->cmc);
7522 GNUNET_free (rbe_old->mh);
7523 GNUNET_free (rbe_old);
7524 }
7525 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
7526 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
7527 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
7529 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
7530 GNUNET_i2s (&cmc->im.sender),
7531 (unsigned int) ntohs (mh->type),
7532 (unsigned int) ntohs (mh_copy->type),
7536 {
7537 ring_buffer_head = 0;
7539 }
7540 else
7542
7544 "%u items stored in ring buffer\n",
7547
7548 /*GNUNET_break_op (0);
7549 GNUNET_STATISTICS_update (GST_stats,
7550 "# CORE messages dropped (virtual link still down)",
7551 1,
7552 GNUNET_NO);
7553
7554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7555 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
7556 (unsigned int) ntohs (mh->type),
7557 (unsigned int) ntohs (mh->size));
7558 finish_cmc_handling (cmc);*/
7559 /* @a cmc lives on in the ring buffer; #send_cmc_ack() and
7560 #resume_cmc_client() have recorded that they ran, so replaying it
7561 from #send_msg_from_cache() cannot ACK or continue a second time. */
7563 return;
7564 }
7566}
7567
7568
7576static int
7578{
7579 uint16_t size = ntohs (fb->header.size);
7580 uint16_t bsize = size - sizeof(*fb);
7581
7582 (void) cls;
7583 if (0 == bsize)
7584 {
7585 GNUNET_break_op (0);
7586 return GNUNET_SYSERR;
7587 }
7588 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
7589 {
7590 GNUNET_break_op (0);
7591 return GNUNET_SYSERR;
7592 }
7593 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
7594 {
7595 GNUNET_break_op (0);
7596 return GNUNET_SYSERR;
7597 }
7598 return GNUNET_YES;
7599}
7600
7601
7607static void
7609{
7610 struct AcknowledgementCummulator *ac = cls;
7611
7612 ac->task = NULL;
7613 GNUNET_assert (0 == ac->num_acks);
7615 GNUNET_YES ==
7617 GNUNET_free (ac);
7618}
7619
7620
7626static void
7628{
7629 struct Neighbour *n;
7630 struct VirtualLink *vl;
7631 struct AcknowledgementCummulator *ac = cls;
7632 char buf[sizeof(struct TransportReliabilityAckMessage)
7633 + ac->num_acks
7635 struct TransportReliabilityAckMessage *ack =
7636 (struct TransportReliabilityAckMessage *) buf;
7638
7639 ac->task = NULL;
7641 "Sending ACK with %u components to %s\n",
7642 ac->num_acks,
7643 GNUNET_i2s (&ac->target));
7644 GNUNET_assert (0 < ac->num_acks);
7646 ack->header.size =
7647 htons (sizeof(*ack)
7648 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
7649 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
7650 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
7651 for (unsigned int i = 0; i < ac->num_acks; i++)
7652 {
7653 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
7656 }
7657 /*route_control_message_without_fc (
7658 &ac->target,
7659 &ack->header,
7660 RMO_DV_ALLOWED);*/
7661 vl = lookup_virtual_link (&ac->target);
7662 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7663 {
7665 vl,
7666 &ack->header,
7668 }
7669 else
7670 {
7671 /* Use route via neighbour */
7672 n = lookup_neighbour (&ac->target);
7673 if (NULL != n)
7675 n,
7676 &ack->header,
7677 RMO_NONE);
7678 }
7679 ac->num_acks = 0;
7680 /* The deadline belonged to the batch we just sent. #cummulative_ack()
7681 only ever lowers it (GNUNET_TIME_absolute_min), so leaving it behind
7682 means every later ACK is armed with GNUNET_SCHEDULER_add_at() on a time
7683 that has already passed: the task fires on the next scheduler pass and
7684 the batching this whole structure exists for is gone for good -- one
7685 ACK message per received message, for the rest of the process' life. */
7689 ac);
7690}
7691
7692
7701static void
7703 const struct AcknowledgementUUIDP *ack_uuid,
7704 struct GNUNET_TIME_Absolute max_delay)
7705{
7706 struct AcknowledgementCummulator *ac;
7707
7709 "Scheduling ACK %s for transmission to %s\n",
7710 GNUNET_uuid2s (&ack_uuid->value),
7711 GNUNET_i2s (pid));
7713 if (NULL == ac)
7714 {
7716 ac->target = *pid;
7717 ac->min_transmission_time = max_delay;
7721 &ac->target,
7722 ac,
7724 }
7725 else
7726 {
7727 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
7728 {
7729 /* Must run immediately, ack buffer full. Cancel the pending task
7730 FIRST: #transmit_cummulative_ack_cb() clears @e task without
7731 cancelling it, which would leave the old task armed with its
7732 handle lost. */
7734 ac->task = NULL;
7736 }
7740 }
7743 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
7744 ac->num_acks++;
7747 ac);
7748}
7749
7750
7766
7767
7777static int
7778find_by_message_uuid (void *cls, uint32_t key, void *value)
7779{
7780 struct FindByMessageUuidContext *fc = cls;
7781 struct ReassemblyContext *rc = value;
7782
7783 (void) key;
7784 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
7785 {
7786 fc->rc = rc;
7787 return GNUNET_NO;
7788 }
7789 return GNUNET_YES;
7790}
7791
7792
7800static void
7802{
7803 struct CommunicatorMessageContext *cmc = cls;
7804 struct VirtualLink *vl;
7805 struct ReassemblyContext *rc;
7806 const struct GNUNET_MessageHeader *msg;
7807 uint16_t msize;
7808 uint16_t fsize;
7809 uint16_t frag_off;
7810 char *target;
7811 struct GNUNET_TIME_Relative cdelay;
7812 struct FindByMessageUuidContext fc;
7813
7814 vl = lookup_virtual_link (&cmc->im.sender);
7815 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
7816 {
7817 /* Entirely normal: fragments of a message that was already in flight
7818 keep arriving for a while after a link goes down, and a peer that has
7819 validated us may start sending before we have validated it. This used
7820 to call #GNUNET_SERVICE_client_drop(), which disconnects the
7821 communicator *process* -- every queue it owns, hence every neighbour
7822 reachable through it, hence every CORE session. On a peer with many
7823 neighbours a single ill-timed fragment therefore dropped all
7824 connections at once, and since the fragment comes from the network,
7825 any peer could cause it at will. Drop the fragment, keep the
7826 communicator; see #demultiplex_with_cmc() for the same reasoning. */
7828 "No virtual link for %s to handle fragment\n",
7829 GNUNET_i2s (&cmc->im.sender));
7831 "# fragments dropped (virtual link down)",
7832 1,
7833 GNUNET_NO);
7834 finish_cmc_handling (cmc);
7835 return;
7836 }
7837 if (NULL == vl->reassembly_map)
7838 {
7840 vl->reassembly_heap =
7845 vl);
7846 }
7847 msize = ntohs (fb->msg_size);
7848 fc.message_uuid = fb->msg_uuid;
7849 fc.rc = NULL;
7851 fb->msg_uuid.uuid,
7853 &fc);
7854 fsize = ntohs (fb->header.size) - sizeof(*fb);
7855 if (NULL == (rc = fc.rc))
7856 {
7857 /* Bound the RAM a single sender can pin here: @e msg_size is chosen by
7858 the peer, not by us. */
7861 {
7862 struct ReassemblyContext *drop;
7863
7865 GNUNET_assert (NULL != drop);
7867 "# Reassembly contexts dropped (limit reached)",
7868 1,
7869 GNUNET_NO);
7871 }
7872 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
7873 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
7874 rc->msg_uuid = fb->msg_uuid;
7875 rc->virtual_link = vl;
7876 rc->msg_size = msize;
7877 rc->reassembly_timeout =
7881 rc,
7885 vl->reassembly_map,
7886 rc->msg_uuid.uuid,
7887 rc,
7889 target = (char *) &rc[1];
7890 rc->bitfield = (uint8_t *) (target + rc->msg_size);
7891 /* The bitfield loop below decrements @e msg_missing once per newly
7892 received byte, so this must always start at the full message size:
7893 initialising it to 0 for a single-fragment message made it
7894 underflow, and the message was then never delivered. */
7895 rc->msg_missing = rc->msg_size;
7897 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
7898 PRIu64 "\n",
7899 fsize,
7900 ntohs (fb->frag_off),
7901 msize,
7902 rc->msg_missing,
7903 GNUNET_i2s (&cmc->im.sender),
7904 fb->msg_uuid.uuid);
7905 }
7906 else
7907 {
7908 target = (char *) &rc[1];
7910 "Received fragment at offset %u/%u from %s for message %u\n",
7911 ntohs (fb->frag_off),
7912 msize,
7913 GNUNET_i2s (&cmc->im.sender),
7914 (unsigned int) fb->msg_uuid.uuid);
7915 }
7916 if (msize != rc->msg_size)
7917 {
7918 GNUNET_break (0);
7919 finish_cmc_handling (cmc);
7920 return;
7921 }
7922
7923 /* reassemble */
7924 if (0 == fsize)
7925 {
7926 GNUNET_break (0);
7927 finish_cmc_handling (cmc);
7928 return;
7929 }
7930 frag_off = ntohs (fb->frag_off);
7931 if (frag_off + fsize > msize)
7932 {
7933 /* Fragment (plus fragment size) exceeds message size! */
7934 GNUNET_break_op (0);
7935 finish_cmc_handling (cmc);
7936 return;
7937 }
7938 memcpy (&target[frag_off], &fb[1], fsize);
7939 /* update bitfield and msg_missing */
7940 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
7941 {
7942 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
7943 {
7944 rc->bitfield[i / 8] |= (1 << (i % 8));
7945 rc->msg_missing--;
7946 }
7947 }
7948
7949 /* Compute cumulative ACK */
7951 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
7952 if (0 == rc->msg_missing)
7953 cdelay = GNUNET_TIME_UNIT_ZERO;
7954 cummulative_ack (&cmc->im.sender,
7955 &fb->ack_uuid,
7958 /* is reassembly complete? */
7959 if (0 != rc->msg_missing)
7960 {
7961 finish_cmc_handling (cmc);
7962 return;
7963 }
7964 /* reassembly is complete, verify result */
7965 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7966 if (ntohs (msg->size) != rc->msg_size)
7967 {
7968 GNUNET_break (0);
7970 finish_cmc_handling (cmc);
7971 return;
7972 }
7973 /* successful reassembly */
7975 "Fragment reassembly complete for message %u\n",
7976 (unsigned int) fb->msg_uuid.uuid);
7977 /* FIXME: check that the resulting msg is NOT a
7978 DV Box or Reliability Box, as that is NOT allowed! */
7979 {
7980 uint16_t rsize = rc->msg_size;
7981 char rbuf[rsize] GNUNET_ALIGN;
7982
7983 /* Copy the reassembled message out and release `rc' BEFORE
7984 demultiplexing: the inner message may tear down the virtual link,
7985 which frees every reassembly context of that link -- the old code
7986 then used and freed `rc' a second time afterwards. */
7987 memcpy (rbuf, msg, rsize);
7989 cmc->mh = (const struct GNUNET_MessageHeader *) rbuf;
7991 }
7992}
7993
7994
8002static int
8004 const struct TransportReliabilityBoxMessage *rb)
8005{
8006 const struct GNUNET_MessageHeader *box = (const struct
8007 GNUNET_MessageHeader *) &rb[1];
8008 (void) cls;
8009
8011 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
8012 ntohs (rb->header.size),
8013 ntohs (box->type),
8014 ntohs (box->size),
8015 sizeof (struct TransportReliabilityBoxMessage),
8016 sizeof (struct GNUNET_MessageHeader));
8018 return GNUNET_YES;
8019}
8020
8021
8029static void
8031 const struct TransportReliabilityBoxMessage *rb)
8032{
8033 struct CommunicatorMessageContext *cmc = cls;
8034 const struct GNUNET_MessageHeader *inbox =
8035 (const struct GNUNET_MessageHeader *) &rb[1];
8036 struct GNUNET_TIME_Relative rtt;
8037
8039 "Received reliability box from %s with UUID %s of type %u\n",
8040 GNUNET_i2s (&cmc->im.sender),
8042 (unsigned int) ntohs (inbox->type));
8043 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
8044 do not really have an RTT for the
8045 * incoming* queue (should we have
8046 the sender add it to the rb message?) */
8048 &cmc->im.sender,
8049 &rb->ack_uuid,
8050 (0 == ntohl (rb->ack_countdown))
8053 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
8054 /* continue with inner message */
8055 /* FIXME: check that inbox is NOT a DV Box, fragment or another
8056 reliability box (not allowed!) */
8057 cmc->mh = inbox;
8059}
8060
8061
8070static void
8071update_pd_age (struct PerformanceData *pd, unsigned int age)
8072{
8073 unsigned int sage;
8074
8075 if (age == pd->last_age)
8076 return; /* nothing to do */
8077 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
8078 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
8079 {
8080 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
8081
8082 the->bytes_sent = 0;
8083 the->bytes_received = 0;
8084 }
8085 pd->last_age = age;
8086}
8087
8088
8097static void
8099 struct GNUNET_TIME_Relative rtt,
8100 uint16_t bytes_transmitted_ok)
8101{
8102 uint64_t nval = rtt.rel_value_us;
8103 uint64_t oval = pd->aged_rtt.rel_value_us;
8104 unsigned int age = get_age ();
8105 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
8106
8107 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
8108 pd->aged_rtt = rtt;
8109 else
8110 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
8111 update_pd_age (pd, age);
8112 the->bytes_received += bytes_transmitted_ok;
8113}
8114
8115
8123static void
8125 struct GNUNET_TIME_Relative rtt,
8126 uint16_t bytes_transmitted_ok)
8127{
8128 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
8129}
8130
8131
8139static void
8141 struct GNUNET_TIME_Relative rtt,
8142 uint16_t bytes_transmitted_ok)
8143{
8144 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
8145}
8146
8147
8155static void
8157{
8158 struct PendingMessage *pos;
8159
8161 "Complete transmission of message %" PRIu64 " %u\n",
8162 pm->logging_uuid,
8163 pm->pmt);
8164 switch (pm->pmt)
8165 {
8166 case PMT_CORE:
8168 /* Full message sent, we are done */
8170 return;
8171
8172 case PMT_FRAGMENT_BOX:
8173 /* Fragment sent over reliable channel */
8174 pos = pm->frag_parent;
8175 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
8178 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
8179 (unsigned long) pos->frag_off,
8180 (unsigned long) pos->bytes_msg,
8181 pos->pmt,
8182 NULL == pos->frag_parent ? 1 : 0);
8183 /* check if subtree is done */
8184 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
8185 - sizeof(struct
8187 &&
8188 (NULL != pos->frag_parent))
8189 {
8190 pm = pos;
8191 pos = pm->frag_parent;
8192 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
8193 {
8195 return;
8196 }
8197 else if (PMT_DV_BOX == pm->pmt)
8198 {
8200 return;
8201 }
8202 GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
8204 }
8205
8206 /* Was this the last applicable fragment?
8207
8208 NOTE: @a pos may be a DV box here, and then it is NOT the message the
8209 client is waiting for -- its @e frag_parent is, and that parent's
8210 @e bpm points at @a pos. Answering the client directly (and thereby
8211 releasing @a pos through #free_pending_message()) left @e bpm of a
8212 message that is still queued pointing at freed memory, which
8213 #transmit_on_queue() reads and may free a second time. Hand it to
8214 ourselves instead: the #PMT_DV_BOX case below clears @e bpm and
8215 answers for the parent, and for every other @e pmt it does exactly
8216 what the direct call did. */
8217 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
8218 pos->pmt) &&
8219 (pos->frag_off == pos->bytes_msg))
8221 return;
8222
8223 case PMT_DV_BOX:
8225 "Completed transmission of message %" PRIu64 " (DV Box)\n",
8226 pm->logging_uuid);
8227 if (NULL != pm->frag_parent)
8228 {
8229 pos = pm->frag_parent;
8231 pos->bpm = NULL;
8233 }
8234 else
8236 return;
8237 }
8238}
8239
8240
8248static void
8250 struct GNUNET_TIME_Relative ack_delay)
8251{
8252 struct GNUNET_TIME_Relative delay;
8253 struct PendingMessage *pm = pa->pm;
8254
8256 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
8257 if (NULL != pa->queue && 1 == pa->num_send)
8259 if (NULL != pa->dvh && 1 == pa->num_send)
8260 update_dvh_performance (pa->dvh, delay, pa->message_size);
8261 /* Retire @a pa BEFORE handing its message on. completed_pending_message()
8262 ends in free_pending_message() for anything it finishes, and that now
8263 releases every acknowledgement still attached to the message -- this one
8264 included. Freeing it afterwards is a double free, and it aborts on the
8265 GNUNET_assert() over multiuuidmap_remove() in
8266 free_pending_acknowledgement(), the map entry having gone with the first
8267 release. Nothing below needs @a pa, only its message. */
8269 if (NULL != pm)
8271}
8272
8273
8281static int
8283 const struct TransportReliabilityAckMessage *ra)
8284{
8285 unsigned int n_acks;
8286
8287 (void) cls;
8288 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
8289 / sizeof(struct TransportCummulativeAckPayloadP);
8290 if (0 == n_acks)
8291 {
8292 GNUNET_break_op (0);
8293 return GNUNET_SYSERR;
8294 }
8295 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
8296 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
8297 {
8298 GNUNET_break_op (0);
8299 return GNUNET_SYSERR;
8300 }
8301 return GNUNET_OK;
8302}
8303
8304
8312static void
8314 const struct TransportReliabilityAckMessage *ra)
8315{
8316 struct CommunicatorMessageContext *cmc = cls;
8317 const struct TransportCummulativeAckPayloadP *ack;
8318 unsigned int n_acks;
8319 uint32_t ack_counter;
8320
8321 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
8322 / sizeof(struct TransportCummulativeAckPayloadP);
8323 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
8324 for (unsigned int i = 0; i < n_acks; i++)
8325 {
8326 struct PendingAcknowledgement *pa =
8328 if (NULL == pa)
8329 {
8331 "Received ACK from %s with UUID %s which is unknown to us!\n",
8332 GNUNET_i2s (&cmc->im.sender),
8333 GNUNET_uuid2s (&ack[i].ack_uuid.value));
8335 GST_stats,
8336 "# FRAGMENT_ACKS dropped, no matching pending message",
8337 1,
8338 GNUNET_NO);
8339 continue;
8340 }
8342 "Received ACK from %s with UUID %s\n",
8343 GNUNET_i2s (&cmc->im.sender),
8344 GNUNET_uuid2s (&ack[i].ack_uuid.value));
8345 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
8346 }
8347
8348 ack_counter = ntohl (ra->ack_counter);
8349 (void) ack_counter; /* silence compiler warning for now */
8350 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
8351 // (DV and/or Neighbour?)
8352 finish_cmc_handling (cmc);
8353}
8354
8355
8363static int
8365 void *cls,
8367{
8368 uint16_t size = ntohs (be->header.size) - sizeof(*be);
8369 const struct GNUNET_MessageHeader *inbox =
8370 (const struct GNUNET_MessageHeader *) &be[1];
8371 const char *is;
8372 uint16_t isize;
8373
8374 (void) cls;
8375 /* MUST bound the buffer before reading @a inbox: the size check below
8376 dereferences it, and a message consisting of nothing but the header
8377 leaves no bytes to read. */
8378 if (size <= sizeof(struct GNUNET_MessageHeader))
8379 {
8380 GNUNET_break_op (0);
8381 return GNUNET_SYSERR;
8382 }
8383 if (ntohs (inbox->size) >= size)
8384 {
8385 GNUNET_break_op (0);
8386 return GNUNET_SYSERR;
8387 }
8388 isize = ntohs (inbox->size);
8389 is = ((const char *) inbox) + isize;
8390 size -= isize;
8391 if ('\0' != is[size - 1])
8392 {
8393 GNUNET_break_op (0);
8394 return GNUNET_SYSERR;
8395 }
8396 return GNUNET_YES;
8397}
8398
8399
8408static void
8410 void *cls,
8412{
8413 const struct GNUNET_PeerIdentity *my_identity;
8414 struct CommunicatorMessageContext *cmc = cls;
8416 struct GNUNET_MQ_Envelope *env;
8417 struct TransportClient *tc;
8418 const struct GNUNET_MessageHeader *inbox =
8419 (const struct GNUNET_MessageHeader *) &be[1];
8420 uint16_t isize = ntohs (inbox->size);
8421 const char *target_communicator = ((const char *) inbox) + isize;
8422 char *sender;
8423 char *self;
8424
8427
8428 GNUNET_asprintf (&sender,
8429 "%s",
8430 GNUNET_i2s (&cmc->im.sender));
8431 GNUNET_asprintf (&self,
8432 "%s",
8434
8435 /* Find client providing this communicator */
8436 for (tc = clients_head; NULL != tc; tc = tc->next)
8437 if ((CT_COMMUNICATOR == tc->type) &&
8438 (NULL != tc->details.communicator.address_prefix) &&
8439 (0 ==
8440 strcmp (tc->details.communicator.address_prefix, target_communicator)))
8441 break;
8442 if (NULL == tc)
8443 {
8444 char *stastr;
8445
8447 &stastr,
8448 "# Backchannel message dropped: target communicator `%s' unknown",
8449 target_communicator);
8451 GNUNET_free (stastr);
8452 GNUNET_free (sender);
8453 GNUNET_free (self);
8454 finish_cmc_handling (cmc);
8455 return;
8456 }
8457 /* Finally, deliver backchannel message to communicator */
8459 "Delivering backchannel message from %s to %s of type %u to %s\n",
8460 sender,
8461 self,
8462 ntohs (inbox->type),
8463 target_communicator);
8465 cbi,
8466 isize,
8468 cbi->pid = cmc->im.sender;
8469 memcpy (&cbi[1], inbox, isize);
8470 GNUNET_MQ_send (tc->mq, env);
8471 GNUNET_free (sender);
8472 GNUNET_free (self);
8473 finish_cmc_handling (cmc);
8474}
8475
8476
8486static void
8488{
8489 struct DistanceVector *dv = cls;
8490 struct DistanceVectorHop *pos;
8491 struct GNUNET_TIME_Absolute next;
8492
8493 dv->timeout_task = NULL;
8494 /* @e dv_head is NOT sorted by @e timeout: learn_dv_path() inserts a new
8495 hop at the head, and moves a rediscovered one back to the head, so the
8496 list runs newest (i.e. latest deadline) first. Stopping at the first
8497 live entry therefore inspected exactly the youngest hop and re-armed
8498 for *its* deadline, which is the last one of the whole set: expired
8499 hops behind it were never collected, and check_vl_transmission() kept
8500 skipping them one by one for as long as the route lived. Sweep all of
8501 them and come back for the earliest survivor. */
8503 pos = dv->dv_head;
8504 while (NULL != pos)
8505 {
8506 struct DistanceVectorHop *next_pos = pos->next_dv;
8507
8508 GNUNET_assert (dv == pos->dv);
8511 else
8512 next = GNUNET_TIME_absolute_min (next, pos->timeout);
8513 pos = next_pos;
8514 }
8515 if (NULL == dv->dv_head)
8516 {
8517 free_dv_route (dv);
8518 return;
8519 }
8520 dv->timeout_task =
8522}
8523
8524
8525static void
8527{
8528
8529 const struct GNUNET_PeerIdentity target = vl->target;
8530
8531
8533 {
8534 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
8535 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
8536 0;
8537 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
8540 struct CommunicatorMessageContext *cmc;
8541 struct RingBufferEntry *rbe;
8542 struct GNUNET_MessageHeader *mh;
8543
8545 "Sending from ring buffer, which has %u items\n",
8546 head);
8547
8548 ring_buffer_head = 0;
8549 for (unsigned int i = 0; i < head; i++)
8550 {
8551 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
8552 cmc = rbe->cmc;
8553 mh = rbe->mh;
8554
8555 im = cmc->im;
8556 // mh = cmc->mh;
8558 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
8559 mh->type,
8560 GNUNET_i2s (&im.sender),
8561 GNUNET_i2s2 (&target),
8562 (i + tail) % RING_BUFFER_SIZE);
8563 if (0 == GNUNET_memcmp (&target, &im.sender))
8564 {
8566 "Finish handling message of type %u and size %u\n",
8567 (unsigned int) ntohs (mh->type),
8568 (unsigned int) ntohs (mh->size));
8570 GNUNET_free (mh);
8571 GNUNET_free (rbe->cmc);
8572 GNUNET_free (rbe);
8573 }
8574 else
8575 {
8576 ring_buffer_copy[ring_buffer_head] = rbe;
8578 }
8579 }
8580
8583 {
8585 }
8586
8587 for (unsigned int i = 0; i < ring_buffer_head; i++)
8588 {
8589 ring_buffer[i] = ring_buffer_copy[i];
8591 "ring_buffer[i]->mh->type for i %u %u\n",
8592 i,
8593 ring_buffer[i]->mh->type);
8594 }
8595 /* MUST clear the consumed slots, we freed those entries above */
8596 for (unsigned int i = ring_buffer_head; i < RING_BUFFER_SIZE; i++)
8597 ring_buffer[i] = NULL;
8598
8600 "%u items still in ring buffer\n",
8602 /* If we consumed nothing, compaction rewrote the buffer in place and
8603 left the write index one past the end. #handle_raw_message() would
8604 then read ring_buffer[RING_BUFFER_SIZE] and free whatever that is.
8605 The buffer is still full, and compaction moved the oldest entry to
8606 slot 0, so that is where the next write belongs. */
8608 ring_buffer_head = 0;
8609 }
8610
8612 {
8613 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
8614 struct PendingMessage *pm;
8615 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
8617 0;
8618 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
8621
8623 "Sending from ring buffer dv, which has %u items\n",
8624 head);
8625
8627 for (unsigned int i = 0; i < head; i++)
8628 {
8629 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
8630
8632 "Sending to ring buffer target %s using vl target %s\n",
8633 GNUNET_i2s (&pm->target),
8634 GNUNET_i2s2 (&target));
8635 if (0 == GNUNET_memcmp (&target, &pm->target))
8636 {
8638 "Adding PendingMessage to vl, checking transmission.\n");
8639 pm->vl = vl;
8643 pm);
8644
8646 }
8647 else
8648 {
8649 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
8651 }
8652 }
8653
8655 {
8657 }
8658
8659 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
8660 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
8661 /* MUST clear the consumed slots: entries we handed to a VirtualLink are
8662 now owned by that link, and #forward_dv_box() would GNUNET_free() them
8663 again once the ring buffer wraps around. */
8664 for (unsigned int i = ring_buffer_dv_head; i < RING_BUFFER_SIZE; i++)
8665 ring_buffer_dv[i] = NULL;
8666
8668 "%u items still in ring buffer dv.\n",
8670 /* Same one-past-the-end hazard as above: #forward_dv_box() reads
8671 ring_buffer_dv[ring_buffer_dv_head] and GNUNET_free()s it. */
8674 }
8675}
8676
8677
8685static void
8687{
8688 struct DistanceVector *dv = hop->dv;
8689 struct VirtualLink *vl;
8690
8691 vl = lookup_virtual_link (&dv->target);
8692 if (NULL == vl)
8693 {
8694
8695 vl = GNUNET_new (struct VirtualLink);
8697 "Creating new virtual link %p to %s using DV!\n",
8698 vl,
8699 GNUNET_i2s (&dv->target));
8700 vl->burst_addr = NULL;
8701 vl->confirmed = GNUNET_YES;
8702 vl->message_uuid_ctr =
8703 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
8704 vl->target = dv->target;
8708 /* What the peer will grant us in its very first FLOW_CONTROL anyway
8709 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
8710 Starting at zero instead means a link that is up, validated and
8711 working carries nothing at all until an FC round trip completes --
8712 and if the peer cannot answer, not ever. */
8716 links,
8717 &vl->target,
8718 vl,
8720 vl->dv = dv;
8721 dv->vl = vl;
8722 vl->visibility_task =
8725 /* We lacked a confirmed connection to the target
8726 before, so tell CORE about it (finally!) */
8729 }
8730 else
8731 {
8732 /* Link was already up, remember dv is also now available and we are done */
8733 vl->dv = dv;
8734 dv->vl = vl;
8735 if (GNUNET_NO == vl->confirmed)
8736 {
8737 vl->confirmed = GNUNET_YES;
8738 vl->visibility_task =
8741 /* We lacked a confirmed connection to the target
8742 before, so tell CORE about it (finally!) */
8745 }
8746 else
8748 "Virtual link to %s could now also use DV!\n",
8749 GNUNET_i2s (&dv->target));
8750 }
8751}
8752
8753
8779static int
8781 unsigned int path_len,
8782 struct GNUNET_TIME_Relative network_latency,
8783 struct GNUNET_TIME_Absolute path_valid_until)
8784{
8785 const struct GNUNET_PeerIdentity *my_identity;
8786 struct DistanceVectorHop *hop;
8787 struct DistanceVector *dv;
8788 struct Neighbour *next_hop;
8789 unsigned int shorter_distance;
8790
8791 if (path_len < 3)
8792 {
8793 /* what a boring path! not allowed! */
8794 GNUNET_break (0);
8795 return GNUNET_SYSERR;
8796 }
8797
8800
8801 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
8802 next_hop = lookup_neighbour (&path[1]);
8803 if (NULL == next_hop)
8804 {
8805 /* next hop must be a neighbour, otherwise this whole thing is useless! */
8806 GNUNET_break (0);
8807 return GNUNET_SYSERR;
8808 }
8809 for (unsigned int i = 2; i < path_len; i++)
8810 {
8811 struct Neighbour *n = lookup_neighbour (&path[i]);
8812 struct GNUNET_TIME_Absolute q_timeout;
8813
8814 if (NULL != n)
8815 {
8816 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
8817 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
8818 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
8820 "remaining %lu to %s\n",
8821 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
8822 .rel_value_us,
8823 GNUNET_i2s (&n->pid));
8824 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
8825 {
8826 /* Useless path: we have a direct active connection to some hop
8827 in the middle of the path, so this one is not even
8828 terribly useful for redundancy */
8830 "Path of %u hops useless: directly link to hop %u (%s)\n",
8831 path_len,
8832 i,
8833 GNUNET_i2s (&path[i]));
8835 "# Useless DV path ignored: hop is neighbour",
8836 1,
8837 GNUNET_NO);
8838 return GNUNET_SYSERR;
8839 }
8840 }
8841 }
8842 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
8843 if (NULL == dv)
8844 {
8845 dv = GNUNET_new (struct DistanceVector);
8846 dv->target = path[path_len - 1];
8849 dv);
8852 dv_routes,
8853 &dv->target,
8854 dv,
8856 }
8857 /* Check if we have this path already! */
8858 shorter_distance = 0;
8859 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
8860 pos = pos->next_dv)
8861 {
8862 if (pos->distance < path_len - 3)
8863 shorter_distance++;
8864 /* Note that the distances in 'pos' excludes us (path[0]),
8865 the next_hop (path[1]) and the target so we need to subtract three
8866 and check next_hop explicitly */
8867 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
8868 {
8869 int match = GNUNET_YES;
8870
8871 for (unsigned int i = 0; i < pos->distance; i++)
8872 {
8873 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
8874 {
8875 match = GNUNET_NO;
8876 break;
8877 }
8878 }
8879 if (GNUNET_YES == match)
8880 {
8881 struct GNUNET_TIME_Relative last_timeout;
8882
8883 /* Re-discovered known path, update timeout */
8885 "# Known DV path refreshed",
8886 1,
8887 GNUNET_NO);
8888 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
8889 pos->timeout =
8891 pos->path_valid_until =
8892 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
8893 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
8894 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
8895 if (0 <
8898 if (last_timeout.rel_value_us <
8901 .rel_value_us)
8902 {
8903 /* Some peer send DV learn messages too often, we are learning
8904 the same path faster than it would be useful; do not forward! */
8906 "Rediscovered path too quickly, not forwarding further\n")
8907 ;
8908 return GNUNET_NO;
8909 }
8911 "Refreshed known path to %s valid until %s, forwarding further\n",
8912 GNUNET_i2s (&dv->target),
8914 pos->path_valid_until));
8915 return GNUNET_YES;
8916 }
8917 }
8918 }
8919 /* Count how many shorter paths we have (incl. direct
8920 neighbours) before simply giving up on this one! */
8921 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
8922 {
8923 /* We have a shorter path already! */
8925 "Have many shorter DV paths %s, not forwarding further\n",
8926 GNUNET_i2s (&dv->target));
8927 return GNUNET_NO;
8928 }
8929 /* create new DV path entry */
8931 "Discovered new DV path to %s valid until %s\n",
8932 GNUNET_i2s (&dv->target),
8933 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
8934 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
8935 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
8936 hop->next_hop = next_hop;
8937 hop->dv = dv;
8938 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
8939 memcpy (&hop[1],
8940 &path[2],
8941 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
8943 hop->path_valid_until = path_valid_until;
8944 hop->distance = path_len - 3;
8945 hop->pd.aged_rtt = network_latency;
8946 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
8948 next_hop->dv_head,
8949 next_hop->dv_tail,
8950 hop);
8951 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
8953 return GNUNET_YES;
8954}
8955
8956
8964static int
8965check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8966{
8967 const struct GNUNET_PeerIdentity *my_identity;
8968 uint16_t size = ntohs (dvl->header.size);
8969 uint16_t num_hops = ntohs (dvl->num_hops);
8970 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
8971
8972 (void) cls;
8973 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
8974 {
8975 GNUNET_break_op (0);
8976 return GNUNET_SYSERR;
8977 }
8978 if (num_hops > MAX_DV_HOPS_ALLOWED)
8979 {
8980 GNUNET_break_op (0);
8981 return GNUNET_SYSERR;
8982 }
8983
8986
8987 for (unsigned int i = 0; i < num_hops; i++)
8988 {
8989 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
8990 {
8991 GNUNET_break_op (0);
8992 return GNUNET_SYSERR;
8993 }
8994 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
8995 {
8996 GNUNET_break_op (0);
8997 return GNUNET_SYSERR;
8998 }
8999 }
9000 return GNUNET_YES;
9001}
9002
9003
9015static void
9017 const struct TransportDVLearnMessage *msg,
9018 uint16_t bi_history,
9019 uint16_t nhops,
9020 const struct DVPathEntryP *hops,
9021 struct GNUNET_TIME_Absolute in_time)
9022{
9023 struct DVPathEntryP *dhops;
9024 size_t fwd_size = sizeof(struct TransportDVLearnMessage)
9025 + (nhops + 1) * sizeof(struct DVPathEntryP);
9026 /* Signing is synchronous and the routing calls below copy the message,
9027 so this never outlives the frame. Keeping it on the stack matters:
9028 a hub forwards a DV learn to every eligible neighbour, so this is one
9029 of the hottest allocation sites in the service. Size it by the hop
9030 limit rather than by @a nhops -- @a nhops is only asserted to be below
9031 that limit further down, and a VLA is sized before we get there. */
9032 char fwd_buf[sizeof(struct TransportDVLearnMessage)
9033 + (MAX_DV_HOPS_ALLOWED + 1)
9034 * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
9035 struct TransportDVLearnMessage *fwd
9036 = (struct TransportDVLearnMessage *) fwd_buf;
9037 struct GNUNET_TIME_Relative nnd;
9038 const struct GNUNET_PeerIdentity *my_identity;
9039 struct VirtualLink *vl;
9040 struct Neighbour *n;
9041
9043 memset (fwd_buf, 0, fwd_size);
9044
9045 /* compute message for forwarding */
9047 "Forwarding DV learn message originating from %s to %s\n",
9048 GNUNET_i2s (&msg->initiator),
9049 GNUNET_i2s2 (next_hop));
9052 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
9053 + (nhops + 1) * sizeof(struct DVPathEntryP));
9054 fwd->num_hops = htons (nhops + 1);
9055 fwd->bidirectional = htons (bi_history);
9058 msg->non_network_delay));
9060 fwd->init_sig = msg->init_sig;
9061 fwd->initiator = msg->initiator;
9062 fwd->challenge = msg->challenge;
9063 fwd->monotonic_time = msg->monotonic_time;
9064
9067
9068 dhops = (struct DVPathEntryP *) &fwd[1];
9069 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
9070 dhops[nhops].hop = *my_identity;
9071 {
9072 struct DvHopPS dhp = {
9074 .purpose.size = htonl (sizeof(dhp)),
9075 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
9076 .succ = *next_hop,
9077 .challenge = msg->challenge
9078 };
9079
9081 &dhops[nhops].hop_sig))
9082 return; /* nobody would accept the path without our hop signature */
9083 }
9084 vl = lookup_virtual_link (next_hop);
9085 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9086 {
9088 &fwd->header,
9090 return;
9091 }
9092 /* Use route via neighbour */
9093 n = lookup_neighbour (next_hop);
9094 if (NULL != n)
9096 &fwd->header,
9098}
9099
9100
9110static int
9112 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
9113 const struct GNUNET_PeerIdentity *init,
9115 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
9116{
9117 struct DvInitPS ip = { .purpose.purpose = htonl (
9119 .purpose.size = htonl (sizeof(ip)),
9120 .monotonic_time = sender_monotonic_time,
9121 .challenge = *challenge };
9122
9123 if (
9124 GNUNET_OK !=
9126 &ip,
9127 init_sig,
9128 &init->public_key))
9129 {
9130 GNUNET_break_op (0);
9131 return GNUNET_SYSERR;
9132 }
9133 return GNUNET_OK;
9134}
9135
9136
9141{
9146
9150 const struct DVPathEntryP *hops;
9151
9156
9161
9165 unsigned int num_eligible;
9166
9170 unsigned int num_selections;
9171
9175 uint16_t nhops;
9176
9180 uint16_t bi_history;
9181};
9182
9183
9192static int
9194 const struct GNUNET_PeerIdentity *pid,
9195 void *value)
9196{
9197 struct NeighbourSelectionContext *nsc = cls;
9198
9199 (void) value;
9200 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
9201 return GNUNET_YES; /* skip initiator */
9202 for (unsigned int i = 0; i < nsc->nhops; i++)
9203 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
9204 return GNUNET_YES;
9205 /* skip peers on path */
9206 nsc->num_eligible++;
9207 return GNUNET_YES;
9208}
9209
9210
9221static int
9223 const struct GNUNET_PeerIdentity *pid,
9224 void *value)
9225{
9226 struct NeighbourSelectionContext *nsc = cls;
9227
9229 "transmission %s\n",
9230 GNUNET_i2s (pid));
9231 (void) value;
9232 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
9233 return GNUNET_YES; /* skip initiator */
9234 for (unsigned int i = 0; i < nsc->nhops; i++)
9235 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
9236 return GNUNET_YES;
9237 /* skip peers on path */
9238 for (unsigned int i = 0; i < nsc->num_selections; i++)
9239 {
9240 if (nsc->selections[i] == nsc->num_eligible)
9241 {
9242 forward_dv_learn (pid,
9243 nsc->dvl,
9244 nsc->bi_history,
9245 nsc->nhops,
9246 nsc->hops,
9247 nsc->in_time);
9248 break;
9249 }
9250 }
9251 nsc->num_eligible++;
9252 return GNUNET_YES;
9253}
9254
9255
9299static unsigned int
9300calculate_fork_degree (unsigned int hops_taken,
9301 unsigned int neighbour_count,
9302 unsigned int eligible_count)
9303{
9304 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
9305 double eligible_ratio =
9306 ((double) eligible_count) / ((double) neighbour_count);
9307 double boost_factor = eligible_ratio * eligible_ratio;
9308 unsigned int rnd;
9309 double left;
9310
9311 if (hops_taken >= 64)
9312 {
9313 GNUNET_break (0);
9314 return 0; /* precaution given bitshift below */
9315 }
9316 for (unsigned int i = 1; i < hops_taken; i++)
9317 {
9318 /* For each hop, subtract the expected number of targets
9319 reached at distance d (so what remains divided by 2^d) */
9320 target_total -= (target_total * boost_factor / (1LLU << i));
9321 }
9322 {
9323 double degree = target_total * boost_factor / (1LLU << hops_taken);
9324
9325 rnd = (unsigned int) floor (degree);
9326 /* round up or down probabilistically depending on how close we were
9327 when floor()ing to rnd. NOTE: this must be the fractional part of
9328 @e degree; using `target_total - rnd' here made the condition below
9329 true essentially always, so we always rounded up. */
9330 left = degree - (double) rnd;
9331 }
9332 if (UINT32_MAX * left >
9333 GNUNET_CRYPTO_random_u64 (UINT32_MAX))
9334 rnd++; /* round up */
9336 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
9337 hops_taken,
9338 rnd,
9339 eligible_count,
9340 neighbour_count);
9341 return rnd;
9342}
9343
9344
9351static void
9352neighbour_store_dvmono_cb (void *cls, int success)
9353{
9354 struct Neighbour *n = cls;
9355
9356 n->sc = NULL;
9357 if (GNUNET_YES != success)
9359 "Failed to store other peer's monotonic time in peerstore!\n");
9360}
9361
9362
9363static struct GNUNET_TIME_Relative
9365{
9366 struct GNUNET_TIME_Relative host_latency_sum;
9367 struct GNUNET_TIME_Relative latency;
9368 struct GNUNET_TIME_Relative network_latency;
9369 uint16_t nhops = ntohs (dvl->num_hops);;
9370
9371 /* We initiated this, learn the forward path! */
9372 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
9373
9374 // Need also something to lookup initiation time
9375 // to compute RTT! -> add RTT argument here?
9377 dvl->monotonic_time));
9378 /* @e non_network_delay is fully attacker-controlled, and our clock may
9379 simply be behind the initiator's: never assert on this. */
9380 if (latency.rel_value_us < host_latency_sum.rel_value_us)
9381 {
9383 "# DV learn with implausible non-network delay",
9384 1,
9385 GNUNET_NO);
9387 }
9388 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
9389 // (based on dvl->challenge, we can identify time of origin!)
9390
9391 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
9392 /* assumption: latency on all links is the same */
9393 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
9394
9395 return network_latency;
9396}
9397
9398
9406static void
9407handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
9408{
9409 struct CommunicatorMessageContext *cmc = cls;
9411 int bi_hop;
9412 uint16_t nhops;
9413 uint16_t bi_history;
9414 const struct DVPathEntryP *hops;
9415 int do_fwd;
9416 int did_initiator;
9417 struct GNUNET_TIME_Absolute in_time;
9418 struct Neighbour *n;
9419 const struct GNUNET_PeerIdentity *my_identity;
9420
9421 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
9422 bi_history = ntohs (dvl->bidirectional);
9423 hops = (const struct DVPathEntryP *) &dvl[1];
9424 if (0 == nhops)
9425 {
9426 /* sanity check */
9427 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
9428 {
9429 GNUNET_break (0);
9430 finish_cmc_handling (cmc);
9431 return;
9432 }
9433 /* A zero-hop message we supposedly initiated ourselves would make the
9434 "we are the initiator" branch below read hops[0] and write past the
9435 end of its `path[nhops + 1]' array. */
9437 {
9438 GNUNET_break_op (0);
9439 finish_cmc_handling (cmc);
9440 return;
9441 }
9442 }
9443 else
9444 {
9446 "handle dv learn message last hop %s\n",
9447 GNUNET_i2s (&hops[nhops - 1].hop));
9448 /* sanity check */
9449 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
9450 {
9451 GNUNET_break (0);
9452 finish_cmc_handling (cmc);
9453 return;
9454 }
9455 }
9456
9458 cc = cmc->tc->details.communicator.cc;
9459 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
9460 cc); // FIXME: add bi-directional flag to cc?
9461 in_time = GNUNET_TIME_absolute_get ();
9462
9463 /* continue communicator here, everything else can happen asynchronous! */
9464 finish_cmc_handling (cmc);
9465
9466 n = lookup_neighbour (&dvl->initiator);
9467 if (NULL != n)
9468 {
9469 if ((n->dv_monotime_available == GNUNET_YES) &&
9472 {
9474 "DV learn from %s discarded due to time travel",
9475 GNUNET_i2s (&dvl->initiator));
9477 "# DV learn discarded due to time travel",
9478 1,
9479 GNUNET_NO);
9480 return;
9481 }
9483 &dvl->initiator,
9484 &dvl->challenge,
9485 &dvl->init_sig))
9486 {
9488 "DV learn signature from %s invalid\n",
9489 GNUNET_i2s (&dvl->initiator));
9490 GNUNET_break_op (0);
9491 return;
9492 }
9495 {
9496 if (NULL != n->sc)
9497 {
9499 "store cancel\n");
9501 }
9502 n->sc =
9504 "transport",
9505 &dvl->initiator,
9507 &dvl->monotonic_time,
9508 sizeof(dvl->monotonic_time),
9512 n);
9513 }
9514 }
9515
9518
9519 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
9520 If signature verification load too high, implement random drop strategy */
9521 for (unsigned int i = 0; i < nhops; i++)
9522 {
9523 struct DvHopPS dhp = { .purpose.purpose =
9525 .purpose.size = htonl (sizeof(dhp)),
9526 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
9527 .succ = (nhops == i + 1) ? *my_identity
9528 : hops[i + 1].hop,
9529 .challenge = dvl->challenge };
9530
9531 if (GNUNET_OK !=
9533 &dhp,
9534 &hops[i].hop_sig,
9535 &hops[i].hop.public_key))
9536 {
9538 "DV learn from %s signature of hop %u invalid\n",
9539 GNUNET_i2s (&dvl->initiator),
9540 i);
9542 "signature of hop %s invalid\n",
9543 GNUNET_i2s (&hops[i].hop));
9545 "pred %s\n",
9546 GNUNET_i2s (&dhp.pred));
9548 "succ %s\n",
9549 GNUNET_i2s (&dhp.succ));
9551 "hash %s\n",
9552 GNUNET_sh2s (&dhp.challenge.value));
9553 GNUNET_break_op (0);
9554 return;
9555 }
9556 }
9557 if (GNUNET_EXTRA_LOGGING > 0)
9558 {
9559 char *path;
9560
9561 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
9562 for (unsigned int i = 0; i < nhops; i++)
9563 {
9564 char *tmp;
9565
9566 GNUNET_asprintf (&tmp,
9567 "%s%s%s",
9568 path,
9569 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
9570 GNUNET_i2s (&hops[i].hop));
9571 GNUNET_free (path);
9572 path = tmp;
9573 }
9575 "Received DVInit via %s%s%s\n",
9576 path,
9577 bi_hop ? "<->" : "-->",
9579 GNUNET_free (path);
9580 }
9581 do_fwd = GNUNET_YES;
9582 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
9583 {
9584 struct GNUNET_PeerIdentity path[nhops + 1];
9585 struct GNUNET_TIME_Relative network_latency;
9586
9587 /* We initiated this, learn the forward path! */
9588 path[0] = *my_identity;
9589 path[1] = hops[0].hop;
9590
9591 network_latency = get_network_latency (dvl);
9592
9593 for (unsigned int i = 2; i <= nhops; i++)
9594 {
9595 struct GNUNET_TIME_Relative ilat;
9596
9597 /* assumption: linear latency increase per hop */
9598 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
9599 path[i] = hops[i - 1].hop;
9601 "Learned path with %u hops to %s with latency %s\n",
9602 i,
9603 GNUNET_i2s (&path[i]),
9605 learn_dv_path (path,
9606 i + 1,
9607 ilat,
9610 }
9611 /* as we initiated, do not forward again (would be circular!) */
9612 do_fwd = GNUNET_NO;
9613 return;
9614 }
9615 if (bi_hop)
9616 {
9617 /* last hop was bi-directional, we could learn something here! */
9618 struct GNUNET_PeerIdentity path[nhops + 2];
9619 struct GNUNET_TIME_Relative ilat;
9620 struct GNUNET_TIME_Relative network_latency;
9621
9622 path[0] = *my_identity;
9623 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
9624 for (unsigned int i = 0; i < nhops; i++)
9625 {
9626 int iret;
9627
9628 if (0 == (bi_history & (1 << i)))
9629 break; /* i-th hop not bi-directional, stop learning! */
9630 if (i == nhops - 1)
9631 {
9632 path[i + 2] = dvl->initiator;
9633 }
9634 else
9635 {
9636 path[i + 2] = hops[nhops - i - 2].hop;
9637 }
9638
9640 "Learned inverse path with %u hops to %s\n",
9641 i + 2,
9642 GNUNET_i2s (&path[i + 2]));
9643 network_latency = get_network_latency (dvl);
9644 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
9645 iret = learn_dv_path (path,
9646 i + 3,
9647 ilat,
9650 if (GNUNET_SYSERR == iret)
9651 {
9652 /* path invalid or too long to be interesting for US, thus should also
9653 not be interesting to our neighbours, cut path when forwarding to
9654 'i' hops, except of course for the one that goes back to the
9655 initiator */
9657 "# DV learn not forwarded due invalidity of path",
9658 1,
9659 GNUNET_NO);
9660 do_fwd = GNUNET_NO;
9661 break;
9662 }
9663 if ((GNUNET_NO == iret) && (nhops == i + 1))
9664 {
9665 /* we have better paths, and this is the longest target,
9666 so there cannot be anything interesting later */
9668 "# DV learn not forwarded, got better paths",
9669 1,
9670 GNUNET_NO);
9671 do_fwd = GNUNET_NO;
9672 break;
9673 }
9674 }
9675 }
9676 if (MAX_DV_HOPS_ALLOWED == nhops)
9677 {
9678 /* At limit, we're out of here! */
9679 return;
9680 }
9681
9682 /* Forward to initiator, if path non-trivial and possible */
9683 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
9684 did_initiator = GNUNET_NO;
9685 if ((1 <= nhops) &&
9686 (GNUNET_YES ==
9688 {
9689 /* send back to origin! */
9691 "Sending DVL back to initiator %s\n",
9692 GNUNET_i2s (&dvl->initiator));
9693 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
9694 did_initiator = GNUNET_YES;
9695 }
9696 /* We forward under two conditions: either we still learned something
9697 ourselves (do_fwd), or the path was darn short and thus the initiator is
9698 likely to still be very interested in this (and we did NOT already
9699 send it back to the initiator) */
9700 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
9701 (GNUNET_NO == did_initiator)))
9702 {
9703 /* Pick random neighbours that are not yet on the path */
9704 struct NeighbourSelectionContext nsc;
9705 unsigned int n_cnt;
9706 unsigned int n_eligible;
9707
9709 nsc.nhops = nhops;
9710 nsc.dvl = dvl;
9711 nsc.bi_history = bi_history;
9712 nsc.hops = hops;
9713 nsc.in_time = in_time;
9714 nsc.num_eligible = 0;
9717 &nsc);
9718 if (0 == nsc.num_eligible)
9719 return; /* done here, cannot forward to anyone else */
9720 n_eligible = nsc.num_eligible;
9721 nsc.num_selections = calculate_fork_degree (nhops, n_cnt, n_eligible);
9722 nsc.num_selections =
9725 "Forwarding DVL to %u other peers\n",
9726 nsc.num_selections);
9727 /* #dv_neighbour_transmission() counts ELIGIBLE peers only, so the
9728 offsets must be drawn from that range -- drawing from the total
9729 number of neighbours made us silently forward to fewer peers than
9730 #calculate_fork_degree() asked for. */
9731 for (unsigned int i = 0; i < nsc.num_selections; i++)
9732 nsc.selections[i] =
9733 (nsc.num_selections == n_eligible)
9734 ? i /* all were selected, avoid collisions by chance */
9735 : GNUNET_CRYPTO_random_u32 (n_eligible);
9736 nsc.num_eligible = 0;
9739 &nsc);
9740 }
9741}
9742
9743
9751static int
9752check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9753{
9754 uint16_t size = ntohs (dvb->header.size);
9755 uint16_t num_hops = ntohs (dvb->num_hops);
9756 uint16_t total_hops = ntohs (dvb->total_hops);
9757 uint16_t orig_size = ntohs (dvb->orig_size);
9758 const struct GNUNET_PeerIdentity *hops =
9759 (const struct GNUNET_PeerIdentity *) &dvb[1];
9760 const struct GNUNET_PeerIdentity *my_identity;
9761
9762 (void) cls;
9763 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
9764 + sizeof(struct GNUNET_MessageHeader))
9765 {
9766 GNUNET_break_op (0);
9767 return GNUNET_SYSERR;
9768 }
9769 if ((num_hops > MAX_DV_HOPS_ALLOWED) ||
9770 (total_hops > MAX_DV_HOPS_ALLOWED))
9771 {
9772 GNUNET_break_op (0);
9773 return GNUNET_SYSERR;
9774 }
9775 /* #decaps_dv_box_cb() derives a VLA size from
9776 orig_size - sizeof(*dvb) - total_hops * sizeof (struct
9777 GNUNET_PeerIdentity); make sure that cannot underflow and that the
9778 remainder can plausibly hold a payload header plus a message. */
9779 if ((orig_size < size) ||
9780 (orig_size < sizeof(*dvb)
9781 + total_hops * sizeof(struct GNUNET_PeerIdentity)
9782 + sizeof(struct TransportDVBoxPayloadP)
9783 + sizeof(struct GNUNET_MessageHeader)))
9784 {
9785 GNUNET_break_op (0);
9786 return GNUNET_SYSERR;
9787 }
9788
9791
9792 /* This peer must not be on the path */
9793 for (unsigned int i = 0; i < num_hops; i++)
9794 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9795 {
9796 GNUNET_break_op (0);
9797 return GNUNET_SYSERR;
9798 }
9799 return GNUNET_YES;
9800}
9801
9802
9815static void
9816forward_dv_box (struct Neighbour *next_hop,
9817 struct TransportDVBoxMessage *hdr,
9818 uint16_t total_hops,
9819 uint16_t num_hops,
9820 const struct GNUNET_PeerIdentity *hops,
9821 const void *enc_payload,
9822 uint16_t enc_payload_size)
9823{
9824 struct VirtualLink *vl = next_hop->vl;
9825 struct PendingMessage *pm;
9826 size_t msg_size = sizeof(struct TransportDVBoxMessage)
9827 + num_hops * sizeof(struct GNUNET_PeerIdentity)
9828 + enc_payload_size;
9829 char *buf;
9830 char msg_buf[msg_size] GNUNET_ALIGN;
9831 struct GNUNET_PeerIdentity *dhops;
9832
9833 hdr->num_hops = htons (num_hops);
9834 hdr->total_hops = htons (total_hops);
9835 hdr->header.size = htons (msg_size);
9836 memcpy (msg_buf, hdr, sizeof(*hdr));
9837 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
9839 ;
9840 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
9841 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
9842
9843 if (GNUNET_YES == ntohl (hdr->without_fc))
9844 {
9846 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
9847 enc_payload_size,
9848 GNUNET_i2s (&next_hop->pid),
9849 (unsigned int) num_hops,
9850 (unsigned int) total_hops);
9851 route_via_neighbour (next_hop, (const struct
9852 GNUNET_MessageHeader *) msg_buf,
9854 }
9855 else
9856 {
9857 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
9859 "2 created pm %p storing vl %p \n",
9860 pm,
9861 vl);
9862 pm->pmt = PMT_DV_BOX;
9863 pm->vl = vl;
9864 pm->target = next_hop->pid;
9868 pm->bytes_msg = msg_size;
9869 buf = (char *) &pm[1];
9870 memcpy (buf, msg_buf, msg_size);
9871
9873 "Created pending message %" PRIu64
9874 " for DV Box with next hop %s (%u/%u)\n",
9875 pm->logging_uuid,
9876 GNUNET_i2s (&next_hop->pid),
9877 (unsigned int) num_hops,
9878 (unsigned int) total_hops);
9879
9880 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9881 {
9883 vl->pending_msg_head,
9884 vl->pending_msg_tail,
9885 pm);
9886
9888 }
9889 else
9890 {
9892 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
9893
9895 {
9897
9898 GNUNET_free (pm_old);
9899 }
9902 {
9905 }
9906 else
9908
9910 "%u items stored in DV ring buffer\n",
9913 }
9914 }
9915}
9916
9917
9923static void
9925{
9926 if (NULL != b->get)
9927 {
9929 b->get = NULL;
9930 GNUNET_assert (NULL != b->cmc);
9932 b->cmc = NULL;
9933 }
9934 if (NULL != b->task)
9935 {
9937 b->task = NULL;
9938 }
9939 if (NULL != b->sc)
9940 {
9942 "store cancel\n");
9944 b->sc = NULL;
9945 }
9947 "Removing backtalker for %s\n",
9948 GNUNET_i2s (&b->pid));
9950 GNUNET_YES ==
9952 GNUNET_free (b);
9953}
9954
9955
9964static int
9966 const struct GNUNET_PeerIdentity *pid,
9967 void *value)
9968{
9969 struct Backtalker *b = value;
9970
9971 (void) cls;
9972 (void) pid;
9973 free_backtalker (b);
9974 return GNUNET_OK;
9975}
9976
9977
9983static void
9985{
9986 struct Backtalker *b = cls;
9987
9989 "backtalker timeout.\n");
9990 b->task = NULL;
9992 {
9994 return;
9995 }
9996 /* A monotime store may well still be in flight -- @e timeout is about how
9997 long the *peer* has been quiet, and says nothing about PEERSTORE. This
9998 used to `GNUNET_assert (NULL == b->sc)', which aborted the service in
9999 exactly that case. #free_backtalker() cancels the store. */
10000 free_backtalker (b);
10001}
10002
10003
10012static void
10014 const struct GNUNET_PEERSTORE_Record *record,
10015 const char *emsg)
10016{
10017 struct Backtalker *b = cls;
10018 struct GNUNET_TIME_AbsoluteNBO *mtbe;
10019 struct GNUNET_TIME_Absolute mt;
10020
10021 (void) emsg;
10022 if (NULL == record)
10023 {
10024 struct CommunicatorMessageContext *cmc;
10025
10026 /* we're done with #backtalker_monotime_cb() invocations,
10027 continue normal processing */
10028 b->get = NULL;
10029 GNUNET_assert (NULL != b->cmc);
10030 /* Take @e cmc out of @a b *before* dispatching: the dispatch runs
10031 arbitrary message handling, and writing `b->cmc = NULL' afterwards
10032 is a write to freed memory should anything on that path have
10033 released @a b. #free_backtalker() keys its "must finish the parked
10034 cmc" decision off @e get, which is already NULL here, so clearing
10035 @e cmc early cannot lose the message either. */
10036 cmc = b->cmc;
10037 b->cmc = NULL;
10038 cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
10039 if (0 != b->body_size)
10041 else
10042 finish_cmc_handling (cmc);
10043 return;
10044 }
10045 if (sizeof(*mtbe) != record->value_size)
10046 {
10048 GNUNET_break (0);
10049 return;
10050 }
10051 mtbe = record->value;
10052 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
10054 {
10056 "Backtalker message from %s dropped, monotime in the past\n",
10057 GNUNET_i2s (&b->pid));
10059 GST_stats,
10060 "# Backchannel messages dropped: monotonic time not increasing",
10061 1,
10062 GNUNET_NO);
10063 b->monotonic_time = mt;
10064 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
10065 */
10066 b->body_size = 0;
10067 }
10069}
10070
10071
10079static void
10080backtalker_monotime_store_cb (void *cls, int success)
10081{
10082 struct Backtalker *b = cls;
10083
10084 if (GNUNET_OK != success)
10085 {
10087 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
10088 }
10089 b->sc = NULL;
10090 /* @e task is armed for the whole life of @a b -- #backtalker_timeout_cb()
10091 re-arms itself whenever @e timeout has moved forward -- so there is
10092 nothing to do here beyond releasing the store. It used to cancel and
10093 re-add the task, which is what made the task's existence depend on this
10094 callback ever running. */
10095 GNUNET_assert (NULL != b->task);
10096}
10097
10098
10104static void
10106{
10107 struct GNUNET_TIME_AbsoluteNBO mtbe;
10108
10109 /* At most one store may be outstanding. The value we are about to write
10110 supersedes whatever the previous one carried, and leaving the old
10111 context alive means its completion clears @e sc while the newer store
10112 is still in flight -- after which the next update sees a NULL @e sc and
10113 starts a third one. Cancelling is also what keeps @e sc from being
10114 silently overwritten and leaked.
10115
10116 Note what this must NOT do: touch @e task. That task is the only thing
10117 that ever releases a `struct CommunicatorMessageContext' parked in
10118 @e cmc, and cancelling it here left its re-arming up to
10119 #backtalker_monotime_store_cb() -- i.e. up to PEERSTORE answering. A
10120 lost store completion then stalled the parked communicator client for
10121 the life of the process. #backtalker_timeout_cb() already re-arms
10122 itself against the current @e timeout, so the task needs no help. */
10123 if (NULL != b->sc)
10124 {
10126 "Superseding in-flight backtalker monotime store %p\n",
10127 b->sc);
10129 b->sc = NULL;
10130 }
10132 b->sc =
10134 "transport",
10135 &b->pid,
10137 &mtbe,
10138 sizeof(mtbe),
10142 b);
10143}
10144
10145
10154static void
10156 const struct TransportDVBoxMessage *dvb,
10157 const struct GNUNET_ShortHashCode *km)
10158{
10159 const unsigned char *hdr;
10160 size_t hdr_len;
10162
10163 key = (struct GNUNET_CRYPTO_AeadSecretKey*) km;
10164 /* We are the ultimate target, so #handle_dv_box() has established that no
10165 hop entries are left: the ciphertext directly follows the header, and
10166 its length is what we actually received. Deriving it from orig_size
10167 and total_hops instead would only be equivalent if every forwarder
10168 accounted its skipped hops exactly. */
10169 hdr = (const unsigned char *) &dvb[1];
10170 {
10171 uint16_t size = ntohs (dvb->header.size);
10172
10173 if (size < sizeof(*dvb)
10174 + sizeof(struct TransportDVBoxPayloadP)
10175 + sizeof(struct GNUNET_MessageHeader))
10176 {
10177 GNUNET_break_op (0);
10178 finish_cmc_handling (cmc);
10179 return;
10180 }
10181 hdr_len = size - sizeof(*dvb);
10182 }
10183
10184 /* begin actual decryption */
10185 {
10186 struct Backtalker *b;
10187 struct GNUNET_TIME_Absolute monotime;
10188 struct TransportDVBoxPayloadP *ppay;
10189 unsigned char pt[hdr_len + sizeof *ppay] GNUNET_ALIGN;
10190 unsigned char *body;
10191 const struct GNUNET_MessageHeader *mh;
10192
10193 ppay = (struct TransportDVBoxPayloadP *) pt;
10194 body = &pt[sizeof *ppay];
10195 GNUNET_assert (hdr_len >=
10196 sizeof(*ppay) + sizeof(struct GNUNET_MessageHeader));
10197 if (GNUNET_OK != GNUNET_CRYPTO_aead_decrypt (hdr_len,
10198 hdr,
10199 0,
10200 NULL,
10201 key,
10202 &dvb->iv,
10203 &dvb->mac,
10204 pt))
10205 {
10207 "Error decrypting DV payload header\n");
10208 GNUNET_break_op (0);
10209 finish_cmc_handling (cmc);
10210 return;
10211 }
10212 mh = (const struct GNUNET_MessageHeader *) body;
10213 /* NOTE: this used to compare against `sizeof (body)', i.e. the size of
10214 a pointer, which meant only 8-byte payloads were ever accepted. */
10215 if (ntohs (mh->size) != hdr_len - sizeof(*ppay))
10216 {
10217 GNUNET_break_op (0);
10218 finish_cmc_handling (cmc);
10219 return;
10220 }
10221 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
10222 switch (ntohs (mh->type))
10223 {
10225 GNUNET_break_op (0);
10226 finish_cmc_handling (cmc);
10227 return;
10228
10230 GNUNET_break_op (0);
10231 finish_cmc_handling (cmc);
10232 return;
10233
10234 default:
10235 /* permitted, continue */
10236 break;
10237 }
10238 monotime = GNUNET_TIME_absolute_ntoh (ppay->monotonic_time);
10240 "Decrypted backtalk from %s\n",
10241 GNUNET_i2s (&ppay->sender));
10243 &ppay->sender);
10244 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
10245 {
10247 GST_stats,
10248 "# Backchannel messages dropped: monotonic time not increasing",
10249 1,
10250 GNUNET_NO);
10251 finish_cmc_handling (cmc);
10252 return;
10253 }
10254 if ((NULL == b) ||
10255 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
10256 {
10257 /* Check signature */
10258 const struct GNUNET_PeerIdentity *my_identity;
10259 struct EphemeralConfirmationPS ec;
10260
10263
10265 ec.target = *my_identity;
10266 ec.ephemeral_key = dvb->ephemeral_key;
10267 ec.purpose.size = htonl (sizeof(ec));
10269 if (
10270 GNUNET_OK !=
10273 &ec,
10274 &ppay->sender_sig,
10275 &ppay->sender.public_key))
10276 {
10277 /* Signature invalid, discard! */
10278 GNUNET_break_op (0);
10279 finish_cmc_handling (cmc);
10280 return;
10281 }
10282 }
10283 /* Update sender, we now know the real origin! */
10285 "DVBox received for me from %s via %s\n",
10286 GNUNET_i2s2 (&ppay->sender),
10287 GNUNET_i2s (&cmc->im.sender));
10288 cmc->im.sender = ppay->sender;
10289
10290 if (NULL != b)
10291 {
10292 /* update key cache and mono time */
10293 b->last_ephemeral = dvb->ephemeral_key;
10294 b->monotonic_time = monotime;
10296 b->timeout =
10298 cmc->mh = mh;
10300 return;
10301 }
10302 /* setup data structure to cache signature AND check
10303 monotonic time with PEERSTORE before forwarding backchannel payload */
10304 b = GNUNET_malloc (sizeof(struct Backtalker) + (hdr_len - sizeof(*ppay)));
10305 b->pid = ppay->sender;
10306 b->body_size = hdr_len - sizeof(*ppay);
10307 memcpy (&b[1], body, hdr_len - sizeof(*ppay));
10311 &b->pid,
10312 b,
10314 b->monotonic_time = monotime; /* NOTE: to be checked still! */
10315 b->cmc = cmc;
10316 b->timeout =
10319 b->get =
10321 "transport",
10322 &b->pid,
10325 b);
10326 } /* end actual decryption */
10327}
10328
10329
10337static void
10338handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
10339{
10340 struct CommunicatorMessageContext *cmc = cls;
10341 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
10342 uint16_t num_hops = ntohs (dvb->num_hops);
10343 const struct GNUNET_PeerIdentity *hops =
10344 (const struct GNUNET_PeerIdentity *) &dvb[1];
10345 const char *enc_payload = (const char *) &hops[num_hops];
10346 uint16_t enc_payload_size =
10347 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
10348 const struct GNUNET_PeerIdentity *my_identity;
10349
10352
10353 if (GNUNET_EXTRA_LOGGING > 0)
10354 {
10355 char *path;
10356
10358 for (unsigned int i = 0; i < num_hops; i++)
10359 {
10360 char *tmp;
10361
10362 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
10363 GNUNET_free (path);
10364 path = tmp;
10365 }
10367 "Received DVBox with remaining path %s\n",
10368 path);
10369 GNUNET_free (path);
10370 }
10371
10372 if (num_hops > 0)
10373 {
10374 /* We're trying from the end of the hops array, as we may be
10375 able to find a shortcut unknown to the origin that way */
10376 for (int i = num_hops - 1; i >= 0; i--)
10377 {
10378 struct Neighbour *n;
10379
10380 if (0 == GNUNET_memcmp (&hops[i], my_identity))
10381 {
10382 GNUNET_break_op (0);
10383 finish_cmc_handling (cmc);
10384 return;
10385 }
10386 n = lookup_neighbour (&hops[i]);
10387 if (NULL == n)
10388 continue;
10390 "Skipping %u/%u hops ahead while routing DV Box\n",
10391 i,
10392 num_hops);
10393
10394 forward_dv_box (n,
10395 (struct TransportDVBoxMessage *) dvb,
10396 /* we strip i+1 entries, and the receiver reconstructs
10397 the ciphertext offset from total_hops */
10398 ntohs (dvb->total_hops) + i + 1,
10399 num_hops - i - 1, /* number of hops left */
10400 &hops[i + 1], /* remaining hops */
10401 enc_payload,
10402 enc_payload_size);
10404 "# DV hops skipped routing boxes",
10405 i,
10406 GNUNET_NO);
10408 "# DV boxes routed (total)",
10409 1,
10410 GNUNET_NO);
10411 finish_cmc_handling (cmc);
10412 return;
10413 }
10414 /* Woopsie, next hop not in neighbours, drop! */
10416 "# DV Boxes dropped: next hop unknown",
10417 1,
10418 GNUNET_NO);
10419 finish_cmc_handling (cmc);
10420 return;
10421 }
10422 /* We are the target. Unbox and handle message. */
10424 "# DV boxes opened (ultimate target)",
10425 1,
10426 GNUNET_NO);
10427 cmc->total_hops = ntohs (dvb->total_hops);
10428
10429 {
10430 // DH key derivation with received DV, could be garbage.
10432 struct GNUNET_ShortHashCode km;
10433
10435 if ( (NULL == my_private_key) ||
10436 (GNUNET_OK !=
10438 &dvb->ephemeral_key,
10439 &km)) )
10440 {
10441 GNUNET_break_op (0);
10442 finish_cmc_handling (cmc);
10443 return;
10444 }
10445 decaps_dv_box_cont (cmc,
10446 dvb,
10447 &km);
10448 }
10449}
10450
10451
10459static int
10461 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10462{
10463 struct TransportClient *tc = cls;
10464
10465 if (CT_COMMUNICATOR != tc->type)
10466 {
10467 GNUNET_break (0);
10468 return GNUNET_SYSERR;
10469 }
10471 return GNUNET_OK;
10472}
10473
10474
10479{
10483 const char *address;
10484
10489};
10490
10491
10501static int
10503 const struct GNUNET_PeerIdentity *pid,
10504 void *value)
10505{
10506 struct CheckKnownAddressContext *ckac = cls;
10507 struct ValidationState *vs = value;
10508
10509 (void) pid;
10510 if (0 != strcmp (vs->address, ckac->address))
10511 return GNUNET_OK;
10512 ckac->vs = vs;
10513 return GNUNET_NO;
10514}
10515
10516
10522static void
10523validation_start_cb (void *cls);
10524
10525
10533static void
10535 struct GNUNET_TIME_Absolute new_time)
10536{
10538 struct ValidationState *next;
10539
10540 /* NOTE: "be lazy" must not apply while #validation_task is unset. Our
10541 only caller that can leave it unset is #validation_start_cb(), which
10542 NULLs it on entry and relies on us to arm it again -- and nothing else
10543 ever does. Returning early there stops address (re)validation and the
10544 #suggest_to_connect() retries that go with it for *every* peer, for
10545 good. */
10546 if ((new_time.abs_value_us == vs->next_challenge.abs_value_us) &&
10547 (NULL != validation_task) &&
10548 (NULL != vs->hn))
10549 return; /* be lazy */
10550 vs->next_challenge = new_time;
10551 if (NULL == vs->hn)
10552 vs->hn =
10554 else
10557 (NULL != validation_task))
10558 return;
10559 if (NULL != validation_task)
10561 /* Arm for the earliest entry in the heap, which need NOT be @a vs:
10562 #validation_start_cb() calls us with @e validation_task unset and with
10563 @a vs already pushed out to its new @e challenge_backoff, which doubles
10564 up to #MAX_VALIDATION_CHALLENGE_FREQ (one day) while an address stays
10565 unanswered. Arming for @a vs there parks the single global validation
10566 task for that long, no matter how many other addresses are due right
10567 now -- and every address of a peer we cannot reach (NAT) is such an
10568 address. Everything that needs a validation then stops with it:
10569 bringing a lost link back up, and confirming the link to a peer that
10570 contacted us. */
10572 if (NULL == next)
10573 return;
10574 /* randomize a bit */
10579 delta),
10581 NULL);
10582}
10583
10584
10595static enum GNUNET_GenericReturnValue
10597 const struct GNUNET_PeerIdentity *pid,
10598 void *value)
10599{
10600 struct ValidationState *vs = value;
10601 const struct GNUNET_TIME_Absolute now =
10603
10604 (void) cls;
10605 (void) pid;
10606 /* What #start_address_validation() does for an address it hears about
10607 again, but without needing the address string. */
10608 vs->challenge_backoff =
10611 vs->challenge_backoff,
10612 2));
10613 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
10614 vs->first_challenge_use = now;
10617 vs->challenge_backoff));
10618 return GNUNET_OK;
10619}
10620
10621
10628static void
10630 const char *address)
10631{
10632 struct GNUNET_TIME_Absolute now;
10633 struct ValidationState *vs;
10634 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
10635
10637 pid,
10639 &ckac);
10641 if (NULL != (vs = ckac.vs))
10642 {
10643 const struct VirtualLink *vl = lookup_virtual_link (pid);
10644
10645 /* Speed up retrying the validation if 'vs' is not currently valid, or if
10646 * we have no confirmed virtual link to @a pid. In the latter case the
10647 * address may still be well inside its validity window -- but the link is
10648 * down, and #handle_validation_response() is the only thing that can
10649 * rebuild it and tell CORE about the peer again. Without this we would
10650 * wait for @e revalidation_task, which does not fire until
10651 * #ADDRESS_VALIDATION_LIFETIME is nearly over. */
10652 if ((vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us) ||
10653 (NULL == vl) ||
10654 (GNUNET_NO == vl->confirmed))
10655 {
10656 /* reduce backoff as we got a fresh advertisement */
10657 vs->challenge_backoff =
10660 vs->challenge_backoff,
10661 2));
10662 /* A successful validation parks @e first_challenge_use just before
10663 @e validated_until, so that the *next* challenge is not used before
10664 the current validation is about to expire. #validation_start_cb()
10665 refuses to run while that time is still in the future, so pulling
10666 @e next_challenge in without this would only make it reschedule
10667 itself four hours out. The challenge has not been used yet, so
10668 moving the start of its window to now stays truthful -- it is what
10669 the fresh-@a vs path below does as well. */
10670 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
10671 vs->first_challenge_use = now;
10674 vs->challenge_backoff));
10675 }
10676 return;
10677 }
10678 vs = GNUNET_new (struct ValidationState);
10679 vs->pid = *pid;
10680 vs->valid_until =
10682 vs->first_challenge_use = now;
10683 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
10684 GNUNET_CRYPTO_random_block (&vs->challenge,
10685 sizeof(vs->challenge));
10686 vs->address = GNUNET_strdup (address);
10687 {
10688 /* The peer identity MUST be part of @e hc: two peers behind the same NAT
10689 advertise the very same address string (`PROTO-IP:0'), and with an
10690 address-only key the second one's #revalidation_map entry would be
10691 rejected as a duplicate of the first one's. */
10692 struct GNUNET_HashContext *hsh;
10693
10695 GNUNET_CRYPTO_hash_context_read (hsh, vs->address, strlen (vs->address));
10696 GNUNET_CRYPTO_hash_context_read (hsh, &vs->pid, sizeof(vs->pid));
10697 GNUNET_CRYPTO_hash_context_finish (hsh, &vs->hc);
10698 }
10700 "Starting address validation `%s' of peer %s using challenge %s\n",
10701 address,
10702 GNUNET_i2s (pid),
10703 GNUNET_sh2s (&vs->challenge.value));
10707 &vs->pid,
10708 vs,
10711}
10712
10713
10714static struct Queue *
10715find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
10716
10717
10718static void
10719suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
10720
10721
10722static void
10724 const struct GNUNET_PeerIdentity *pid,
10725 const char *uri)
10726{
10727 struct Queue *q;
10728 int pfx_len;
10729 const char *eou;
10730 char *address;
10731 (void) cls;
10732
10733 eou = strstr (uri,
10734 "://");
10735 if ((NULL == eou) || (eou == uri))
10736 {
10737 /* @a uri comes from a HELLO some remote peer published. */
10738 GNUNET_break_op (0);
10739 return;
10740 }
10741 pfx_len = eou - uri;
10742 eou += 3;
10744 "%.*s-%s",
10745 pfx_len,
10746 uri,
10747 eou);
10748
10750 "helo for client %s\n",
10751 address);
10752 q = find_queue (pid, address);
10753 if (NULL == q)
10754 {
10756 }
10757 else
10760}
10761
10762
10785static const struct GNUNET_MessageHeader *
10787{
10788 const struct GNUNET_MessageHeader *hello;
10789
10790 if ((NULL == record) ||
10791 (NULL == record->value) ||
10792 (record->value_size < sizeof(*hello)))
10793 {
10794 GNUNET_break_op (0);
10795 return NULL;
10796 }
10797 hello = record->value;
10798 if (ntohs (hello->size) > record->value_size)
10799 {
10800 GNUNET_break_op (0);
10801 return NULL;
10802 }
10803 return hello;
10804}
10805
10806
10814static void
10816 const struct GNUNET_PEERSTORE_Record *record,
10817 const char *emsg)
10818{
10819 struct IncomingRequest *ir = cls;
10820 struct GNUNET_HELLO_Parser *parser;
10821 const struct GNUNET_MessageHeader *hello;
10822 const struct GNUNET_PeerIdentity *my_identity;
10823
10824 if (NULL != emsg)
10825 {
10827 "Got failure from PEERSTORE: %s\n",
10828 emsg);
10830 return;
10831 }
10832 if (NULL == record)
10833 {
10834 GNUNET_break (0);
10836 return;
10837 }
10838 hello = hello_from_record (record);
10839 if (NULL == hello)
10840 {
10841 /* MUST still ask for the next record: a bad one is not a reason to
10842 stall this monitor forever. */
10844 return;
10845 }
10847 if (NULL == my_identity)
10848 {
10850 return;
10851 }
10852 if (0 == GNUNET_memcmp (&record->peer, my_identity))
10853 {
10855 return;
10856 }
10857 if (0 != GNUNET_memcmp (&record->peer, &ir->pid))
10858 {
10859 /* Not the peer this request is about. */
10861 return;
10862 }
10863 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10864 if (NULL != parser)
10865 {
10868 NULL);
10869 GNUNET_HELLO_parser_free (parser);
10870 }
10871 /* MUST ask for the next record, or this monitor stalls after one HELLO */
10873}
10874
10875
10876static void
10878{
10880 "Error in PEERSTORE monitoring\n");
10881}
10882
10883
10884static void
10886{
10888 "Done with initial PEERSTORE iteration during monitoring\n");
10889}
10890
10891
10900static void
10902{
10903 struct Neighbour *n;
10904 struct IncomingRequest *ir;
10905
10906 if (GNUNET_YES == in_shutdown)
10907 return;
10908 /* (1) Addresses we already track. These outlive the queues, which is the
10909 point: once a link is down the queue that carried it is usually gone,
10910 so there is no address string left for #start_address_validation(). */
10912 pid,
10914 NULL);
10915 /* (2) Queues we still have; may cover an address with no validation state
10916 yet. After (1), because it may insert into #validation_map. */
10917 n = lookup_neighbour (pid);
10918 if (NULL != n)
10919 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
10920 start_address_validation (pid, q->address);
10921 /* (3) Failing that, look for an address in PEERSTORE. */
10922 for (ir = ir_head; NULL != ir; ir = ir->next)
10923 {
10924 if (0 == GNUNET_memcmp (&ir->pid, pid))
10925 return; /* we are already trying */
10926 }
10927 ir = GNUNET_new (struct IncomingRequest);
10928 ir->pid = *pid;
10930 /* Monitor only @a pid: with NULL every request sees every HELLO in
10931 PEERSTORE, so each of the up to #MAX_INCOMING_REQUEST requests started
10932 a connection attempt and an address validation for peers it was not
10933 created for. */
10935 GNUNET_YES,
10936 "peerstore",
10937 &ir->pid,
10940 NULL,
10942 NULL,
10944 ir);
10945 ir_total++;
10946 /* Bound attempts we do in parallel here, might otherwise get excessive.
10947 Drop the OLDEST request: #ir_head is the one we just inserted, so
10948 freeing that would immediately undo the work above. */
10951}
10952
10953
10961static void
10964{
10965 struct VirtualLink *vl;
10966 struct Neighbour *n;
10967 struct GNUNET_PeerIdentity sender;
10968
10969 sender = cmc->im.sender;
10970 vl = lookup_virtual_link (&sender);
10971 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
10972 {
10973 // route_control_message_without_fc (&cmc->im.sender,
10975 &tvr.header,
10977 }
10978 else
10979 {
10980 /* Use route via neighbour */
10981 n = lookup_neighbour (&sender);
10982 if (NULL != n)
10983 route_via_neighbour (n, &tvr.header,
10986 }
10987
10988 finish_cmc_handling (cmc);
10989 /* An *unconfirmed* link is not a link -- it carries nothing, and CORE has
10990 never been told about the peer. Bailing out on one merely because it
10991 exists is what deadlocks a pair of peers into permanent one-way state:
10992 the challenger validated us, so it believes the connection is up and
10993 starts sending us FLOW_CONTROL; #handle_flow_control() answers an
10994 unknown sender by allocating exactly such an unconfirmed link; and from
10995 then on every challenge it retransmits lands here, gets a response --
10996 which keeps *its* side confirmed and its RTT healthy -- and returns
10997 without ever validating an address of its own. The unconfirmed link
10998 reaps itself after #UNCONFIRMED_LINK_TIMEOUT, but the next FLOW_CONTROL
10999 recreates it, and the peer keeps sending those precisely because it
11000 thinks it is connected. Nothing ever breaks the tie, so CORE on this
11001 side never hears about the peer and never answers its handshake.
11002 Only a confirmed link means there is nothing left to do. */
11003 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
11004 return;
11005
11006 /* For us, the link is still down, but we need bi-directional
11007 connections (for flow-control and for this to be useful for
11008 CORE), so we must try to bring the link up! */
11009 try_to_bring_link_up (&sender);
11010}
11011
11012
11021static void
11023 void *cls,
11024 const struct TransportValidationChallengeMessage *tvc)
11025{
11026 struct CommunicatorMessageContext *cmc = cls;
11027 struct TransportValidationResponseMessage tvr = { 0 };
11028 struct GNUNET_TIME_RelativeNBO validity_duration;
11029
11030 /* DV-routed messages are not allowed for validation challenges */
11031 if (cmc->total_hops > 0)
11032 {
11033 GNUNET_break_op (0);
11034 finish_cmc_handling (cmc);
11035 return;
11036 }
11037 validity_duration = cmc->im.expected_address_validity;
11039 "Received address validation challenge %s\n",
11040 GNUNET_sh2s (&tvc->challenge.value));
11041 /* If we have a virtual link, we use this mechanism to signal the
11042 size of the flow control window, and to allow the sender
11043 to ask for increases. If for us the virtual link is still down,
11044 we will always give a window size of zero. */
11045 tvr.header.type =
11047 tvr.header.size = htons (sizeof(tvr));
11048 tvr.reserved = htonl (0);
11049 tvr.challenge = tvc->challenge;
11050 tvr.origin_time = tvc->sender_time;
11051 tvr.validity_duration = validity_duration;
11052 {
11053 /* create signature */
11054 struct TransportValidationPS tvp = {
11056 .purpose.size = htonl (sizeof(tvp)),
11057 .validity_duration = validity_duration,
11058 .challenge = tvc->challenge
11059 };
11060 if (GNUNET_OK != sign_by_my_identity (&tvp.purpose, &tvr.signature))
11061 {
11062 /* Not answering costs us this address validation; leaving @a cmc
11063 behind would cost us the communicator. */
11064 finish_cmc_handling (cmc);
11065 return;
11066 }
11067 }
11068 send_t_validation_response (cmc, tvr);
11069}
11070
11071
11087
11088
11098static int
11100 const struct GNUNET_PeerIdentity *pid,
11101 void *value)
11102{
11103 struct CheckKnownChallengeContext *ckac = cls;
11104 struct ValidationState *vs = value;
11105
11106 (void) pid;
11107 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
11108 return GNUNET_OK;
11109 ckac->vs = vs;
11110 return GNUNET_NO;
11111}
11112
11113
11121static void
11122peerstore_store_validation_cb (void *cls, int success)
11123{
11124 struct ValidationState *vs = cls;
11125
11126 vs->sc = NULL;
11127 if (GNUNET_YES == success)
11128 return;
11130 "# Peerstore failed to store foreign address",
11131 1,
11132 GNUNET_NO);
11133}
11134
11135
11143static struct Queue *
11144find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
11145{
11146 struct Neighbour *n;
11147
11148 n = lookup_neighbour (pid);
11149 if (NULL == n)
11150 return NULL;
11151 for (struct Queue *pos = n->queue_head; NULL != pos;
11152 pos = pos->next_neighbour)
11153 {
11154 if (0 == strcmp (pos->address, address))
11155 return pos;
11156 }
11157 return NULL;
11158}
11159
11160
11176static struct Queue *
11177find_queue_by_ip (const struct GNUNET_PeerIdentity *pid, const char *address)
11178{
11179 struct Neighbour *n;
11180 struct Queue *ret = NULL;
11181 char *prefix;
11182 char *ip;
11183
11184 n = lookup_neighbour (pid);
11185 if (NULL == n)
11186 return NULL;
11189 if ((NULL == prefix) || (NULL == ip))
11190 {
11192 GNUNET_free (ip);
11193 return NULL;
11194 }
11195 for (struct Queue *pos = n->queue_head; NULL != pos;
11196 pos = pos->next_neighbour)
11197 {
11198 char *q_prefix = GNUNET_HELLO_address_to_prefix (pos->address);
11199 char *q_ip = get_address_without_port (pos->address);
11200
11201 /* Same communicator and same host -- only the port may differ. */
11202 if ((NULL != q_prefix) && (NULL != q_ip) &&
11203 (0 == strcmp (q_prefix, prefix)) &&
11204 (0 == strcmp (q_ip, ip)))
11205 ret = pos;
11206 GNUNET_free (q_prefix);
11207 GNUNET_free (q_ip);
11208 if (NULL != ret)
11209 break;
11210 }
11212 GNUNET_free (ip);
11213 return ret;
11214}
11215
11216
11217static void
11219
11220static void
11222{
11223 struct ValidationState *vs = cls;
11224 struct Queue *q;
11225 struct GNUNET_TIME_Absolute now;
11226
11227 vs->revalidation_task = NULL;
11228 q = find_queue (&vs->pid, vs->address);
11229 if (NULL == q)
11230 {
11231 now = GNUNET_TIME_absolute_get ();
11232 vs->awaiting_queue = GNUNET_YES;
11233 suggest_to_connect (&vs->pid, vs->address);
11235 }
11236 else
11238}
11239
11240
11241static enum GNUNET_GenericReturnValue
11243 void *cls,
11244 const struct GNUNET_HashCode *key,
11245 void *value)
11246{
11247 (void) cls;
11249 "Key in revalidate map %s \n",
11250 GNUNET_h2s (key));
11251 return GNUNET_YES;
11252}
11253
11254
11263static void
11265 void *cls,
11266 const struct TransportValidationResponseMessage *tvr)
11267{
11268 struct CommunicatorMessageContext *cmc = cls;
11269 struct ValidationState *vs;
11270 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
11271 .vs = NULL};
11272 struct GNUNET_TIME_Absolute origin_time;
11273 struct Queue *q;
11274 struct Neighbour *n;
11275 struct VirtualLink *vl;
11277 GST_cfg);
11278
11279 /* check this is one of our challenges */
11281 &cmc->im.sender,
11283 &ckac);
11284 if (NULL == (vs = ckac.vs))
11285 {
11286 /* This can happen simply if we 'forgot' the challenge by now,
11287 i.e. because we received the validation response twice */
11289 "# Validations dropped, challenge unknown",
11290 1,
11291 GNUNET_NO);
11293 "Validation response %s dropped, challenge unknown\n",
11294 GNUNET_sh2s (&tvr->challenge.value));
11295 finish_cmc_handling (cmc);
11296 return;
11297 }
11298
11299 /* sanity check on origin time */
11300 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
11301 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
11302 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
11303 {
11305 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
11306 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
11307 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
11308 GNUNET_break_op (0);
11309 finish_cmc_handling (cmc);
11310 return;
11311 }
11312
11313 {
11314 /* check signature */
11315 struct TransportValidationPS tvp = {
11317 .purpose.size = htonl (sizeof(tvp)),
11318 .validity_duration = tvr->validity_duration,
11319 .challenge = tvr->challenge
11320 };
11321
11322 if (
11323 GNUNET_OK !=
11325 &tvp,
11326 &tvr->signature,
11327 &cmc->im.sender.public_key))
11328 {
11329 GNUNET_break_op (0);
11330 finish_cmc_handling (cmc);
11331 return;
11332 }
11333 }
11334
11335 /* validity is capped by our willingness to keep track of the
11336 validation entry and the maximum the other peer allows */
11339 tvr->validity_duration),
11341 vs->validated_until =
11345 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
11346 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
11347 GNUNET_CRYPTO_random_block (&vs->challenge,
11348 sizeof(vs->challenge));
11349 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
11350 vs->validated_until,
11351 GNUNET_TIME_relative_multiply (vs->validation_rtt,
11353 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
11354 {
11356 "First challenge use is now %" PRIu64 " %s \n",
11357 vs->first_challenge_use.abs_value_us,
11358 GNUNET_sh2s (&vs->challenge.value));
11359 vs->first_challenge_use = now;
11360 }
11361 else
11363 "First challenge use is later %" PRIu64 " %s \n",
11364 vs->first_challenge_use.abs_value_us,
11365 GNUNET_sh2s (&vs->challenge.value));
11366 vs->last_challenge_use =
11367 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
11368 update_next_challenge_time (vs, vs->first_challenge_use);
11370 "Validation response %s from %s accepted, address valid until %s\n",
11371 GNUNET_sh2s (&tvr->challenge.value),
11372 GNUNET_i2s (&cmc->im.sender),
11374 /*memcpy (&hkey,
11375 &hc,
11376 sizeof (hkey));*/
11378 "Key %s for address %s map size %u contains %u\n",
11379 GNUNET_h2s (&vs->hc),
11380 vs->address,
11383 &vs->hc));
11384 /* NOTE: @e hc hashes the address only, so two `struct ValidationState's
11385 for different peers can collide here. That must not abort us. */
11386 if (GNUNET_YES !=
11389 &vs->hc,
11390 vs,
11393 "Address `%s' already tracked for revalidation\n",
11394 vs->address);
11397 NULL);
11398 vs->revalidation_task =
11403 "transport",
11404 &cmc->im.sender,
11406 vs->address,
11407 strlen (vs->address) + 1,
11408 vs->valid_until,
11411 vs);
11412 finish_cmc_handling (cmc);
11413
11414 /* Finally, we now possibly have a confirmed (!) working queue,
11415 update queue status (if queue still is around) */
11416 q = find_queue (&vs->pid, vs->address);
11417 if (NULL == q)
11418 {
11419 /* The challenge may have gone out on a queue whose address is not
11420 literally @e address: #check_validation_request_pending() matches on
11421 the IP alone, precisely so that a validation waiting for the NAT
11422 address `PROTO-IP:0' can be answered over the queue that the peer
11423 actually established from `PROTO-IP:port'. Insisting on an exact
11424 match here would silently discard that (successful!) validation and
11425 never bring the virtual link up. */
11426 q = find_queue_by_ip (&vs->pid, vs->address);
11427 }
11428 if (NULL == q)
11429 {
11431 "# Queues lost at time of successful validation",
11432 1,
11433 GNUNET_NO);
11434 return;
11435 }
11436 q->validated_until = vs->validated_until;
11437 q->pd.aged_rtt = vs->validation_rtt;
11438 n = q->neighbour;
11439 vl = lookup_virtual_link (&vs->pid);
11440 if (NULL == vl)
11441 {
11442 vl = GNUNET_new (struct VirtualLink);
11444 "Creating new virtual link %p to %s using direct neighbour!\n",
11445 vl,
11446 GNUNET_i2s (&vs->pid));
11447 vl->burst_addr = NULL;
11448 vl->confirmed = GNUNET_YES;
11449 vl->message_uuid_ctr =
11450 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
11451 vl->target = n->pid;
11455 /* What the peer will grant us in its very first FLOW_CONTROL anyway
11456 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
11457 Starting at zero instead means a link that is up, validated and
11458 working carries nothing at all until an FC round trip completes --
11459 and if the peer cannot answer, not ever. */
11463 links,
11464 &vl->target,
11465 vl,
11467 vl->n = n;
11468 n->vl = vl;
11469 q->idle = GNUNET_YES;
11470 vl->visibility_task =
11471 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
11473 /* We lacked a confirmed connection to the target
11474 before, so tell CORE about it (finally!) */
11477 }
11478 else
11479 {
11480 /* Link was already up, remember n is also now available and we are done */
11481 if (NULL == vl->n)
11482 {
11483 vl->n = n;
11484 n->vl = vl;
11485 if (GNUNET_YES == vl->confirmed)
11487 "Virtual link to %s could now also use direct neighbour!\n",
11488 GNUNET_i2s (&vs->pid));
11489 }
11490 else
11491 {
11492 GNUNET_assert (n == vl->n);
11493 }
11494 if (GNUNET_NO == vl->confirmed)
11495 {
11496 vl->confirmed = GNUNET_YES;
11497 q->idle = GNUNET_YES;
11498 vl->visibility_task =
11499 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
11501 /* We lacked a confirmed connection to the target
11502 before, so tell CORE about it (finally!) */
11505 }
11506 }
11507}
11508
11509
11515static void
11517 const struct GNUNET_TRANSPORT_IncomingMessage *im)
11518{
11519 struct TransportClient *tc = cls;
11520 struct Neighbour *n;
11521 struct CommunicatorMessageContext *cmc =
11523
11524 cmc->tc = tc;
11525 cmc->im = *im;
11527 "Received message with size %u and flow control id %" PRIu64
11528 " via communicator from peer %s\n",
11529 ntohs (im->header.size),
11530 im->fc_id,
11531 GNUNET_i2s (&im->sender));
11532 cmc->im.neighbour_sender = cmc->im.sender;
11533 /* A communicator got this straight from @a im->sender, so the queues to
11534 that neighbour demonstrably still work. This is what #check_link_down()
11535 uses to bound how long a communicator that stopped working (without
11536 telling us) can keep a virtual link -- and CORE -- fooled. */
11537 if (NULL != (n = lookup_neighbour (&im->sender)))
11539 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
11541}
11542
11543
11552static int
11554{
11555 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
11556 uint16_t msize = ntohs (fc->header.size);
11557 const char *tgnas;
11558 size_t avail;
11559 size_t off;
11560
11561 (void) cls;
11563 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
11564 ntohs (fc->header.size),
11565 ntohl (fc->size_of_addresses),
11566 ntohl (fc->number_of_addresses),
11567 sizeof(struct TransportFlowControlMessage),
11568 sizeof (struct TransportGlobalNattedAddress));
11569 if (0 == number_of_addresses)
11570 return GNUNET_OK;
11571 if (msize < sizeof(struct TransportFlowControlMessage))
11572 {
11573 GNUNET_break_op (0);
11574 return GNUNET_SYSERR;
11575 }
11576 avail = msize - sizeof(struct TransportFlowControlMessage);
11577 tgnas = (const char *) &fc[1];
11578 off = 0;
11579 /* Validate EVERY entry: checking only the aggregate size lets a single
11580 entry claim a bogus address_length and send #handle_flow_control()
11581 out of bounds. */
11582 for (unsigned int i = 0; i < number_of_addresses; i++)
11583 {
11584 const struct TransportGlobalNattedAddress *tgna;
11585 size_t alen;
11586
11587 if (avail - off < sizeof(struct TransportGlobalNattedAddress))
11588 {
11589 GNUNET_break_op (0);
11590 return GNUNET_SYSERR;
11591 }
11592 tgna = (const struct TransportGlobalNattedAddress *) &tgnas[off];
11593 off += sizeof(struct TransportGlobalNattedAddress);
11594 alen = ntohl (tgna->address_length);
11595 if (avail - off < alen)
11596 {
11597 GNUNET_break_op (0);
11598 return GNUNET_SYSERR;
11599 }
11600 off += alen;
11601 }
11602 return GNUNET_OK;
11603}
11604
11605
11606static struct GNUNET_TIME_Relative
11608{
11610 unsigned int n_hops = 0;
11611
11613 "calculate_rtt\n");
11614 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
11615 pos = pos->next_dv)
11616 {
11618 "calculate_rtt %lu\n",
11619 (unsigned long) pos->pd.aged_rtt.rel_value_us);
11620 n_hops++;
11622 aged_rtt, pos
11623 ->distance
11624 + 2), ret);
11625 }
11626
11627 if (0 == n_hops)
11629 return ret;
11630}
11631
11632
11633static void
11635 const struct GNUNET_PeerIdentity *pid,
11636 const char *uri)
11637{
11638 struct VirtualLink *vl = cls;
11639 const char *slash;
11640 char *address_uri;
11641 char *prefix;
11642 char *uri_without_port;
11643
11644 slash = strrchr (uri, '/');
11645 if ((NULL == slash) || (slash - uri < 2))
11646 {
11647 GNUNET_break_op (0); /* @a uri comes from a remote HELLO */
11648 return;
11649 }
11650 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
11651 slash++;
11652 GNUNET_asprintf (&address_uri,
11653 "%s-%s",
11654 prefix,
11655 slash);
11656
11657 uri_without_port = get_address_without_port (address_uri);
11659 "iterate_address_start_burst %s %s %s %s\n",
11660 (NULL == uri_without_port) ? "<unparsable>" : uri_without_port,
11661 uri,
11662 address_uri,
11663 slash);
11664 GNUNET_free (vl->burst_addr);
11665 if ((NULL != uri_without_port) &&
11666 (0 == strcmp (uri_without_port, slash)))
11667 vl->burst_addr = GNUNET_strdup (uri_without_port);
11668
11670 GNUNET_free (address_uri);
11671 GNUNET_free (uri_without_port);
11672}
11673
11674
11675static void
11677 const struct GNUNET_PEERSTORE_Record *record,
11678 const char *emsg)
11679{
11680 struct GNUNET_StartBurstCls *sb_cls = cls;
11681 struct VirtualLink *vl = sb_cls->vl;
11682 const struct GNUNET_MessageHeader *hello;
11683 struct GNUNET_HELLO_Parser *parser;
11684
11685 if (NULL != emsg)
11686 {
11688 "Got failure from PEERSTORE: %s\n",
11689 emsg);
11690 /* @a emsg comes with a NULL record, which means the iteration is over
11691 and PEERSTORE is releasing the context itself -- stopping it here as
11692 well would free it twice. Just drop our handle. */
11693 vl->ic = NULL;
11694 free_burst_cls (sb_cls);
11695 return;
11696 }
11697 if (NULL == record)
11698 {
11700 "Hello iteration end for %s\n",
11701 GNUNET_i2s (&vl->target));
11702 /* PEERSTORE destroys the context itself once it signals the end. */
11703 vl->ic = NULL;
11704 free_burst_cls (sb_cls);
11705 return;
11706 }
11707
11709 "check_for_burst_address\n");
11710 /* @a hello was published by a remote peer, it may well be malformed. */
11711 hello = hello_from_record (record);
11712 if (NULL != hello)
11713 {
11714 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
11715 if (NULL != parser)
11716 {
11719 vl);
11720 GNUNET_HELLO_parser_free (parser);
11721 }
11722 }
11723
11724 /* MUST clear @e ic: #GNUNET_PEERSTORE_iteration_stop() frees it, and
11725 #free_virtual_link() would otherwise stop it a second time. */
11726 if (NULL != vl->ic)
11727 {
11729 vl->ic = NULL;
11730 }
11731 free_burst_cls (sb_cls);
11732}
11733
11734
11735static void
11736burst_timeout (void *cls)
11737{
11739}
11740
11741
11742static void
11743start_burst (void *cls)
11744{
11745 struct GNUNET_StartBurstCls *sb_cls = cls;
11746 struct VirtualLink *vl = sb_cls->vl;
11747 struct GNUNET_TRANSPORT_StartBurst *sb;
11748 struct GNUNET_MQ_Envelope *env;
11749 char *uri_without_port = vl->burst_addr;
11750
11751 burst_task = NULL;
11752 burst_task_cls = NULL;
11753 if (NULL == uri_without_port)
11754 {
11755 /* Lost the address in the meantime, nothing to burst to. */
11756 free_burst_cls (sb_cls);
11757 return;
11758 }
11759 /*char buf[strlen (uri_without_port) + 1];
11760
11761 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
11762 buf[strlen (uri_without_port)] = '\0';*/
11763 env =
11765 strlen (uri_without_port) + 1,
11767 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
11768 sb->pid = vl->target;
11769 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
11770 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11771 {
11772 if (CT_COMMUNICATOR != tc->type)
11773 continue; /* MUST come first: the log below reads the union! */
11775 "iterate_address_start_burst client tc prefix %s\n",
11776 tc->details.communicator.address_prefix);
11777 if (GNUNET_YES == tc->details.communicator.can_burst)
11778 {
11780 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
11781 uri_without_port,
11782 strlen (uri_without_port),
11783 ntohs (sb->header.size),
11784 (unsigned long) sb_cls->rtt.rel_value_us);
11785 GNUNET_MQ_send (tc->mq, env);
11786 env = NULL; /* MQ took ownership */
11790 60),
11792 NULL);
11793 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
11794 break;
11795 }
11796 }
11797 if (NULL != env)
11799 free_burst_cls (sb_cls);
11800}
11801
11802
11809static void
11811{
11812 struct VirtualLink *vl = sb_cls->vl;
11813
11814 if (burst_task_cls == sb_cls)
11815 {
11816 if (NULL != burst_task)
11817 {
11819 burst_task = NULL;
11820 }
11821 burst_task_cls = NULL;
11822 }
11823 if ((NULL != vl) && (vl->sb_cls == sb_cls))
11824 vl->sb_cls = NULL;
11826}
11827
11828
11829static void
11830queue_burst (void *cls)
11831{
11832 struct GNUNET_StartBurstCls *sb_cls = cls;
11833 struct VirtualLink *vl = sb_cls->vl;
11834
11835 if (GNUNET_YES != use_burst)
11836 {
11837 /* MUST release: nobody else owns @a sb_cls, and #handle_flow_control()
11838 allocates one for every FLOW_CONTROL message we receive. */
11840 return;
11841 }
11843 "burst_task %p ready %s burst addr %s (%p)\n",
11844 burst_task,
11845 sb_cls->sync_ready ? "yes" : "no",
11846 vl->burst_addr,
11847 vl->burst_addr);
11848 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
11849 {
11850 /* Cancel the pending burst. Both closures (the scheduled task's and
11851 ours) are ours to release. */
11853
11855 burst_task = NULL;
11856 burst_task_cls = NULL;
11857 if ((NULL != pending) && (pending != sb_cls))
11859 free_burst_cls (sb_cls);
11860 return;
11861 }
11862 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
11863 )
11864 {
11866 &start_burst,
11867 sb_cls);
11868 burst_task_cls = sb_cls;
11869 }
11870 else if (NULL == vl->burst_addr)
11871 {
11872 if (NULL != vl->ic)
11873 {
11874 /* An address lookup is already running for this link; starting a
11875 second one would leak the first. */
11876 free_burst_cls (sb_cls);
11877 return;
11878 }
11880 "peerstore",
11881 &vl->target,
11884 sb_cls);
11885 }
11886 else
11887 {
11888 /* A burst is already running or already scheduled; we have no use for
11889 this closure. */
11890 free_burst_cls (sb_cls);
11891 }
11892}
11893
11894
11901static void
11903{
11904 struct VirtualLink *vl = cls;
11905
11906 vl->unconfirmed_timeout_task = NULL;
11907 if ((GNUNET_YES == vl->confirmed) ||
11908 (NULL != vl->n) ||
11909 (NULL != vl->dv))
11910 return; /* got promoted in the meantime, its owner will clean up */
11912 "Discarding unconfirmed virtual link to %s\n",
11913 GNUNET_i2s (&vl->target));
11915 "# Unconfirmed virtual links timed out",
11916 1,
11917 GNUNET_NO);
11918 free_virtual_link (vl);
11919}
11920
11921
11930static void
11932{
11933 struct CommunicatorMessageContext *cmc = cls;
11934 struct VirtualLink *vl;
11936 uint32_t seq;
11937 struct GNUNET_TIME_Absolute st;
11938 uint64_t os;
11939 uint64_t wnd;
11940 uint32_t random;
11941
11943 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
11944 vl = lookup_virtual_link (&cmc->im.sender);
11945 if (NULL == vl)
11946 {
11947 vl = GNUNET_new (struct VirtualLink);
11949 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
11950 vl,
11951 GNUNET_i2s (&cmc->im.sender));
11952 vl->burst_addr = NULL;
11953 vl->confirmed = GNUNET_NO;
11954 vl->message_uuid_ctr =
11955 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
11956 vl->target = cmc->im.sender;
11960 /* What the peer will grant us in its very first FLOW_CONTROL anyway
11961 (@e incoming_fc_window_size plus what we have sent, i.e. nothing).
11962 Starting at zero instead means a link that is up, validated and
11963 working carries nothing at all until an FC round trip completes --
11964 and if the peer cannot answer, not ever. */
11968 links,
11969 &vl->target,
11970 vl,
11972 /* Nothing else owns this link yet, so it must reap itself if it never
11973 becomes confirmed -- otherwise any peer can make us allocate
11974 VirtualLinks without bound. */
11978 vl);
11979 }
11980 if (GNUNET_YES != vl->confirmed)
11981 {
11982 /* The peer flow-controls us, so it has a confirmed link to us -- but an
11983 unconfirmed link carries nothing and is never reported to CORE. Only
11984 #handle_validation_response() breaks that tie, and nothing here used
11985 to ask for one, so the pair could sit one-way until the peer's own
11986 four hour revalidation came round. */
11988 }
11989 if (NULL != vl->n)
11990 {
11991 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
11992 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
11993 }
11994
11996 "remaining %lu timeout for neighbour %p\n",
11997 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
11998 rel_value_us,
11999 vl->n);
12000 if (NULL == vl->n ||
12001 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
12002 {
12003 struct GNUNET_TIME_Relative rtt;
12004 struct GNUNET_BurstSync burst_sync;
12005 struct GNUNET_StartBurstCls *bcls;
12006
12007 if (NULL != vl->sb_cls)
12008 {
12009 /* A burst attempt for this link is already in flight. Allocating a
12010 second closure would orphan the first one: @e sb_cls is how
12011 #free_virtual_link() finds (and cancels) the pending #burst_task,
12012 and a peer that just keeps sending us FLOW_CONTROL messages would
12013 otherwise make us leak one closure per message. */
12015 "Burst attempt to %s already pending\n",
12016 GNUNET_i2s (&vl->target));
12017 }
12018 else
12019 {
12020 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
12021 bcls->vl = vl;
12022 vl->sb_cls = bcls;
12023 if (NULL != vl->dv)
12024 rtt = calculate_rtt (vl->dv);
12025 else
12027 burst_sync.rtt_average = fc->rtt;
12028 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
12029 /* @e sync_ready of `struct GNUNET_BurstSync' is a host-order enum. */
12030 burst_sync.sync_ready =
12031 (enum GNUNET_GenericReturnValue) ntohl (fc->sync_ready);
12032
12033 /* NOTE: #GNUNET_is_burst_ready() does NOT invoke the task unless both
12034 RTT estimates are known and close; #queue_burst() is thus not
12035 guaranteed to run, which is why @e sb_cls stays owned by @a vl. */
12037 &burst_sync,
12038 &queue_burst,
12039 bcls);
12040 }
12041 }
12042 if (0 != ntohl (fc->number_of_addresses))
12043 {
12044 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
12045 const char *tgnas;
12046 unsigned int off = 0;
12047
12048 tgnas = (const char *) &fc[1];
12049
12050 for (unsigned int i = 0; i < number_of_addresses; i++)
12051 {
12052 struct TransportGlobalNattedAddress *tgna;
12053 char *addr;
12054 uint32_t address_length;
12055
12056 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
12057 addr = (char *) &tgna[1];
12058 address_length = ntohl (tgna->address_length);
12059 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
12060
12061 /* NOTE: the address is NOT 0-terminated (it comes straight off the
12062 wire), it must be printed with an explicit precision. */
12064 "received address %.*s length %u\n",
12065 (int) address_length,
12066 addr,
12068
12069 if (NULL != nh)
12070 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
12071 }
12072 }
12074 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
12075 {
12077 "FC dropped: Message out of order\n");
12078 /* out of order, drop */
12080 "# FC dropped: message out of order",
12081 1,
12082 GNUNET_NO);
12083 finish_cmc_handling (cmc);
12084 return;
12085 }
12086 seq = ntohl (fc->seq);
12087 if (seq < vl->last_fc_seq)
12088 {
12089 /* Wrap-around/reset of other peer; start all counters from zero */
12091 }
12092 vl->last_fc_seq = seq;
12093 vl->last_fc_timestamp = st;
12094 /* The peer is answering, so the backoff in #consider_sending_fc() starts
12095 over: @e fc_retransmit_count counts *unanswered* rounds. */
12096 vl->fc_retransmit_count = 0;
12098 os = GNUNET_ntohll (fc->outbound_sent);
12100 (int64_t) (os - vl->incoming_fc_window_size_used);
12102 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
12103 GNUNET_i2s (&vl->target),
12104 (unsigned int) seq,
12105 (unsigned long long) vl->outbound_fc_window_size,
12106 (long long) vl->incoming_fc_window_size_loss);
12108 random = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
12109 /* NOTE: this must NOT be restricted to a confirmed link. @e
12110 outbound_fc_window_size starts at zero and is raised *only* here, from
12111 the peer's FC. So a peer whose link to us is confirmed while ours to it
12112 is not cannot send us a single byte until we answer -- and it is exactly
12113 that peer that keeps asking. Staying quiet deadlocks the pair: it shows
12114 an established virtual link with messages pending forever, we show none,
12115 and CORE never completes its handshake in either direction. */
12116 if ((wnd < vl->incoming_fc_window_size
12120 (0 == random % FC_NO_CHANGE_REPLY_PROBABILITY))
12121 {
12123 "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",
12124 (unsigned long long) wnd,
12125 (unsigned long long) vl->incoming_fc_window_size,
12126 (unsigned long long) vl->last_outbound_window_size_received,
12129 }
12130 if ((wnd == vl->incoming_fc_window_size
12134 {
12136 "Slowing FC transmission to %s to keepalive rate: peer is current at window %llu\n",
12137 GNUNET_i2s (&vl->target),
12138 (unsigned long long) wnd);
12139 /* NOTE: this used to also require @e fc_retransmit_task to be non-NULL
12140 and did nothing at all otherwise -- so a link whose chain had ended
12141 (see #consider_sending_fc()) could never pick the keepalive back up,
12142 even though the peer was demonstrably still talking to us. */
12143 if (NULL != vl->fc_retransmit_task)
12145 vl->fc_retransmit_count = 0;
12146 /* Drop to the keepalive rate rather than stopping outright. There is
12147 nothing left to retransmit -- but if we go completely quiet, and the
12148 peer does the same for the same reason, then neither end sees any
12149 traffic and #check_link_down() tears down a perfectly healthy link
12150 after #NEIGHBOUR_LIVENESS_TIMEOUT. One tiny FC message every
12151 #FC_KEEPALIVE_INTERVAL is what keeps @e last_inbound moving on the
12152 other side (and, via their reply, on ours). */
12153 vl->fc_retransmit_task =
12156 vl);
12157 }
12159 /* FC window likely increased, check transmission possibilities! */
12161 finish_cmc_handling (cmc);
12162}
12163
12164
12172static void
12174{
12176 { GNUNET_MQ_hd_var_size (fragment_box,
12179 cmc),
12180 GNUNET_MQ_hd_var_size (reliability_box,
12183 cmc),
12184 GNUNET_MQ_hd_var_size (reliability_ack,
12187 cmc),
12188 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
12191 cmc),
12192 GNUNET_MQ_hd_var_size (dv_learn,
12195 cmc),
12196 GNUNET_MQ_hd_var_size (dv_box,
12198 struct TransportDVBoxMessage,
12199 cmc),
12200 GNUNET_MQ_hd_var_size (flow_control,
12203 cmc),
12205 validation_challenge,
12208 cmc),
12210 validation_response,
12213 cmc),
12215 int ret;
12216 const struct GNUNET_MessageHeader *msg = cmc->mh;
12217
12219 "Handling message of type %u with %u bytes\n",
12220 (unsigned int) ntohs (msg->type),
12221 (unsigned int) ntohs (msg->size));
12222 /* @a handlers only covers the encapsulations *we* add; anything else is a
12223 payload for CORE and leaves through #handle_raw_message() below. So
12224 #GNUNET_NO is the common case here -- one per delivered CORE message --
12225 and not something to log about, which is why this is the "try" variant. */
12227 if (GNUNET_SYSERR == ret)
12228 {
12229 /* @a msg is the message a *remote peer* sent us: #handle_incoming_msg()
12230 points @e mh into the payload of the
12231 #GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG the communicator
12232 delivered, and every other caller unwraps it from remote traffic as
12233 well. So failing a check here is that peer's protocol violation, and
12234 it says nothing at all about the communicator that carried it.
12235
12236 Dropping the client therefore punishes the wrong party, and it
12237 punishes it hard: #GNUNET_SERVICE_client_drop() disconnects the
12238 communicator *process*, which takes down every queue it owns and thus
12239 every neighbour reachable through it. One malformed DV box on a
12240 shared UDP communicator disconnects every peer we have on it, CORE
12241 tears the sessions down, and the key exchanges that would rebuild
12242 them have to wait for the communicator to come back and revalidate.
12243 Since the offending bytes arrive from the network, any peer can do
12244 this to us at will, repeatedly.
12245
12246 Drop the message and keep the communicator: resume it exactly as the
12247 success path does, so it still gets its flow-control ACK and its
12248 GNUNET_SERVICE_client_continue(). */
12249 GNUNET_break_op (0);
12251 "# malformed messages discarded",
12252 1,
12253 GNUNET_NO);
12255 return;
12256 }
12257 if (GNUNET_NO == ret)
12258 {
12259 /* unencapsulated 'raw' message */
12260 handle_raw_message (cmc, msg);
12261 }
12262}
12263
12264
12271static int
12273 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12274{
12275 struct TransportClient *tc = cls;
12276
12277 if (CT_COMMUNICATOR != tc->type)
12278 {
12279 GNUNET_break (0);
12280 return GNUNET_SYSERR;
12281 }
12283 return GNUNET_OK;
12284}
12285
12286
12292static void
12294{
12295 if (pm->msg_uuid_set)
12296 return;
12297 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
12299}
12300
12301
12310static struct PendingAcknowledgement *
12312 struct DistanceVectorHop *dvh,
12313 struct PendingMessage *pm)
12314{
12315 struct PendingAcknowledgement *pa;
12316
12317 pa = GNUNET_new (struct PendingAcknowledgement);
12318 pa->queue = queue;
12319 pa->dvh = dvh;
12320 pa->pm = pm;
12321 do
12322 {
12324 sizeof(pa->ack_uuid));
12325 }
12328 &pa->ack_uuid.value,
12329 pa,
12331 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
12333 if (NULL != dvh)
12336 pa->message_size = pm->bytes_msg;
12338 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
12340 pm->logging_uuid);
12341 return pa;
12342}
12343
12344
12356static struct PendingMessage *
12358 struct DistanceVectorHop *dvh,
12359 struct PendingMessage *pm)
12360{
12361 struct PendingAcknowledgement *pa;
12362 struct PendingMessage *ff;
12363 uint16_t mtu;
12364 uint16_t msize;
12365
12366 mtu = (UINT16_MAX == queue->mtu)
12367 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
12368 : queue->mtu;
12370 "Fragmenting message <%" PRIu64
12371 "> with size %u to %s for MTU %u\n",
12372 pm->logging_uuid,
12373 pm->bytes_msg,
12374 GNUNET_i2s (&pm->vl->target),
12375 (unsigned int) mtu);
12378 "Fragmenting message %" PRIu64 " <%" PRIu64
12379 "> with size %u to %s for MTU %u\n",
12380 pm->msg_uuid.uuid,
12381 pm->logging_uuid,
12382 pm->bytes_msg,
12383 GNUNET_i2s (&pm->vl->target),
12384 (unsigned int) mtu);
12385
12386 /* This invariant is established in #handle_add_queue_message() */
12387 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
12388
12389 /* select fragment for transmission, descending the tree if it has
12390 been expanded until we are at a leaf or at a fragment that is small
12391 enough
12392 */
12393 ff = pm;
12394 msize = ff->bytes_msg;
12395
12396 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
12397 (ff->frag_off == msize) && (NULL != ff->head_frag))
12398 {
12399 ff = ff->head_frag; /* descent into fragmented fragments */
12400 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
12401 }
12402
12403 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
12404 {
12405 /* Did not yet calculate all fragments, calculate next fragment */
12406 struct PendingMessage *frag;
12407 struct TransportFragmentBoxMessage tfb;
12408 const char *orig;
12409 char *msg;
12410 uint16_t fragmax;
12411 uint16_t fragsize;
12412 uint16_t msize_ff;
12413 uint16_t xoff = 0;
12414 pm->frag_count++;
12415
12416 orig = (const char *) &ff[1];
12417 msize_ff = ff->bytes_msg;
12418 if (pm != ff)
12419 {
12420 const struct TransportFragmentBoxMessage *tfbo;
12421
12422 tfbo = (const struct TransportFragmentBoxMessage *) orig;
12423 orig += sizeof(struct TransportFragmentBoxMessage);
12424 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
12425 xoff = ntohs (tfbo->frag_off);
12426 }
12427 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
12428 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
12429 frag =
12430 GNUNET_malloc (sizeof(struct PendingMessage)
12431 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
12433 "3 created pm %p from pm %p storing vl %p from pm %p\n",
12434 frag,
12435 ff,
12436 pm->vl,
12437 pm);
12439 frag->vl = pm->vl;
12440 frag->frag_parent = ff;
12441 frag->timeout = pm->timeout;
12442 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
12443 frag->pmt = PMT_FRAGMENT_BOX;
12444 msg = (char *) &frag[1];
12446 tfb.header.size =
12447 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
12448 pa = prepare_pending_acknowledgement (queue, dvh, frag);
12449 tfb.ack_uuid = pa->ack_uuid;
12450 tfb.msg_uuid = pm->msg_uuid;
12451 tfb.frag_off = htons (ff->frag_off + xoff);
12452 tfb.msg_size = htons (pm->bytes_msg);
12453 memcpy (msg, &tfb, sizeof(tfb));
12454 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
12456 ff->tail_frag, frag);
12457 ff->frag_off += fragsize;
12458 ff = frag;
12459 }
12460
12461 if (pm == ff)
12462 {
12463 /* Neither the descent nor the branch above moved us off @a pm, so there
12464 is no fragment to send: @e head_frag is empty *and* @e frag_off says
12465 everything was already cut. completed_pending_message() leaves
12466 exactly that state behind when the last outstanding fragment is
12467 acknowledged but its condition for finishing the root does not hold
12468 (@e frag_off having been advanced past the boxed payload size, or the
12469 root being a reliability box). The rotate below then dereferences
12470 @e frag_parent, which is NULL for the message on @e pending_msg_head.
12471
12472 Report "nothing to fragment" instead; the caller reschedules. */
12473 GNUNET_break (0);
12474 return NULL;
12475 }
12476 /* Move head to the tail and return it */
12480 ff);
12484 ff);
12485
12486 return ff;
12487}
12488
12489
12502static struct PendingMessage *
12504 struct DistanceVectorHop *dvh,
12505 struct PendingMessage *pm)
12506{
12508 struct PendingAcknowledgement *pa;
12509 struct PendingMessage *bpm;
12510 char *msg;
12511
12512 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
12513 return pm; /* already fragmented or reliability boxed, or control message:
12514 do nothing */
12515 if (NULL != pm->bpm)
12516 return pm->bpm; /* already computed earlier: do nothing */
12517 // TODO I guess we do not need this assertion. We might have a DLL with
12518 // fragments, because the MTU changed, and we do not need to fragment anymore.
12519 // But we should keep the fragments until message was completed, because
12520 // the MTU might change again.
12521 // GNUNET_assert (NULL == pm->head_frag);
12522 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
12523 {
12524 /* failed hard */
12525 GNUNET_break (0);
12527 return NULL;
12528 }
12529
12530 pa = prepare_pending_acknowledgement (queue, dvh, pm);
12531
12532 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
12533 + pm->bytes_msg);
12535 "4 created pm %p storing vl %p from pm %p\n",
12536 bpm,
12537 pm->vl,
12538 pm);
12540 bpm->vl = pm->vl;
12541 bpm->frag_parent = pm;
12542 // Why was this needed?
12543 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
12544 bpm->timeout = pm->timeout;
12546 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
12549 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
12550 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
12551
12552 rbox.ack_uuid = pa->ack_uuid;
12553 msg = (char *) &bpm[1];
12554 memcpy (msg, &rbox, sizeof(rbox));
12555 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
12556 pm->bpm = bpm;
12558 "Preparing reliability box for message <%" PRIu64
12559 "> of size %d (%d) to %s on queue %s\n",
12560 pm->logging_uuid,
12561 pm->bytes_msg,
12562 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
12563 GNUNET_i2s (&pm->vl->target),
12564 queue->address);
12565 return bpm;
12566}
12567
12568
12569static void
12572{
12573 struct VirtualLink *vl = pm->vl;
12574 struct PendingMessage *pos;
12575
12576 /* Only a message without a parent is on vl->pending_msg_head; anything
12577 else is not ours to reorder and MDLL_remove() would abort on it. */
12578 if ((NULL == vl) ||
12579 (NULL != pm->frag_parent) ||
12580 ((NULL == pm->prev_vl) && (vl->pending_msg_head != pm)))
12581 {
12582 GNUNET_break (0);
12583 return;
12584 }
12585 /* re-insert sort in neighbour list */
12589 pm);
12590 pos = vl->pending_msg_tail;
12591 while ((NULL != pos) &&
12593 pos = pos->prev_vl;
12597 pos,
12598 pm);
12599}
12600
12601
12602static unsigned int
12604{
12605 struct PendingMessage *pos;
12606 /* MUST be initialised: for a leaf the loop below never runs */
12608
12609 pos = pm->head_frag;
12610 while (NULL != pos)
12611 {
12613 GNUNET_NO == check_next_attempt_tree (pos, root))
12615 else
12616 {
12618 break;
12619 }
12620 pos = pos->next_frag;
12621 }
12622
12623 return frags_in_flight;
12624}
12625
12626
12627static void
12629{
12630 struct PendingMessage *pos;
12631
12632 pos = pm->head_frag;
12633 while (NULL != pos)
12634 {
12637 pos = pos->next_frag;
12638 }
12639}
12640
12641
12650static void
12653{
12654 if (NULL == pm->frag_parent)
12655 {
12658 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
12659 pm->logging_uuid,
12662 }
12663 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
12664 {
12665 struct PendingMessage *root = pm->frag_parent;
12666
12667 while (NULL != root->frag_parent)
12668 root = root->frag_parent;
12670 "Next attempt for root message <%" PRIu64 "> set to %s\n",
12671 root->logging_uuid,
12673 root->next_attempt = next_attempt;
12675 }
12676 else
12677 {
12678 struct PendingMessage *root = pm->frag_parent;
12679
12680 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
12681 root = root->frag_parent;
12682
12684 "frag_count next attempt %u\n",
12685 root->frag_count);
12686
12687 if (GNUNET_NO == root->frags_in_flight)
12688 {
12689 root->next_attempt = next_attempt;
12691 root->frags_in_flight_round++;
12693 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
12694 ">)set to %" PRIu64 "\n",
12695 pm->logging_uuid,
12696 root->logging_uuid,
12698 }
12699
12700 pm->next_attempt = root->next_attempt;
12703
12704 if (root->bytes_msg == root->frag_off)
12705 root->frags_in_flight = check_next_attempt_tree (root, root);
12706 else
12708
12709 if (GNUNET_NO == root->frags_in_flight)
12710 {
12711 /* `root' deliberately stops at a DV box, which is itself a child of
12712 the message on vl->pending_msg_head. Walk the rest of the way for
12713 the reorder: only the parentless message is on that list. */
12714 struct PendingMessage *vl_root = root;
12715
12716 while (NULL != vl_root->frag_parent)
12717 vl_root = vl_root->frag_parent;
12718 vl_root->next_attempt = root->next_attempt;
12720 "We have no fragments in flight for message %" PRIu64
12721 ", reorder root %" PRIu64 "! Next attempt is %" PRIu64 "\n",
12722 root->logging_uuid,
12723 vl_root->logging_uuid,
12724 vl_root->next_attempt.abs_value_us);
12725 reorder_root_pm (vl_root, vl_root->next_attempt);
12726 }
12727 else
12728 {
12729 double factor = ((double) root->frag_count - 1)
12730 / (double) root->frag_count;
12731 struct GNUNET_TIME_Relative s1;
12732 struct GNUNET_TIME_Relative s2;
12733 struct GNUNET_TIME_Relative plus_mean =
12736 next_attempt);
12737
12739 "frag_count %u after factor\n",
12740 root->frag_count);
12742 factor);
12743 s2 = GNUNET_TIME_relative_divide (plus,
12744 root->frag_count);
12745 plus_mean = GNUNET_TIME_relative_add (s1, s2);
12748 "We have fragments in flight for message %" PRIu64
12749 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
12750 root->logging_uuid,
12752 }
12753 }
12754}
12755
12756
12761{
12766
12771
12776
12781
12785 int frag;
12786
12790 int relb;
12791
12796
12800 unsigned int frags_in_flight;
12801
12806};
12807
12808
12820static void
12822 struct Queue *queue,
12823 struct VirtualLink *vl,
12824 struct DistanceVectorHop *dvh,
12825 size_t overhead)
12826{
12827 struct GNUNET_TIME_Absolute now;
12828
12829 now = GNUNET_TIME_absolute_get ();
12830 /* NOTE: @a sc accumulates across calls -- #transmit_on_queue() zeroes it
12831 once and then runs us for the direct link and for every DV hop in turn.
12832 Clearing the verdict here made each call discard what the previous ones
12833 found, so a message that was too early on the direct link was forgotten
12834 as soon as one DV hop had nothing to offer, and nothing rescheduled the
12835 queue at all. */
12836 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
12837 pos = pos->next_vl)
12838 {
12839 size_t real_overhead = overhead;
12840 int frag;
12841 int relb;
12842
12843 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
12844 {
12846 "DV messages must not be DV-routed to next hop!\n");
12847 continue; /* DV messages must not be DV-routed to next hop! */
12848 }
12849 if (pos->next_attempt.abs_value_us > now.abs_value_us)
12850 {
12851 if (GNUNET_YES == pos->frags_in_flight)
12852 {
12853 sc->frags_in_flight = GNUNET_YES;
12855 "Fragments in flight for message %" PRIu64 "\n",
12856 pos->logging_uuid);
12857 }
12858 else
12859 {
12861 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
12862 PRIu64 "\n",
12863 pos->logging_uuid);
12864 /* The *earliest* deadline is the one to come back for: @e
12865 pending_msg_head is sorted by @e next_attempt, so overwriting
12866 this on every iteration left the largest delay of the whole
12867 list -- the queue then slept past every message but the last
12868 one. Across the calls for the direct link and each DV hop the
12869 same argument applies, hence the min() rather than an
12870 assignment. */
12871 sc->to_early_retry_delay =
12872 (GNUNET_YES == sc->to_early)
12873 ? GNUNET_TIME_relative_min (sc->to_early_retry_delay,
12875 pos->next_attempt))
12876 : GNUNET_TIME_absolute_get_remaining (pos->next_attempt);
12877 sc->to_early = GNUNET_YES;
12878 continue;
12879 }
12880 // break; /* too early for all messages, they are sorted by next_attempt */
12881 }
12882 if (NULL != pos->qe)
12883 {
12885 "not eligible\n");
12886 continue; /* not eligible */
12887 }
12888 sc->consideration_counter++;
12889 /* determine if we have to fragment, if so add fragmentation
12890 overhead! */
12892 "check %" PRIu64 " for sc->best\n",
12893 pos->logging_uuid);
12894 frag = GNUNET_NO;
12895 if (((0 != queue->mtu) &&
12896 (pos->bytes_msg + real_overhead > queue->mtu)) ||
12897 (pos->bytes_msg > UINT16_MAX - sizeof(struct
12899 ||
12900 (NULL != pos->head_frag /* fragments already exist, should
12901 respect that even if MTU is UINT16_MAX for
12902 this queue */))
12903 {
12905 "fragment msg with size %u, realoverhead is %lu\n",
12906 pos->bytes_msg,
12907 real_overhead);
12908 frag = GNUNET_YES;
12909 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
12910 {
12911 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
12912 header without the ACK UUID when using a *reliable* channel! */
12913 }
12914 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
12915 }
12916 /* determine if we have to reliability-box, if so add reliability box
12917 overhead */
12918 relb = GNUNET_NO;
12919 if ((GNUNET_NO == frag) &&
12920 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
12921 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
12922 {
12923 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
12924
12925 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
12926 {
12927 frag = GNUNET_YES;
12928 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
12929 }
12930 else
12931 {
12932 relb = GNUNET_YES;
12933 }
12935 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
12936 pos->bytes_msg,
12937 real_overhead,
12938 queue->mtu,
12939 frag,
12940 relb);
12941 }
12942
12943 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
12944 message would beat it! */
12945 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
12946 {
12947 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
12948 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
12949 experimentally validated. There may be some huge potential for
12950 improvement here. Also, we right now only compare how well the
12951 given message fits _this_ queue, and do not consider how well other
12952 queues might suit the message. Taking other queues into consideration
12953 may further improve the result, but could also be expensive
12954 in terms of CPU time. */
12955 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
12956 long long pm_score = frag * 40 + relb * 20 + real_overhead;
12957 long long time_delta =
12958 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
12959 / 1000LL;
12960
12961 /* "time_delta" considers which message has been 'ready' for transmission
12962 for longer, if a message has a preference for low latency, increase
12963 the weight of the time_delta by 10x if it is favorable for that message */
12964 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
12965 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
12966 time_delta *= 10; /* increase weight (always, both are low latency) */
12967 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
12968 (time_delta > 0))
12969 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
12970 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
12971 (time_delta < 0))
12972 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
12973 if (0 != queue->mtu)
12974 {
12975 /* Grant bonus if we are below MTU, larger bonus the closer we will
12976 be to the MTU */
12977 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
12978 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
12979 if (queue->mtu > real_overhead + pos->bytes_msg)
12980 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
12981 }
12982 if (sc_score + time_delta > pm_score)
12983 {
12985 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
12986 "\n",
12987 pos->logging_uuid,
12988 sc->best->logging_uuid);
12989 continue; /* sc_score larger, keep sc->best */
12990 }
12991 }
12992 sc->best = pos;
12993 sc->dvh = dvh;
12994 sc->frag = frag;
12995 sc->relb = relb;
12996 sc->real_overhead = real_overhead;
12997 }
12998}
12999
13000
13011static void
13013 struct Neighbour *next_hop,
13014 const struct GNUNET_MessageHeader *hdr,
13016{
13017 struct PendingMessageScoreContext *sc = cls;
13018 struct PendingMessage *pm = sc->best;
13019 struct PendingMessage *bpm;
13020 uint16_t bsize = ntohs (hdr->size);
13021
13022 GNUNET_assert (NULL == pm->bpm);
13023 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
13025 "5 created pm %p storing vl %p from pm %p\n",
13026 bpm,
13027 pm->vl,
13028 pm);
13030 bpm->pmt = PMT_DV_BOX;
13031 bpm->vl = pm->vl;
13032 bpm->timeout = pm->timeout;
13033 bpm->bytes_msg = bsize;
13034 bpm->frag_parent = pm;
13037 "Creating DV Box %" PRIu64 " for original message %" PRIu64
13038 " (next hop is %s)\n",
13040 pm->logging_uuid,
13041 GNUNET_i2s (&next_hop->pid));
13042 memcpy (&bpm[1], hdr, bsize);
13043 pm->bpm = bpm;
13044}
13045
13046
13062static void
13064{
13065 struct Queue *queue = cls;
13066 struct Neighbour *n = queue->neighbour;
13068 struct PendingMessage *pm;
13069
13070 queue->transmit_task = NULL;
13071 if ((NULL == n->vl) && (NULL == n->dv_head))
13072 {
13074 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
13075 GNUNET_i2s (&n->pid),
13076 queue->address);
13077 queue->idle = GNUNET_YES;
13078 return;
13079 }
13080 memset (&sc, 0, sizeof(sc));
13081 /* @e n need not have a link of its own: it may serve only as the first
13082 hop of DV paths, and the traffic queued for those still has to go out. */
13083 if (NULL != n->vl)
13084 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
13085 if (NULL == sc.best)
13086 {
13087 /* Also look at DVH that have the n as first hop! */
13088 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
13089 dvh = dvh->next_neighbour)
13090 {
13091 if (NULL == dvh->dv->vl)
13092 continue; /* route not (yet) visible to CORE, no messages for it */
13094 queue,
13095 dvh->dv->vl,
13096 dvh,
13097 sizeof(struct GNUNET_PeerIdentity)
13098 * (1 + dvh->distance)
13099 + sizeof(struct TransportDVBoxMessage)
13100 + sizeof(struct TransportDVBoxPayloadP));
13101 }
13102 }
13103 if (NULL == sc.best)
13104 {
13105 /* no message pending, nothing to do here! */
13107 "No pending messages, queue `%s' to %s now idle\n",
13108 queue->address,
13109 GNUNET_i2s (&n->pid));
13110 if (GNUNET_YES == sc.to_early)
13111 schedule_transmit_on_queue (sc.to_early_retry_delay,
13112 queue,
13114 queue->idle = GNUNET_YES;
13115 return;
13116 }
13117 /* There is a message pending, we are certainly not idle */
13118 queue->idle = GNUNET_NO;
13119
13120 /* Given selection in `sc`, do transmission */
13121 pm = sc.best;
13123 "Selected message <%" PRIu64 ">\n",
13124 pm->logging_uuid);
13125 if (NULL != sc.dvh)
13126 {
13128 "Is this %u a DV box?\n",
13129 pm->pmt);
13130 GNUNET_assert (PMT_DV_BOX != pm->pmt);
13131 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
13132 {
13134 "Discard old box, because we have a new DV path.\n");
13135 free_pending_message (sc.best->bpm);
13136 sc.best->bpm = NULL;
13137 }
13138
13139 if (NULL == sc.best->bpm)
13140 {
13142 "encapsulate_for_dv 2\n");
13143 encapsulate_for_dv (sc.dvh->dv,
13144 1,
13145 &sc.dvh,
13146 (const struct GNUNET_MessageHeader *) &sc.best[1],
13148 &sc,
13149 RMO_NONE,
13150 GNUNET_NO);
13151 GNUNET_assert (NULL != sc.best->bpm);
13153 "%lu %lu %lu %lu %u\n",
13154 sizeof(struct GNUNET_PeerIdentity),
13155 sizeof(struct TransportDVBoxMessage),
13156 sizeof(struct TransportDVBoxPayloadP),
13157 sizeof(struct TransportFragmentBoxMessage),
13158 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
13159 sc.best->bpm->used_dvh = sc.dvh;
13160 }
13161 pm = sc.best->bpm;
13162 }
13163 if (GNUNET_YES == sc.frag)
13164 {
13165 pm = fragment_message (queue, sc.dvh, pm);
13166 if (NULL == pm)
13167 {
13169 "Fragmentation failed queue %s to %s for <%" PRIu64
13170 ">, trying again\n",
13171 queue->address,
13172 GNUNET_i2s (&n->pid),
13173 sc.best->logging_uuid);
13174 /* NOT with a zero delay: nothing about @a queue or about the message
13175 changed between here and the next pass, so "trying again" at once
13176 is a busy loop that reproduces the failure at scheduler speed. */
13178 queue,
13180 return;
13181 }
13182 }
13183 else if (GNUNET_YES == sc.relb)
13184 {
13185 pm = reliability_box_message (queue, sc.dvh, pm);
13186 if (NULL == pm)
13187 {
13188 /* Reliability boxing failed, try next message... */
13189 GNUNET_log (
13191 "Reliability boxing failed queue %s to %s for <%" PRIu64
13192 ">, trying again\n",
13193 queue->address,
13194 GNUNET_i2s (&n->pid),
13195 sc.best->logging_uuid);
13196 /* Same reasoning as for the fragmentation failure above. */
13198 queue,
13200 return;
13201 }
13202 }
13203
13204 /* Pass 'pm' for transission to the communicator */
13205 GNUNET_log (
13207 "Passing message <%" PRIu64
13208 "> to queue %s for peer %s (considered %u others)\n",
13209 pm->logging_uuid,
13210 queue->address,
13211 GNUNET_i2s (&n->pid),
13212 sc.consideration_counter);
13213
13214 /* Flow control: increment amount of traffic sent; if we are routing
13215 via DV (and thus the ultimate target of the pending message is for
13216 a different virtual link than the one of the queue), then we need
13217 to use up not only the window of the direct link but also the
13218 flow control window for the DV link! */
13220
13221 if (pm->vl != queue->neighbour->vl)
13222 {
13223 /* If the virtual link of the queue differs, this better be distance
13224 vector routing! */
13225 GNUNET_assert (NULL != sc.dvh);
13226 /* If we do distance vector routing, we better not do this for a
13227 message that was itself DV-routed */
13228 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
13229 /* We use the size of the unboxed message here, to avoid counting
13230 the DV-Box header which is eaten up on the way by intermediaries.
13231 The next hop need not have a link of its own, in which case there is
13232 no window of it to charge. */
13233 if (NULL != queue->neighbour->vl)
13234 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
13235 }
13236 else
13237 {
13238 GNUNET_assert (NULL == sc.dvh);
13239 }
13240
13241 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
13242
13243 /* The message is with the communicator now, so return the CORE send
13244 window credit for it -- see #credit_client().
13245
13246 It used to be returned here only for an unboxed message or a reliable
13247 communicator, and otherwise not until the *peer* acknowledged the
13248 message below. That makes a window into a delivery confirmation: over
13249 an unreliable communicator every reliability-boxed or fragmented
13250 message holds one of the client's #SEND_WINDOW_SIZE slots for as long
13251 as its ACK takes, and a lost ACK holds it for the whole retransmission
13252 chain. Four of those and CORE cannot send to that peer at all -- not
13253 payload, but also not its HEARTBEATs and not one message of its key
13254 exchange. So the session times out for want of a heartbeat that is
13255 sitting in a queue, and the handshake that would rebuild it cannot go
13256 out either; CORE only recovers when a reconnect resets the window
13257 wholesale. Acknowledgements still drive retransmission below, they
13258 just no longer gate the client. */
13259 credit_client (sc.best);
13260
13261 /* Check if this transmission somehow conclusively finished handing 'pm'
13262 even without any explicit ACKs */
13263 if ((PMT_CORE == pm->pmt) ||
13264 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
13265 {
13267 }
13268 else
13269 {
13270 struct GNUNET_TIME_Relative wait_duration;
13271 unsigned int wait_multiplier;
13272
13273 if (PMT_FRAGMENT_BOX == pm->pmt)
13274 {
13275 struct PendingMessage *root;
13276
13277 root = pm->frag_parent;
13278 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
13279 root = root->frag_parent;
13280
13281 if ((0 == root->frag_off) || (0 == root->frag_count))
13282 {
13283 wait_multiplier = 4;
13284 }
13285 else
13286 {
13287 double wm = ceil ((double) root->bytes_msg
13288 / ((double) root->frag_off
13289 / (double) root->frag_count)) * 4.0;
13290
13291 if ((! (wm >= 1.0)) || (wm > 1024.0))
13292 wm = 4.0; /* NaN, infinity or absurd: fall back to the default */
13293 wait_multiplier = (unsigned int) wm;
13294 }
13295 }
13296 else
13297 {
13298 // No fragments, we use 4 RTT before retransmitting.
13299 wait_multiplier = 4;
13300 }
13301
13302 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
13303 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
13304
13306 "Wait multiplier %u\n",
13307 wait_multiplier);
13308
13309 /* Message not finished, waiting for acknowledgement.
13310 Update time by which we might retransmit 's' based on queue
13311 characteristics (i.e. RTT); it takes one RTT for the message to
13312 arrive and the ACK to come back in the best case; but the other
13313 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
13314 retransmitting.
13315
13316 OPTIMIZE: Note that in the future this heuristic should likely
13317 be improved further (measure RTT stability, consider message
13318 urgency and size when delaying ACKs, etc.) */
13319
13320 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
13321 queue->pd.aged_rtt.rel_value_us)
13322 wait_duration = GNUNET_TIME_relative_max (queue->pd.aged_rtt,
13324 else
13325 {
13326 wait_duration = DEFAULT_ACK_WAIT_DURATION;
13327 wait_multiplier = 4;
13328 }
13329 {
13332 wait_duration, wait_multiplier));
13334 wait_duration, wait_multiplier);
13336 "Waiting %s for ACK until %s\n",
13341 GNUNET_TIME_relative_multiply (wait_duration,
13342 wait_multiplier))
13343 );
13344 }
13345 }
13346 /* finally, re-schedule queue transmission task itself */
13348 queue,
13350}
13351
13352
13359static void
13361 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
13362{
13363 struct TransportClient *tc = cls;
13364
13365 if (CT_COMMUNICATOR != tc->type)
13366 {
13367 GNUNET_break (0);
13369 return;
13370 }
13371 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
13372 queue = queue->next_client)
13373 {
13374 struct Neighbour *neighbour = queue->neighbour;
13375
13376 if ((ntohl (dqm->qid) != queue->qid) ||
13377 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
13378 continue;
13380 "Dropped queue %s to peer %s\n",
13381 queue->address,
13382 GNUNET_i2s (&neighbour->pid));
13383 free_queue (queue);
13385 return;
13386 }
13387 /* Not finding the queue is a race, not a protocol violation: we may have
13388 freed it ourselves already, or the communicator may be tearing down a
13389 queue we never fully learned about. Do NOT drop the client over it --
13390 that runs #client_disconnect_cb(), which frees *every* queue this
13391 communicator owns, so one stale QUEUE_TEARDOWN would disconnect us from
13392 every peer it serves at once. Compare #handle_send_message_ack(), which
13393 tolerates the same lookup miss. */
13395 "QUEUE_TEARDOWN for unknown queue QID %u to peer %s ignored\n",
13396 ntohl (dqm->qid),
13397 GNUNET_i2s (&dqm->receiver));
13399 "# QUEUE_TEARDOWN dropped: queue unknown",
13400 1,
13401 GNUNET_NO);
13403}
13404
13405
13406static void
13408 struct TransportClient *tc)
13409{
13410 struct PendingMessage *pm;
13411
13412 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
13413 qe->queue->queue_tail,
13414 qe);
13415 qe->queue->queue_length--;
13416 tc->details.communicator.total_queue_length--;
13418 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
13419 qe->queue->address,
13420 qe->queue->qid,
13421 GNUNET_i2s (&qe->queue->neighbour->pid),
13422 qe->queue->queue_length,
13423 tc->details.communicator.total_queue_length);
13424
13425 /* if applicable, resume transmissions that waited on ACK */
13427 tc->details.communicator.total_queue_length)
13428 {
13429 /* Communicator dropped below threshold, resume all queues
13430 incident with this client! */
13432 GST_stats,
13433 "# Transmission throttled due to communicator queue limit",
13434 -1,
13435 GNUNET_NO);
13436 for (struct Queue *queue = tc->details.communicator.queue_head;
13437 NULL != queue;
13438 queue = queue->next_client)
13439 {
13441 queue,
13443 }
13444 }
13445 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
13446 {
13447 /* queue dropped below threshold; only resume this one queue */
13449 "# Transmission throttled due to queue queue limit",
13450 -1,
13451 GNUNET_NO);
13453 qe->queue,
13455 }
13456 else if (1 == qe->queue->q_capacity)
13457 {
13458 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
13460 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
13461 PRIu64 ".\n",
13462 qe->queue->qid,
13463 qe->queue->q_capacity);
13464 /* message queue has capacity; only resume this one queue */
13465 /* queue dropped below threshold; only resume this one queue */
13467 "# Transmission throttled due to message queue capacity",
13468 -1,
13469 GNUNET_NO);
13471 qe->queue,
13473 }
13474
13475 if (NULL != (pm = qe->pm))
13476 {
13477 struct VirtualLink *vl;
13478
13479 // GNUNET_assert (qe == pm->qe);
13480 pm->qe = NULL;
13481 /* If waiting for this communicator may have blocked transmission
13482 of pm on other queues for this neighbour, force schedule
13483 transmit on queue for queues of the neighbour */
13484 if (NULL == pm->frag_parent)
13485 {
13486 vl = pm->vl;
13487 if ((NULL != vl) &&
13488 (NULL != vl->pending_msg_head) &&
13489 (vl->pending_msg_head == pm))
13491 }
13492 }
13493 GNUNET_free (qe);
13494}
13495
13496
13503static void
13505 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
13506{
13507 struct TransportClient *tc = cls;
13508 struct QueueEntry *qe;
13509 struct Queue *failed_queue = NULL;
13510
13511 if (CT_COMMUNICATOR != tc->type)
13512 {
13513 GNUNET_break (0);
13515 return;
13516 }
13517
13518 /* find our queue entry matching the ACK */
13519 qe = NULL;
13521 "Looking for queue for PID %s\n",
13522 GNUNET_i2s (&sma->receiver));
13523 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
13524 queue = queue->next_client)
13525 {
13526 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
13527 continue;
13529 "Found PID %s\n",
13530 GNUNET_i2s (&queue->neighbour->pid));
13531
13532
13533 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
13534 qep = qep->next)
13535 {
13536 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
13537 sma->qid))
13538 continue;
13540 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
13541 PRIu64 " Ack QID %u\n",
13542 qep->mid,
13543 queue->qid,
13544 GNUNET_ntohll (sma->mid),
13545 ntohl (sma->qid));
13546 qe = qep;
13547 if ((NULL != qe->pm) && (qe->pm->qe != qe))
13549 "For pending message %" PRIu64 " we had retransmissions.\n",
13550 qe->pm->logging_uuid);
13551 break;
13552 }
13553 }
13554 if (GNUNET_OK != (int) ntohl (sma->status))
13555 {
13556 /* The communicator could not hand the message to the peer. The only
13557 thing that produces this today is #handle_send_msg()'s "queue no
13558 longer exists" branch in `transport_api_communication.c', i.e. the
13559 communicator has already torn the queue down on its side and the
13560 QUEUE_TEARDOWN is merely still in flight (or was lost).
13561
13562 Ignoring the status, as we used to, makes this self-sustaining:
13563 #free_queue_entry() releases the pending message and immediately
13564 reschedules transmission, #transmit_on_queue() picks the very same
13565 queue again -- transport still has it -- and we get another failure.
13566 Every round adds an envelope to the client MQ that is already
13567 congested, which is what shows up at the other end as
13568
13569 communicator INFO Transmission failed, queue no longer exists.
13570
13571 repeating at scheduler speed, and (because the service is busy
13572 servicing that loop) as
13573
13574 communicator WARNING Dropping message: transport is too slow,
13575 queue length N exceeded
13576
13577 on every *other* communicator. Treat the failure as the queue
13578 teardown it is and stop selecting this queue. */
13580 "Communicator could not send MID %" PRIu64
13581 " on QID %u to %s; dropping that queue\n",
13582 GNUNET_ntohll (sma->mid),
13583 ntohl (sma->qid),
13584 GNUNET_i2s (&sma->receiver));
13586 "# queues dropped (communicator send failed)",
13587 1,
13588 GNUNET_NO);
13589 if (NULL != qe)
13590 failed_queue = qe->queue;
13591 else
13592 for (struct Queue *queue = tc->details.communicator.queue_head;
13593 NULL != queue;
13594 queue = queue->next_client)
13595 if ((ntohl (sma->qid) == queue->qid) &&
13596 (0 == GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver)))
13597 {
13598 failed_queue = queue;
13599 break;
13600 }
13601 if (NULL != failed_queue)
13602 {
13603 /* #free_queue() releases every `struct QueueEntry' still on it --
13604 including @a qe -- and detaches their pending messages, so they are
13605 retried on whatever other queue this neighbour has. */
13606 free_queue (failed_queue);
13608 return;
13609 }
13610 }
13611 if (NULL == qe)
13612 {
13614 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
13615 GNUNET_ntohll (sma->mid),
13616 ntohl (sma->qid));
13617 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
13618 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
13619 /* this should never happen */
13620 // GNUNET_break (0);
13621 // GNUNET_SERVICE_client_drop (tc->client);
13623 return;
13624 }
13627}
13628
13629
13635static void
13637 const struct GNUNET_TRANSPORT_BurstFinished *bf)
13638{
13639 struct TransportClient *tc = cls;
13640
13641 (void) bf;
13644}
13645
13646
13656static int
13658 const struct GNUNET_PeerIdentity *pid,
13659 void *value)
13660{
13661 struct TransportClient *tc = cls;
13662 struct Neighbour *neighbour = value;
13663
13664 GNUNET_assert (CT_MONITOR == tc->type);
13665 for (struct Queue *q = neighbour->queue_head; NULL != q;
13666 q = q->next_neighbour)
13667 {
13668 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
13669 .cs = q->cs,
13670 .num_msg_pending = q->num_msg_pending,
13671 .num_bytes_pending = q->num_bytes_pending };
13672
13673 notify_monitor (tc, pid, q->address, q->nt, &me);
13674 }
13675 return GNUNET_OK;
13676}
13677
13678
13685static void
13688{
13689 struct TransportClient *tc = cls;
13690
13691 if (CT_NONE != tc->type)
13692 {
13693 GNUNET_break (0);
13695 return;
13696 }
13697 tc->type = CT_MONITOR;
13698 tc->details.monitor.peer = start->peer;
13699 tc->details.monitor.one_shot = ntohl (start->one_shot);
13703}
13704
13705
13710{
13715
13720};
13721
13722
13731static char *
13733 unsigned int *num_queues)
13734{
13735 char *ret = GNUNET_strdup ("");
13736
13737 *num_queues = 0;
13738 if (NULL == n)
13739 return ret;
13740 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
13741 {
13742 const char *prefix = q->tc->details.communicator.address_prefix;
13743 size_t plen = strlen (prefix);
13744 const char *pos;
13745 char *tmp;
13746
13747 (*num_queues)++;
13748 if (0 == plen)
13749 continue;
13750 /* Several queues to one neighbour routinely share a communicator;
13751 name each one once. */
13752 for (pos = strstr (ret, prefix);
13753 NULL != pos;
13754 pos = strstr (pos + 1, prefix))
13755 if (((pos == ret) || (',' == pos[-1])) &&
13756 (('\0' == pos[plen]) || (',' == pos[plen])))
13757 break;
13758 if (NULL != pos)
13759 continue;
13760 GNUNET_asprintf (&tmp, "%s%s%s", ret, ('\0' == ret[0]) ? "" : ",", prefix);
13761 GNUNET_free (ret);
13762 ret = tmp;
13763 }
13764 return ret;
13765}
13766
13767
13776static enum GNUNET_GenericReturnValue
13777report_link (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
13778{
13779 struct LinkListContext *llc = cls;
13780 struct VirtualLink *vl = value;
13782 struct GNUNET_MQ_Envelope *env;
13783 unsigned int pending = 0;
13784 unsigned int num_queues = 0;
13785 unsigned int distance = 0;
13786 struct Neighbour *hop;
13787 char *ccs;
13788 size_t clen;
13789
13790 if ((GNUNET_YES != llc->include_unconfirmed) &&
13791 (GNUNET_YES != vl->confirmed))
13792 return GNUNET_OK;
13793 for (struct PendingMessage *pm = vl->pending_msg_head;
13794 NULL != pm;
13795 pm = pm->next_vl)
13796 pending++;
13797 if (NULL != vl->n)
13798 {
13799 hop = vl->n;
13800 }
13801 else
13802 {
13803 /* Report the best (shortest) of the paths we currently know, and the
13804 communicators that carry its first hop. */
13805 struct DistanceVectorHop *best = NULL;
13806
13807 distance = UINT_MAX;
13808 if (NULL != vl->dv)
13809 for (struct DistanceVectorHop *pos = vl->dv->dv_head;
13810 NULL != pos;
13811 pos = pos->next_dv)
13812 if (pos->distance < distance)
13813 {
13814 distance = pos->distance;
13815 best = pos;
13816 }
13817 if (NULL == best)
13818 distance = 0; /* no paths left; report the link as adjacent */
13819 hop = (NULL != best) ? best->next_hop : NULL;
13820 }
13821 ccs = communicator_list (hop, &num_queues);
13822 clen = strlen (ccs) + 1;
13823 env = GNUNET_MQ_msg_extra (resp,
13824 clen,
13826 memcpy (&resp[1], ccs, clen);
13827 GNUNET_free (ccs);
13828 resp->target = *pid;
13829 resp->confirmed = htonl ((uint32_t) vl->confirmed);
13830 resp->route = htonl ((uint32_t) ((NULL != vl->n)
13833 resp->distance = htonl ((uint32_t) distance);
13834 resp->num_queues = htonl ((uint32_t) num_queues);
13835 resp->core_recv_window = htonl ((int32_t) vl->core_recv_window);
13836 resp->stalled = htonl ((uint32_t) vl->cmc_count);
13837 resp->pending = htonl (pending);
13838 resp->fc_retransmit_count = htonl ((uint32_t) vl->fc_retransmit_count);
13857 GNUNET_MQ_send (llc->tc->mq, env);
13858 return GNUNET_OK;
13859}
13860
13861
13870static void
13872 void *cls,
13874{
13875 struct TransportClient *tc = cls;
13876 struct LinkListContext llc = {
13877 .tc = tc,
13878 .include_unconfirmed = (int) ntohl (lr->include_unconfirmed)
13879 };
13880 struct GNUNET_MQ_Envelope *env;
13881 struct GNUNET_MessageHeader *end;
13882
13883 if (CT_NONE != tc->type)
13884 {
13885 GNUNET_break (0);
13887 return;
13888 }
13889 if (GNUNET_YES == GNUNET_is_zero (&lr->peer))
13890 {
13892 }
13893 else
13894 {
13895 struct VirtualLink *vl = lookup_virtual_link (&lr->peer);
13896
13897 if (NULL != vl)
13898 report_link (&llc, &lr->peer, vl);
13899 }
13902 GNUNET_MQ_send (tc->mq, env);
13904}
13905
13906
13914static struct TransportClient *
13916{
13917 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13918 {
13919 if (CT_COMMUNICATOR != tc->type)
13920 continue;
13921 if (NULL == tc->details.communicator.address_prefix)
13922 continue; /* receive-only communicator */
13923 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
13924 return tc;
13925 }
13926 GNUNET_log (
13928 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
13929 prefix);
13930 return NULL;
13931}
13932
13933
13941static void
13942suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
13943{
13944 static uint32_t idgen = 0;
13945 struct TransportClient *tc;
13946 char *prefix;
13947 struct GNUNET_TRANSPORT_CreateQueue *cqm;
13948 struct GNUNET_MQ_Envelope *env;
13949 size_t alen;
13950
13952 if (NULL == prefix)
13953 {
13954 GNUNET_break (0); /* We got an invalid address!? */
13955 return;
13956 }
13958 if (NULL == tc)
13959 {
13961 "# Suggestions ignored due to missing communicator",
13962 1,
13963 GNUNET_NO);
13965 "Cannot connect to %s at `%s', no matching communicator present\n",
13966 GNUNET_i2s (pid),
13967 address);
13969 return;
13970 }
13971 /* forward suggestion for queue creation to communicator */
13973 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
13974 (unsigned int) idgen,
13975 prefix,
13976 GNUNET_i2s (pid),
13977 address);
13979 alen = strlen (address) + 1;
13980 env =
13982 cqm->request_id = htonl (idgen++);
13983 cqm->receiver = *pid;
13984 memcpy (&cqm[1], address, alen);
13985 GNUNET_MQ_send (tc->mq, env);
13986}
13987
13988
13996static void
13998{
14000 struct GNUNET_TIME_Absolute monotonic_time;
14001
14002 if (NULL != vs->revalidation_task)
14003 {
14004 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
14005 vs->revalidation_task = NULL;
14006 }
14007 /*memcpy (&hkey,
14008 &hc,
14009 sizeof (hkey));*/
14011 "Remove key %s for address %s map size %u contains %u\n",
14012 GNUNET_h2s (&vs->hc),
14013 vs->address,
14016 &vs->hc));
14018
14020 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
14021 vs->last_challenge_use.abs_value_us)
14022 {
14023 vs->first_challenge_use = monotonic_time;
14024 }
14025 vs->last_challenge_use = monotonic_time;
14026 tvc.header.type =
14028 tvc.header.size = htons (sizeof(tvc));
14029 tvc.reserved = htonl (0);
14030 tvc.challenge = vs->challenge;
14031 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
14033 "Sending address validation challenge %s to %s\n",
14035 GNUNET_i2s (&q->neighbour->pid));
14036 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
14037}
14038
14039
14051static struct GNUNET_TIME_Relative
14053{
14054 const struct VirtualLink *vl = lookup_virtual_link (pid);
14055
14056 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
14057 return MAX_VALIDATION_CHALLENGE_FREQ; /* we have what we want */
14058 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
14059 {
14060 if (CT_APPLICATION != tc->type)
14061 continue;
14063 tc->details.application.requests,
14064 pid))
14066 }
14068}
14069
14070
14076static void
14078{
14079 struct ValidationState *vs;
14080 struct Queue *q;
14082 GST_cfg);
14083
14084 (void) cls;
14085 validation_task = NULL;
14087 /* drop validations past their expiration */
14088 while (
14089 (NULL != vs) &&
14091 {
14093 "Validation response %s cleaned up\n",
14094 GNUNET_sh2s (&vs->challenge.value));
14097 }
14098 if (NULL == vs)
14099 {
14101 "Address validation task not scheduled anymore, nothing to do\n");
14102 return; /* woopsie, no more addresses known, should only
14103 happen if we're really a lonely peer */
14104 }
14105 q = find_queue (&vs->pid, vs->address);
14106 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
14107 {
14109 "To early to start next address validation for challenge %s\n",
14110 GNUNET_sh2s (&vs->challenge.value));
14111 /* Do NOT just return: @e validation_task was set to NULL above and
14112 nothing re-arms it by itself. #update_next_challenge_time() only
14113 schedules us again when it is called with a *changed* time for some
14114 validation state, so bailing out here leaves a non-empty
14115 #validation_heap with no task attached: address (re)validation and
14116 the #suggest_to_connect() retries that go with it stop for *every*
14117 peer until some unrelated event happens to come along. A peer that
14118 just lost its only connection has no such events left. */
14121 now,
14122 vs->first_challenge_use),
14124 NULL);
14125 return;
14126 }
14127 if (NULL == q)
14128 {
14129 vs->awaiting_queue = GNUNET_YES;
14130 suggest_to_connect (&vs->pid, vs->address);
14131 }
14132 else
14134 /* Finally, reschedule next attempt */
14135 vs->challenge_backoff =
14136 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
14139 "Address validation task will run again in %s\n",
14140 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
14141 GNUNET_YES));
14144 vs->challenge_backoff));
14145}
14146
14147
14152{
14156 struct Queue *q;
14157
14161 unsigned int quality_count;
14162
14166 unsigned int num_queues;
14167
14172 unsigned int k;
14173};
14174
14175
14187static int
14189 const struct GNUNET_PeerIdentity *pid,
14190 void *value)
14191{
14192 struct QueueQualityContext *ctx = cls;
14193 struct Neighbour *n = value;
14194 int do_inc;
14195
14196 (void) pid;
14197 do_inc = GNUNET_NO;
14198 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
14199 {
14200 ctx->num_queues++;
14201 if (0 == ctx->k--)
14202 ctx->q = q;
14203 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
14204 statistics and consider those as well here? */
14205 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
14206 do_inc = GNUNET_YES;
14207 }
14208 if (GNUNET_YES == do_inc)
14209 ctx->quality_count++;
14210 return GNUNET_OK;
14211}
14212
14213
14225static void
14226start_dv_learn (void *cls);
14227
14228
14236static void
14238 struct LearnLaunchEntry *lle,
14239 struct QueueQualityContext qqc)
14240{
14241 if (0 == qqc.num_queues)
14242 {
14244 "# DV learn aborted: no queue left",
14245 1,
14246 GNUNET_NO);
14247 return;
14248 }
14249 qqc.quality_count = 0;
14251 qqc.num_queues = 0;
14252 qqc.q = NULL;
14255 &qqc);
14256 if (NULL == qqc.q)
14257 {
14259 "# DV learn aborted: no queue left",
14260 1,
14261 GNUNET_NO);
14262 return;
14263 }
14264
14265 /* Do this as close to transmission time as possible! */
14267
14268 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
14269 /* reschedule this job, randomizing the time it runs (but no
14270 actual backoff!) */
14271 if (NULL != dvlearn_task)
14276 NULL);
14277}
14278
14279
14291static void
14293{
14294 struct LearnLaunchEntry *lle;
14295 struct QueueQualityContext qqc;
14296 struct TransportDVLearnMessage dvl;
14297 const struct GNUNET_PeerIdentity *my_identity;
14298
14299 (void) cls;
14300 dvlearn_task = NULL;
14301 if ((GNUNET_YES == in_shutdown) || (NULL == pils))
14302 return;
14304 return; /* lost all connectivity, cannot do learning */
14306 if (NULL == my_identity)
14307 {
14308 /* PILS has not handed us an identity yet. The first queue arriving
14309 schedules us with add_now(), which routinely wins that race; retry
14310 instead of taking the service down. */
14314 NULL);
14315 return;
14316 }
14318 qqc.quality_count = 0;
14319 qqc.num_queues = 0;
14323 &qqc);
14325 {
14326 struct GNUNET_TIME_Relative delay;
14327 unsigned int factor;
14328
14329 /* scale our retries by how far we are above the threshold */
14333 "At connection quality %u, will launch DV learn in %s\n",
14334 qqc.quality_count,
14337 return;
14338 }
14339 /* remove old entries in #dvlearn_map if it has grown too big */
14340 while (MAX_DV_LEARN_PENDING <=
14342 {
14343 lle = lle_tail;
14346 &lle->challenge.value,
14347 lle));
14349 GNUNET_free (lle);
14350 }
14351 /* setup data structure for learning */
14352 lle = GNUNET_new (struct LearnLaunchEntry);
14354 sizeof(lle->challenge));
14356 "Starting launch DV learn with challenge %s\n",
14357 GNUNET_sh2s (&lle->challenge.value));
14362 &lle->challenge.value,
14363 lle,
14366 dvl.header.size = htons (sizeof(dvl));
14367 dvl.num_hops = htons (0);
14368 dvl.bidirectional = htons (0);
14370 dvl.monotonic_time =
14372 // We will set the below again later
14373 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
14374 dvl.challenge = lle->challenge;
14375 dvl.initiator = *my_identity;
14376 {
14377 struct DvInitPS dvip = {
14378 .purpose.purpose = htonl (
14380 .purpose.size = htonl (sizeof(dvip)),
14381 .monotonic_time = dvl.monotonic_time,
14382 .challenge = lle->challenge
14383 };
14384
14385 if (GNUNET_OK != sign_by_my_identity (&dvip.purpose, &dvl.init_sig))
14386 return;
14387 }
14388 transmit_dv_init (dvl, lle, qqc);
14389}
14390
14391
14401static char *
14403{
14404 const char *dash;
14405 const char *colon;
14406
14407 if (NULL == address)
14408 return NULL;
14409 dash = strchr (address, '-');
14410 if (NULL == dash)
14411 return NULL;
14412 colon = strchr (dash, ':');
14413 if (NULL == colon)
14414 return NULL;
14415 return GNUNET_strndup (dash + 1,
14416 colon - (dash + 1));
14417}
14418
14419
14429static int
14431 const struct GNUNET_PeerIdentity *pid,
14432 void *value)
14433{
14434 struct Queue *q = cls;
14435 struct ValidationState *vs = value;
14436 char *address_without_port_vs;
14437 char *address_without_port_q;
14438 char *prefix_vs;
14439 char *prefix_q;
14440 int success = GNUNET_YES;
14441
14442 // TODO Check if this is really necessary.
14443 address_without_port_vs = get_address_without_port (vs->address);
14444 address_without_port_q = get_address_without_port (q->address);
14445 prefix_vs = GNUNET_HELLO_address_to_prefix (vs->address);
14446 prefix_q = GNUNET_HELLO_address_to_prefix (q->address);
14447
14449 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
14450 GNUNET_i2s (pid),
14451 (NULL == address_without_port_vs) ? "<unparsable>"
14452 : address_without_port_vs,
14453 (NULL == address_without_port_q) ? "<unparsable>"
14454 : address_without_port_q);
14455 (void) pid;
14456 /* Only the port may differ: the address we asked to connect to is
14457 `PROTO-IP:0' for a NATed peer, while the queue that then materializes
14458 sits at `PROTO-IP:port'. The communicator must match all the same --
14459 a challenge for a `tcp-' address is not answered by a `udp-' queue. */
14460 if ((GNUNET_YES == vs->awaiting_queue) &&
14461 (NULL != address_without_port_vs) &&
14462 (NULL != address_without_port_q) &&
14463 (NULL != prefix_vs) &&
14464 (NULL != prefix_q) &&
14465 (0 == strcmp (prefix_vs, prefix_q)) &&
14466 (0 == strcmp (address_without_port_vs, address_without_port_q)))
14467 {
14468
14469 vs->awaiting_queue = GNUNET_NO;
14471 success = GNUNET_NO;
14472 }
14473
14474 GNUNET_free (address_without_port_vs);
14475 GNUNET_free (address_without_port_q);
14476 GNUNET_free (prefix_vs);
14477 GNUNET_free (prefix_q);
14478 return success;
14479}
14480
14481
14490static void
14492 const struct GNUNET_PEERSTORE_Record *record,
14493 const char *emsg)
14494{
14495 struct Neighbour *n = cls;
14496 struct GNUNET_TIME_AbsoluteNBO *mtbe;
14497
14498 (void) emsg;
14499 if (NULL == record)
14500 {
14501 /* we're done with #neighbour_dv_monotime_cb() invocations,
14502 continue normal processing */
14503 n->get = NULL;
14505 return;
14506 }
14507 if (0 == record->value_size)
14508 {
14510 GNUNET_break (0);
14511 return;
14512 }
14513 mtbe = record->value;
14518}
14519
14520
14521static void
14523 const struct GNUNET_PeerIdentity *pid,
14524 const char *uri)
14525{
14526 struct Queue *queue = cls;
14527 struct sockaddr_in v4;
14528 const char *slash;
14529 char *address_uri;
14530 char *prefix;
14531 char *uri_without_port;
14532 char *address_uri_without_port;
14533
14534 slash = strrchr (uri, '/');
14535 if ((NULL == slash) || (slash - uri < 2))
14536 {
14537 GNUNET_break_op (0); /* @a uri comes from a remote HELLO */
14538 return;
14539 }
14540 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
14541 slash++;
14542 GNUNET_asprintf (&address_uri,
14543 "%s-%s",
14544 prefix,
14545 slash);
14546
14548 "1 not global natted_address %u %s %s %s\n",
14549 queue->is_global_natted,
14550 uri,
14551 queue->address,
14552 slash);
14553
14554 uri_without_port = get_address_without_port (address_uri);
14555 if ((NULL == uri_without_port) ||
14556 (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr)))
14557 {
14559 GNUNET_free (address_uri);
14560 GNUNET_free (uri_without_port);
14561 return;
14562 }
14563
14565 "2 not global natted_address %u %s %s\n",
14566 queue->is_global_natted,
14567 uri,
14568 queue->address);
14569
14570 if (GNUNET_NO == queue->is_global_natted)
14571 {
14573 GNUNET_free (address_uri);
14574 GNUNET_free (uri_without_port);
14575 return;
14576 }
14577
14579 "3 not global natted_address %u %s %s\n",
14580 queue->is_global_natted,
14581 uri,
14582 queue->address);
14583
14584 if (0 == strcmp (uri_without_port, address_uri))
14585 {
14587 GNUNET_free (address_uri);
14588 GNUNET_free (uri_without_port);
14589 return;
14590 }
14591
14593 "4 not global natted_address %u %s %s\n",
14594 queue->is_global_natted,
14595 uri,
14596 queue->address);
14597
14598 address_uri_without_port = get_address_without_port (queue->address);
14599 if ((NULL != address_uri_without_port) &&
14600 (0 == strcmp (uri_without_port, address_uri_without_port)))
14601 {
14602 queue->is_global_natted = GNUNET_NO;
14603 }
14604
14606 "not global natted_address %u %s %s %s %s %s %u\n",
14607 queue->is_global_natted,
14608 uri,
14609 queue->address,
14610 uri_without_port,
14611 address_uri_without_port,
14612 prefix,
14613 GNUNET_NO);
14615 GNUNET_free (address_uri);
14616 GNUNET_free (address_uri_without_port);
14617 GNUNET_free (uri_without_port);
14618}
14619
14620
14633
14634
14635static enum GNUNET_GenericReturnValue
14637 const struct GNUNET_PeerIdentity *pid,
14638 void *value)
14639{
14640 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
14641 struct TransportGlobalNattedAddress *tgna = value;
14642 char *addr = (char *) &tgna[1];
14643
14644 /* NOTE: @a addr is NOT 0-terminated. */
14646 "Checking tgna %p with addr %.*s and length %u compare length %lu\n",
14647 tgna,
14648 (int) ntohl (tgna->address_length),
14649 addr,
14650 ntohl (tgna->address_length),
14651 strlen (tgna_cls->addr));
14652 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
14653 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
14654 {
14655 tgna_cls->tgna = tgna;
14656 return GNUNET_NO;
14657 }
14658 return GNUNET_YES;
14659}
14660
14661
14662static void
14664{
14666 "Error in PEERSTORE monitoring for checking global natted\n");
14667}
14668
14669
14670static void
14672{
14674 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
14675}
14676
14677
14678static void
14680 const struct GNUNET_PEERSTORE_Record *record,
14681 const char *emsg)
14682{
14683 struct Queue *queue = cls;
14684 struct Neighbour *neighbour = queue->neighbour;
14685 struct GNUNET_HELLO_Parser *parser;
14686 const struct GNUNET_MessageHeader *hello;
14688 size_t address_len_without_port;
14689
14690 if (NULL != emsg)
14691 {
14693 "Got failure from PEERSTORE: %s\n",
14694 emsg);
14696 return;
14697 }
14698 if (NULL == record)
14699 {
14700 GNUNET_break (0);
14702 return;
14703 }
14704 /* @a hello was published by a remote peer and may be malformed. */
14705 hello = hello_from_record (record);
14706 if (NULL == hello)
14707 {
14709 return;
14710 }
14711 queue->is_global_natted = GNUNET_YES;
14712 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
14713 if (NULL == parser)
14714 {
14716 "HELLO cannot be parsed!\n");
14718 return;
14719 }
14721 "before not global natted %u\n",
14722 queue->is_global_natted);
14725 queue);
14727 "after not global natted %u\n",
14728 queue->is_global_natted);
14729 GNUNET_HELLO_parser_free (parser);
14730
14731 tgna_cls.addr = get_address_without_port (queue->address);
14732 if (NULL == tgna_cls.addr)
14733 {
14734 GNUNET_break (0);
14736 return;
14737 }
14738 address_len_without_port = strlen (tgna_cls.addr);
14739 /*{
14740 char buf[address_len_without_port + 1];
14741
14742 GNUNET_memcpy (&buf, addr, address_len_without_port);
14743 buf[address_len_without_port] = '\0';
14744 GNUNET_free (addr);
14745 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
14746 }*/
14747 tgna_cls.tgna = NULL;
14749 &neighbour->pid,
14751 &tgna_cls);
14752 if (NULL != tgna_cls.tgna)
14754 " tgna_cls.tgna tgna %p %lu %u %u\n",
14755 tgna_cls.tgna,
14756 neighbour->size_of_global_addresses,
14757 ntohl (tgna_cls.tgna->address_length),
14758 neighbour->number_of_addresses);
14759 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
14760 {
14761 struct TransportGlobalNattedAddress *tgna;
14762
14763 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
14764 + address_len_without_port);
14765 tgna->address_length = htonl (address_len_without_port);
14766 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
14768 &neighbour->pid,
14769 tgna,
14771 neighbour->number_of_addresses++;
14772 /* MUST match what is subtracted on removal (and what
14773 #add_global_addresses() actually copies), or the accounting drifts. */
14774 neighbour->size_of_global_addresses += address_len_without_port;
14776 "Created tgna %p with address %s and length %lu\n",
14777 tgna,
14778 tgna_cls.addr,
14779 address_len_without_port + 1);
14780 }
14781 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
14782 {
14784 &neighbour->pid,
14785 tgna_cls.tgna);
14786 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
14788 );
14789 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
14790 ;
14791 GNUNET_assert (0 < neighbour->number_of_addresses);
14792 neighbour->number_of_addresses--;
14794 "removed tgna %p\n",
14795 tgna_cls.tgna);
14796 GNUNET_free (tgna_cls.tgna);
14797 }
14799 GNUNET_free (tgna_cls.addr);
14800}
14801
14802
14809static void
14811 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
14812{
14813 struct TransportClient *tc = cls;
14814 struct Queue *queue;
14815 struct Neighbour *neighbour;
14816 const char *addr;
14817 uint16_t addr_len;
14818
14819 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
14820 {
14821 /* MTU so small as to be useless for transmissions,
14822 required for #fragment_message()! */
14823 GNUNET_break_op (0);
14825 return;
14826 }
14827 /* This may simply be a queue update. Match on the peer as well as the
14828 QID: the communicator's key for a queue is the pair, and
14829 #handle_send_msg() on its side looks both of them up. Matching on the
14830 QID alone let an ADD_QUEUE for a *different* peer be folded into an
14831 existing queue, leaving @e neighbour pointing at the old peer -- after
14832 which every SEND_MSG we put on it carries a receiver the communicator
14833 cannot match, and comes straight back as "queue no longer exists". */
14834 for (queue = tc->details.communicator.queue_head;
14835 NULL != queue;
14836 queue = queue->next_client)
14837 {
14838 if (queue->qid != ntohl (aqm->qid))
14839 continue;
14840 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &aqm->receiver))
14841 continue;
14842 break;
14843 }
14844
14845 if (NULL != queue)
14846 {
14847 neighbour = queue->neighbour;
14848 }
14849 else
14850 {
14851 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
14852
14853 neighbour = lookup_neighbour (&aqm->receiver);
14854 if (NULL == neighbour)
14855 {
14856 neighbour = GNUNET_new (struct Neighbour);
14858 GNUNET_YES);
14859 neighbour->pid = aqm->receiver;
14860 /* Give a fresh neighbour a full window to say something. */
14861 neighbour->last_inbound = GNUNET_TIME_absolute_get ();
14864 neighbours,
14865 &neighbour->pid,
14866 neighbour,
14868 neighbour->get =
14870 "transport",
14871 &neighbour->pid,
14874 neighbour);
14875 }
14876 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
14877 addr = (const char *) &aqm[1];
14879 "New queue %s to %s available with QID %u and q_len %" PRIu64
14880 " and mtu %u\n",
14881 addr,
14882 GNUNET_i2s (&aqm->receiver),
14883 ntohl (aqm->qid),
14884 GNUNET_ntohll (aqm->q_len),
14885 ntohl (aqm->mtu));
14886 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
14887 queue->tc = tc;
14888 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
14889 next_neighbour)
14890 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
14891 validated_until);
14892 /* Inherit the validity of the sibling queues, but only while it is
14893 still in the future -- copying an already expired timestamp is
14894 pointless (and the condition used to be inverted). */
14895 if (0 != GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
14896 {
14898 "New queue with QID %u inherit validated until\n",
14899 ntohl (aqm->qid));
14900 queue->validated_until = validated_until;
14901 }
14902 queue->address = (const char *) &queue[1];
14903 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
14904 queue->qid = ntohl (aqm->qid);
14905 queue->neighbour = neighbour;
14907 queue->unlimited_length = GNUNET_YES;
14908 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
14909 memcpy (&queue[1], addr, addr_len);
14910 /* notify monitors about new queue */
14911 {
14912 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
14913
14914 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
14915 }
14917 neighbour->queue_head,
14918 neighbour->queue_tail,
14919 queue);
14921 tc->details.communicator.queue_head,
14922 tc->details.communicator.queue_tail,
14923 queue);
14924
14925 }
14926 queue->mtu = ntohl (aqm->mtu);
14927 queue->nt = ntohl (aqm->nt);
14928 queue->cs = ntohl (aqm->cs);
14929 queue->idle = GNUNET_YES;
14930
14931 if (NULL == queue->mo)
14932 {
14933 /* Only for a NEW queue: on a queue update this used to start a second
14934 monitor and leak the first one. */
14935 struct sockaddr_in v4;
14936 char *addr_without = get_address_without_port (queue->address);
14937 if ((NULL != addr_without) &&
14938 (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr)))
14939 {
14941 "start not global natted\n");
14943 GNUNET_YES,
14944 "peerstore",
14945 &neighbour->pid,
14947 &
14949 NULL,
14950 &
14952 NULL,
14954 queue);
14955 }
14956 GNUNET_free (addr_without);
14957 }
14958 /* check if valdiations are waiting for the queue */
14960 &aqm->receiver))
14963 &aqm->receiver,
14965 queue);
14966 /* Always (also) validate the address of the queue itself. A pending
14967 validation served above may well be for a *different* address string:
14968 #check_validation_request_pending() matches on the IP only, so a
14969 validation state waiting for the NAT address `PROTO-IP:0' is happily
14970 satisfied by a queue at `PROTO-IP:12345'. If we stopped here,
14971 #handle_validation_response() would later look for a queue at
14972 `PROTO-IP:0' -- which never exists -- and drop the successful
14973 validation on the floor without ever creating the virtual link. That
14974 is exactly what happens to the second of two peers behind the same
14975 NAT, as both of them advertise the very same `PROTO-IP:0'. */
14976 start_address_validation (&aqm->receiver, queue->address);
14977 /* look for traffic for this queue */
14978 // TODO Check whether this makes any sense at all.
14979 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
14980 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
14981 /* might be our first queue, try launching DV learning */
14982 if (NULL == dvlearn_task)
14985}
14986
14987
14994static void
14996 const struct
14998{
14999 struct TransportClient *tc = cls;
15000 struct Queue *target_queue = NULL;
15001
15002 if (CT_COMMUNICATOR != tc->type)
15003 {
15004 /* Without this we walk `details.communicator.queue_head' for a client
15005 whose union holds something else entirely. */
15006 GNUNET_break (0);
15008 return;
15009 }
15011 "Received queue update message for %u with q_len %llu and mtu %u\n",
15012 ntohl (msg->qid),
15013 (unsigned long long) GNUNET_ntohll (msg->q_len),
15014 ntohl (msg->mtu));
15015 for (target_queue = tc->details.communicator.queue_head;
15016 NULL != target_queue;
15017 target_queue = target_queue->next_client)
15018 {
15019 if (ntohl (msg->qid) == target_queue->qid)
15020 break;
15021 }
15022 if (NULL == target_queue)
15023 {
15025 "Queue to update no longer exists! Discarding update.\n");
15027 return;
15028 }
15029
15030 target_queue->nt = ntohl (msg->nt);
15031 target_queue->mtu = ntohl (msg->mtu);
15032 target_queue->cs = ntohl (msg->cs);
15033 target_queue->priority = ntohl (msg->priority);
15034 /* The update message indicates how many messages
15035 * the queue should be able to handle.
15036 */
15038 target_queue->unlimited_length = GNUNET_YES;
15039 else
15040 target_queue->unlimited_length = GNUNET_NO;
15041 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
15042 if (0 < target_queue->q_capacity)
15044 target_queue,
15047}
15048
15049
15057static void
15059 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
15060{
15061 struct TransportClient *tc = cls;
15062
15063 if (CT_COMMUNICATOR != tc->type)
15064 {
15065 GNUNET_break (0);
15067 return;
15068 }
15070 "# Suggestions succeeded at communicator",
15071 1,
15072 GNUNET_NO);
15074 "Request #%u for communicator to create queue succeeded\n",
15075 (unsigned int) ntohs (cqr->request_id));
15077}
15078
15079
15088static void
15090 void *cls,
15091 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
15092{
15093 struct TransportClient *tc = cls;
15094
15095 if (CT_COMMUNICATOR != tc->type)
15096 {
15097 GNUNET_break (0);
15099 return;
15100 }
15102 "Request #%u for communicator to create queue failed\n",
15103 (unsigned int) ntohl (cqr->request_id));
15105 "# Suggestions failed in queue creation at communicator",
15106 1,
15107 GNUNET_NO);
15109}
15110
15111
15119static void
15121{
15122 struct TransportClient *tc = cls;
15123 struct PeerRequest *pr;
15124
15125 if (CT_APPLICATION != tc->type)
15126 {
15127 GNUNET_break (0);
15129 return;
15130 }
15131 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
15132 &msg->peer);
15133 if (NULL == pr)
15134 {
15135 GNUNET_break (0);
15137 return;
15138 }
15139 (void) stop_peer_request (tc, &pr->pid, pr);
15141}
15142
15143
15144static void
15146 const struct GNUNET_PeerIdentity *pid,
15147 const char *uri)
15148{
15149 struct Queue *q;
15150 int pfx_len;
15151 const char *eou;
15152 char *address;
15153 (void) cls;
15154
15155 eou = strstr (uri,
15156 "://");
15157 if ((NULL == eou) || (eou == uri))
15158 {
15159 /* @a uri comes from a HELLO some remote peer published. */
15160 GNUNET_break_op (0);
15161 return;
15162 }
15163 pfx_len = eou - uri;
15164 eou += 3;
15166 "%.*s-%s",
15167 pfx_len,
15168 uri,
15169 eou);
15170
15172 "hello for client %s\n",
15173 address);
15174
15175 q = find_queue (pid, address);
15176 if (NULL == q)
15177 {
15179 }
15180 else
15183}
15184
15185
15193static void
15195 const struct GNUNET_PEERSTORE_Record *record,
15196 const char *emsg)
15197{
15198 const struct GNUNET_PeerIdentity *my_identity;
15199 struct PeerRequest *pr = cls;
15200 struct GNUNET_HELLO_Parser *parser;
15201 const struct GNUNET_MessageHeader *hello;
15202
15203 if (NULL != emsg)
15204 {
15206 "Got failure from PEERSTORE: %s\n",
15207 emsg);
15209 return;
15210 }
15211 if (NULL == record)
15212 {
15213 GNUNET_break (0);
15215 return;
15216 }
15218 if (NULL == my_identity)
15219 {
15221 "No identity given yet!\n");
15223 return;
15224 }
15225 hello = hello_from_record (record);
15226 if (NULL == hello)
15227 {
15228 /* MUST still ask for the next record: a bad one is not a reason to
15229 stall this monitor forever. */
15231 return;
15232 }
15233 if (0 == GNUNET_memcmp (&record->peer, my_identity))
15234 {
15236 return;
15237 }
15238 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
15239 if (NULL == parser)
15240 {
15242 "HELLO cannot be parsed!\n");
15244 return;
15245 }
15247 "HELLO for `%s' could be parsed, iterating addresses...!\n",
15251 NULL);
15252 GNUNET_HELLO_parser_free (parser);
15253 /* MUST ask for the next record, or this monitor stalls after one HELLO */
15255}
15256
15257
15258static void
15260{
15262 "Error in PEERSTORE monitoring\n");
15263}
15264
15265
15266static void
15268{
15270 "Done with initial PEERSTORE iteration during monitoring\n");
15271}
15272
15273
15285static void
15287{
15288 if (NULL != pr->nc)
15290 /* Monitor only @e pid. With NULL every application request sees every
15291 HELLO in PEERSTORE, so a client asking for one peer made us suggest a
15292 connection to -- and start an address validation for -- every peer we
15293 have ever heard of, once per request. #try_to_bring_link_up() had the
15294 same bug and was already fixed the same way. */
15295 pr->nc =
15297 GNUNET_YES,
15298 "peerstore",
15299 &pr->pid,
15302 NULL,
15304 NULL,
15306 pr);
15307}
15308
15309
15319static void
15321{
15322 struct PeerRequest *pr = cls;
15323 struct VirtualLink *vl;
15324
15325 pr->retry_task = NULL;
15326 vl = lookup_virtual_link (&pr->pid);
15327 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
15328 {
15329 /* The client has what it asked for. Keep watching cheaply, and start
15330 over from the short interval when the link goes away again. */
15334 pr);
15335 return;
15336 }
15338 "Retrying to connect to %s, an application client wants it\n",
15339 GNUNET_i2s (&pr->pid));
15341 "# link setup retries for application clients",
15342 1,
15343 GNUNET_NO);
15344 /* Addresses we already track, queues we still have, and a fresh look in
15345 PEERSTORE. */
15347 /* ... plus a replay of what PEERSTORE has for this peer, which is the
15348 only way back once the validation state expired and the queues are
15349 gone. */
15355 pr);
15356}
15357
15358
15366static void
15368{
15369 struct TransportClient *tc = cls;
15370 const struct GNUNET_PeerIdentity *my_identity;
15371 struct PeerRequest *pr;
15372
15373 if (CT_NONE == tc->type)
15374 {
15375 tc->type = CT_APPLICATION;
15376 tc->details.application.requests =
15378 }
15379 if (CT_APPLICATION != tc->type)
15380 {
15381 GNUNET_break (0);
15383 return;
15384 }
15386 if (NULL == my_identity)
15387 {
15389 "Still waiting for own identity!\n");
15391 return;
15392 }
15394 "Client suggested we talk to %s with preference %d at rate %u\n",
15395 GNUNET_i2s (&msg->peer),
15396 (int) ntohl (msg->pk),
15397 (int) ntohl (msg->bw.value__));
15398 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
15399 {
15401 "Client suggested connection to ourselves, ignoring...\n");
15403 return;
15404 }
15405 pr = GNUNET_new (struct PeerRequest);
15406 pr->tc = tc;
15407 pr->pid = msg->peer;
15408 pr->bw = msg->bw;
15409 pr->pk = ntohl (msg->pk);
15411 tc->details.application.requests,
15412 &pr->pid,
15413 pr,
15415 {
15416 GNUNET_break (0);
15417 GNUNET_free (pr);
15419 return;
15420 }
15422 /* The monitor alone only ever fires again if the HELLO *changes*. Keep
15423 asking for the link ourselves for as long as the client wants it. */
15424 pr->retry_backoff = SUGGEST_RETRY_MIN;
15425 pr->retry_task = GNUNET_SCHEDULER_add_delayed (pr->retry_backoff,
15427 pr);
15429}
15430
15431
15440static int
15442 const struct RequestHelloValidationMessage *m)
15443{
15444 (void) cls;
15446 return GNUNET_OK;
15447}
15448
15449
15457static void
15459 const struct RequestHelloValidationMessage *m)
15460{
15461 struct TransportClient *tc = cls;
15462 struct Queue *q;
15463
15464 q = find_queue (&m->peer, (const char *) &m[1]);
15465 if (NULL == q)
15466 {
15467 suggest_to_connect (&m->peer, (const char *) &m[1]);
15468 }
15469 else
15470 start_address_validation (&m->peer, (const char *) &m[1]);
15472}
15473
15474
15483static int
15485 const struct GNUNET_PeerIdentity *pid,
15486 void *value)
15487{
15488 struct Neighbour *neighbour = value;
15489
15490 (void) cls;
15491 (void) pid;
15492 GNUNET_break (0); // should this ever happen?
15493 free_neighbour (neighbour, GNUNET_YES);
15494
15495 return GNUNET_OK;
15496}
15497
15498
15513static int
15515 const struct GNUNET_PeerIdentity *pid,
15516 void *value)
15517{
15518 struct VirtualLink *vl = value;
15519
15520 (void) cls;
15521 (void) pid;
15522 free_virtual_link (vl);
15523
15524 return GNUNET_OK;
15525}
15526
15527
15536static int
15538 const struct GNUNET_PeerIdentity *pid,
15539 void *value)
15540{
15541 struct DistanceVector *dv = value;
15542
15543 (void) cls;
15544 (void) pid;
15545 free_dv_route (dv);
15546
15547 return GNUNET_OK;
15548}
15549
15550
15559static int
15561 const struct GNUNET_PeerIdentity *pid,
15562 void *value)
15563{
15564 struct ValidationState *vs = value;
15565
15566 (void) cls;
15567 (void) pid;
15569 return GNUNET_OK;
15570}
15571
15572
15581static int
15582free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
15583{
15584 struct PendingAcknowledgement *pa = value;
15585
15586 (void) cls;
15587 (void) key;
15589 return GNUNET_OK;
15590}
15591
15592
15601static int
15603 const struct GNUNET_PeerIdentity *pid,
15604 void *value)
15605{
15606 struct AcknowledgementCummulator *ac = value;
15607
15608 (void) cls;
15609 (void) pid;
15610 /* @e task is armed for the whole life of @a ac -- but
15611 #transmit_cummulative_ack_cb() clears it before re-arming, and it
15612 routes a message while it is clear. #GNUNET_SCHEDULER_cancel()
15613 dereferences its argument unconditionally. */
15614 if (NULL != ac->task)
15615 {
15617 ac->task = NULL;
15618 }
15619 GNUNET_free (ac);
15620 return GNUNET_OK;
15621}
15622
15623
15630static void
15631do_shutdown (void *cls)
15632{
15633 static int shutdown_done;
15634 struct LearnLaunchEntry *lle;
15635 struct PilsRequest *pr;
15636 (void) cls;
15637
15639 "shutdown logic\n");
15640 if (GNUNET_YES == shutdown_done)
15641 return; /* reachable both from #shutdown_task() and #client_disconnect_cb() */
15642 shutdown_done = GNUNET_YES;
15643 if (NULL != client_grace_task)
15644 {
15646 client_grace_task = NULL;
15647 }
15648 if (NULL != nh)
15649 {
15651 nh = NULL;
15652 }
15654 &free_neighbour_cb, NULL);
15655 /* Freeing a neighbour takes its virtual link with it, so whatever is
15656 left here is ownerless: a link we created from an inbound FLOW_CONTROL
15657 message that never got confirmed, kept alive only by its @e
15658 unconfirmed_timeout_task. #GNUNET_SCHEDULER_shutdown() does not run
15659 that task, so leaving the link in place left the task armed against a
15660 map we destroy further down -- it fired afterwards and
15661 #free_virtual_link() called GNUNET_CONTAINER_multipeermap_remove() on
15662 NULL. Drop them here, while every structure they touch is still
15663 alive. */
15666 NULL);
15667 if (NULL != validation_task)
15668 {
15670 validation_task = NULL;
15671 }
15672 if (NULL != dvlearn_task)
15673 {
15675 dvlearn_task = NULL;
15676 }
15677 if (NULL != burst_task)
15678 {
15680 burst_task = NULL;
15681 }
15682 if (NULL != burst_timeout_task)
15683 {
15685 burst_timeout_task = NULL;
15686 }
15689 dvlearn_map = NULL;
15692 dv_routes = NULL;
15693 if (NULL != GST_stats)
15694 {
15696 GST_stats = NULL;
15697 }
15698 if (NULL != GST_my_hello)
15699 {
15701 GST_my_hello = NULL;
15702 }
15705 NULL);
15707 ack_cummulators = NULL;
15710 NULL);
15712 pending_acks = NULL;
15715 neighbours = NULL;
15718 links = NULL;
15721 NULL);
15723 backtalkers = NULL;
15726 NULL);
15728 validation_map = NULL;
15730 validation_heap = NULL;
15732 revalidation_map = NULL;
15733 while (NULL != ir_head)
15735 GNUNET_assert (0 == ir_total);
15736 while (NULL != (lle = lle_head))
15737 {
15739 GNUNET_free (lle);
15740 }
15741 while (NULL != (pr = pils_requests_head))
15742 {
15745 pr);
15746 if (NULL != pr->op)
15747 GNUNET_PILS_cancel (pr->op);
15748 GNUNET_free (pr);
15749 }
15750 if (NULL != pils_feed_task)
15751 {
15753 pils_feed_task = NULL;
15754 }
15755 if (NULL != pils)
15756 {
15758 pils = NULL;
15759 }
15760 if (NULL != peerstore)
15761 {
15763 "Disconnecting from PEERSTORE service\n");
15765 peerstore = NULL;
15766 }
15768}
15769
15770
15771static const char*
15773{
15774 switch (type)
15775 {
15776 case CT_CORE:
15777 return "CORE";
15778 case CT_MONITOR:
15779 return "MONITOR";
15780 case CT_COMMUNICATOR:
15781 return "COMMUNICATOR";
15782 case CT_APPLICATION:
15783 return "APPLICATION";
15784 default:
15785 return "UNKNOWN";
15786 }
15787}
15788
15789
15797static void
15799{
15800 client_grace_task = NULL;
15801 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
15802 {
15804 "Client did not disconnect within the shutdown grace period, "
15805 "dropping it: %s\n",
15806 get_client_type_name (tc->type));
15807 }
15808 /* We use #GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, so the service will NOT
15809 drop clients for us. Without this we would wait forever for them to
15810 leave on their own and never reach #do_shutdown(). */
15812 /* Dropping the clients ran #client_disconnect_cb() for each of them, so
15813 #do_shutdown() has normally run by now; it is idempotent, and this
15814 covers the case where there was nothing left to drop. */
15815 do_shutdown (cls);
15816}
15817
15818
15819static void
15820shutdown_task (void *cls)
15821{
15823
15825 "Shutdown task executed\n");
15826 if (NULL != clients_head)
15827 {
15828 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
15829 {
15831 "Waiting for client to disconnect: %s\n",
15832 get_client_type_name (tc->type));
15833 }
15834 /* Give them a chance to shut down cleanly; #client_disconnect_cb() calls
15835 #do_shutdown() once the last one is gone, and #do_shutdown() cancels
15836 this task. */
15840 cls);
15841 return;
15842 }
15843 do_shutdown (cls);
15844}
15845
15846
15851
15852static void
15853update_hello_from_pid_change_cb (void *cls, int success)
15854{
15855 struct UpdateHelloFromPidCtx *pc = cls;
15856
15857 /* NOTE: @a success is GNUNET_OK even when #hello_add_iter() decided not to
15858 store anything because PEERSTORE already holds a HELLO that expires
15859 later; the API reports the desired state, not whether it wrote. So this
15860 says "we have a current HELLO on record", not "we just wrote one". */
15861 if (GNUNET_OK != success)
15863 "Failed to store our new hello with peerstore\n");
15864 else
15866 "Our hello is current in peerstore\n");
15867 GNUNET_free (pc);
15868}
15869
15870
15871void
15873 const struct GNUNET_PeerIdentity *pid,
15874 const char *uri)
15875{
15877 "%s\n", uri);
15878}
15879
15880
15890static void
15892 const struct GNUNET_HELLO_Parser *parser,
15893 const struct GNUNET_HashCode *hash)
15894{
15895 const struct GNUNET_PeerIdentity *my_identity;
15896 struct GNUNET_MQ_Envelope *env;
15897 const struct GNUNET_MessageHeader *msg;
15898 struct UpdateHelloFromPidCtx *sc;
15899 struct GNUNET_HELLO_Builder *nbuilder;
15900 struct GNUNET_PeerIdentity npid;
15901
15904
15905 if (NULL == GST_my_hello)
15908 "My current identity is `%s'\n",
15920 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
15921 &npid);
15922 if (GNUNET_NO ==
15924 {
15926 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
15928 "Proposed address list:\n");
15931 "Current address list:\n");
15933 GNUNET_HELLO_builder_free (nbuilder);
15934 return;
15935 }
15937 GST_my_hello = nbuilder;
15939 "My new identity is `%s'\n",
15945 msg,
15947 sc);
15948 GNUNET_free (env);
15949}
15950
15951
15959static void
15960run (void *cls,
15961 const struct GNUNET_CONFIGURATION_Handle *c,
15963{
15964 (void) cls;
15965 /* setup globals */
15969 GST_cfg = c;
15977 GNUNET_YES);
15982 // TODO check for all uses of GST_my_hello that it is not used uninitialized
15984 "transport",
15985 "USE_BURST_NAT");
15986 if (GNUNET_SYSERR == use_burst)
15988 "Could not configure burst nat use. Default to no.\n");
15994 "transport",
15995 0,
15996 0,
15997 NULL,
15998 0,
15999 NULL,
16000 NULL,
16001 NULL);
16002 if (NULL == peerstore)
16003 {
16004 GNUNET_break (0);
16006 return;
16007 }
16010 NULL); // FIXME we need to wait for
16011 // our first peer id before
16012 // we can start the service
16013 // completely - PILS in turn
16014 // waits for the first
16015 // addresses from the
16016 // communicators in order to
16017 // be able to generate a
16018 // peer id
16019 if (NULL == pils)
16020 {
16021 GNUNET_break (0);
16023 return;
16024 }
16025 /* Decapsulate DV box ephemeral keys ourselves. #handle_dv_box() needs
16026 the key material while it still has the box, which points into the
16027 communicator's inbound message and is gone the moment the handler
16028 returns -- so the asynchronous answer arrived to a dangling @a dvb. */
16029 if (GNUNET_OK !=
16032 _ ("Failed to load our private key, "
16033 "cannot open DV boxes addressed to us\n"));
16034}
16035
16036
16042 "transport",
16044 &run,
16047 NULL,
16048 /* communication with applications */
16049 GNUNET_MQ_hd_fixed_size (suggest,
16052 NULL),
16053 GNUNET_MQ_hd_fixed_size (suggest_cancel,
16056 NULL),
16057 GNUNET_MQ_hd_var_size (request_hello_validation,
16060 NULL),
16061 /* communication with core */
16062 GNUNET_MQ_hd_fixed_size (client_start,
16064 struct StartMessage,
16065 NULL),
16066 GNUNET_MQ_hd_var_size (client_send,
16068 struct OutboundMessage,
16069 NULL),
16070 GNUNET_MQ_hd_fixed_size (client_recv_ok,
16072 struct RecvOkMessage,
16073 NULL),
16074 /* communication with communicators */
16075 GNUNET_MQ_hd_var_size (communicator_available,
16078 NULL),
16079 GNUNET_MQ_hd_var_size (communicator_backchannel,
16082 NULL),
16083 GNUNET_MQ_hd_var_size (add_address,
16086 NULL),
16087 GNUNET_MQ_hd_fixed_size (del_address,
16090 NULL),
16091 GNUNET_MQ_hd_var_size (incoming_msg,
16094 NULL),
16095 GNUNET_MQ_hd_fixed_size (queue_create_ok,
16098 NULL),
16099 GNUNET_MQ_hd_fixed_size (queue_create_fail,
16102 NULL),
16103 GNUNET_MQ_hd_var_size (add_queue_message,
16106 NULL),
16107 GNUNET_MQ_hd_fixed_size (update_queue_message,
16110 NULL),
16111 GNUNET_MQ_hd_fixed_size (del_queue_message,
16114 NULL),
16115 GNUNET_MQ_hd_fixed_size (send_message_ack,
16118 NULL),
16119 GNUNET_MQ_hd_fixed_size (burst_finished,
16122 NULL),
16123 /* communication with monitors */
16124 GNUNET_MQ_hd_fixed_size (monitor_start,
16127 NULL),
16128 GNUNET_MQ_hd_fixed_size (link_list_request,
16131 NULL),
16133
16134
16135/* end of file gnunet-service-transport.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition gnunet-arm.c:103
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static char * init
Set to the name of a service to start.
Definition gnunet-arm.c:73
static int end
Set if we are to shutdown all services (including ARM).
Definition gnunet-arm.c:33
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
static struct GNUNET_TESTING_Interpreter * is
static struct Queue * queue_head
Head of queue of messages to transmit.
static int prefix
If printing the value of PREFIX has been requested.
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct GNUNET_FS_Handle * ctx
static struct GNUNET_GNS_LookupWithTldRequest * lr
Handle to lookup request.
Definition gnunet-gns.c:98
struct GNUNET_SCHEDULER_Task * shutdown_task
static unsigned int pending
The number of DNS queries that are outstanding.
static void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
static int result
Global testing status.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static struct GNUNET_FS_SearchContext * sc
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static unsigned long long payload
How much data are we currently storing in the database?
struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
The current private key.
static unsigned int ring_buffer_dv_head
Head of the ring buffer.
static void peerstore_store_validation_cb(void *cls, int success)
Function called when peerstore is done storing a validated address.
static void handle_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
#define DV_PATH_DISCOVERY_FREQUENCY
How long before paths expire would we like to (re)discover DV paths? Should be below DV_PATH_VALIDITY...
static struct GNUNET_SERVICE_Handle * GST_service
Our service handle; needed to force-disconnect clients that did not go away within SHUTDOWN_CLIENT_GR...
static struct PendingMessage * ring_buffer_dv[RING_BUFFER_SIZE]
Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virt...
static int dv_neighbour_transmission(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void reassembly_cleanup_task(void *cls)
Task run to clean up reassembly context of a neighbour that have expired.
static enum GNUNET_GenericReturnValue remove_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void backtalker_timeout_cb(void *cls)
Function called when it is time to clean up a backtalker.
static void handle_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void send_cmc_ack(struct CommunicatorMessageContext *cmc)
Release the CORE flow control credit for cmc by acknowledging the message to the communicator that de...
static unsigned int calculate_fork_degree(unsigned int hops_taken, unsigned int neighbour_count, unsigned int eligible_count)
Computes the number of neighbours we should forward a DVInit message to given that it has so far take...
static enum GNUNET_GenericReturnValue detach_cmc_from_backtalker(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Detach the ‘struct CommunicatorMessageContext’ parked on value from the client in cls.
static struct GNUNET_SCHEDULER_Task * dvlearn_task
Task run to initiate DV learning.
static int check_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void handle_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
#define SUGGEST_RETRY_MAX
What is the slowest rate at which we retry bringing up a link that an application client explicitly a...
static int check_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment box.
static unsigned int get_age()
Get an offset into the transmission history buffer for struct PerformanceData.
static void free_validation_state(struct ValidationState *vs)
Free validation state.
static struct PendingAcknowledgement * prepare_pending_acknowledgement(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Setup data structure waiting for acknowledgements.
static int check_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
static void hello_for_incoming_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
#define MAX_DV_DISCOVERY_SELECTION
Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiato...
#define QUEUE_ENTRY_TIMEOUT
static struct LearnLaunchEntry * lle_tail
Tail of a DLL sorted by launch time.
static struct GNUNET_CONTAINER_Heap * validation_heap
MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware ...
static void core_send_connect_info(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void send_dv_to_neighbour(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
static void harmonize_flight_round(struct PendingMessage *pm)
#define ACK_CUMMULATOR_TIMEOUT
How long until we forget about historic accumulators and thus reset the ACK counter?...
void pils_sign_address(struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
Build address record by signing raw information with private key of the peer identity.
static struct GNUNET_SCHEDULER_Task * client_grace_task
Task run when SHUTDOWN_CLIENT_GRACE_PERIOD expired and clients are still connected,...
static void free_queue(struct Queue *queue)
Free queue.
static void handle_del_address(void *cls, const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
Address of our peer deleted.
static struct LearnLaunchEntry * lle_head
Head of a DLL sorted by launch time.
#define EPHEMERAL_VALIDITY
How long are ephemeral keys valid?
static void free_fragment_tree(struct PendingMessage *root)
Free fragment tree below root, excluding root itself.
static unsigned int is_ring_buffer_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static struct IncomingRequest * ir_tail
Tail of DLL starting at ir_head.
static void pils_pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
Callback called when pils service updates us with our new peer identity.
static int free_pending_ack_cb(void *cls, const struct GNUNET_Uuid *key, void *value)
Free pending acknowledgement.
static void credit_client(struct PendingMessage *pm)
Return the send window credit that pm's client is owed, at most once for pm.
static int check_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
static void completed_pending_message(struct PendingMessage *pm)
We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment...
static void update_dvh_performance(struct DistanceVectorHop *dvh, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via dvh, update metrics.
struct GNUNET_NAT_Handle * nh
Handle for connect to the NAT service.
static int check_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static struct GNUNET_SCHEDULER_Task * pils_feed_task
Task to feed addresses to PILS.
static void client_send_response(struct PendingMessage *pm)
Send a response to the pm that we have processed a "send" request.
static void start_dv_learn(void *cls)
Task run when we CONSIDER initiating a DV learn process.
static int dv_neighbour_selection(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static enum GNUNET_GenericReturnValue revalidate_now_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Pull value's next challenge forward: the link to that peer is not up.
static void start_address_validation(const struct GNUNET_PeerIdentity *pid, const char *address)
Start address validation.
static void handle_del_queue_message(void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
Queue to a peer went down.
static void drop_remaining_clients(void *cls)
The grace period we gave our clients to disconnect on their own expired.
#define QUEUE_LENGTH_LIMIT
How many messages can we have pending for a given queue (queue to a particular peer via a communicato...
static void update_backtalker_monotime(struct Backtalker *b)
The backtalker b monotonic time changed.
#define MAX_CUMMULATIVE_ACKS
Maximum number of messages we acknowledge together in one cumulative ACK.
#define MAX_DV_HOPS_ALLOWED
Maximum DV distance allowed ever.
static const char * get_client_type_name(enum ClientType type)
static void burst_timeout(void *cls)
#define BACKCHANNEL_INACTIVITY_TIMEOUT
How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
#define WANTED_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges to a peer that an application client explicitly ...
static struct GNUNET_TIME_Relative get_network_latency(const struct TransportDVLearnMessage *dvl)
static void hello_for_client_error_cb(void *cls)
static void check_for_global_natted(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
#define ADDRESS_VALIDATION_LIFETIME
How long do we consider an address valid if we just checked?
static void free_distance_vector_hop(struct DistanceVectorHop *dvh)
Free a dvh.
#define MAX_FC_RETRANSMIT_COUNT
Maximum number of FC retransmissions for a running retransmission task.
#define MIN_ACK_WAIT_DURATION
Lower bound on the RTT estimate we are willing to derive a retransmission deadline from.
static void handle_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment.
static enum GNUNET_GenericReturnValue report_link(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Send the state of the virtual link value to the requesting client.
static struct PendingMessage * fragment_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Fragment the given pm to the given mtu.
static void update_hello_from_pid_change_cb(void *cls, int success)
static struct GNUNET_SCHEDULER_Task * validation_task
Task to run address validation.
static void handle_suggest(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void handle_link_list_request(void *cls, const struct GNUNET_TRANSPORT_LinkListRequest *lr)
A client asks for the virtual links we currently have.
static void cores_send_connect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we gained a connection.
#define SUGGEST_RETRY_MIN
How soon after an application asked us for a peer do we retry bringing the link up for the first time...
static void cummulative_ack(const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
static void task_consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define DV_LEARN_QUALITY_THRESHOLD
How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiati...
static void free_neighbour(struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
Release memory used by neighbour.
PendingMessageType
Types of different pending messages.
@ PMT_FRAGMENT_BOX
Fragment box.
@ PMT_DV_BOX
Pending message created during forward_dv_box().
@ PMT_CORE
Ordinary message received from the CORE service.
@ PMT_RELIABILITY_BOX
Reliability box.
static struct GNUNET_TIME_Relative calculate_rtt(struct DistanceVector *dv)
static void arm_free_queue_entry_task(struct TransportClient *tc)
Make sure free_timedout_queue_entry() will run for tc, so that `struct QueueEntry's the communicator ...
static int check_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int stop_peer_request(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Stop the peer request in value.
static void handle_update_queue_message(void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
Handle updates to queues.
static void cores_send_disconnect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void handle_client_start(void *cls, const struct StartMessage *start)
Initialize a "CORE" client.
#define MAX_DV_PATHS_TO_TARGET
Maximum number of DV paths we keep simultaneously to the same target.
static void free_virtual_link(struct VirtualLink *vl)
Free virtual link.
static enum GNUNET_GenericReturnValue detach_cmcs_from_link(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Detach the `struct CommunicatorMessageContext's parked on value from the client in cls.
RouteMessageOptions
Which transmission options are allowable for transmission? Interpreted bit-wise!
@ RMO_UNCONFIRMED_ALLOWED
We are allowed to use unconfirmed queues or DV routes for this message.
@ RMO_DV_ALLOWED
We are allowed to use DV routing for this hdr.
@ RMO_REDUNDANT
If we have multiple choices, it is OK to send this message over multiple channels at the same time to...
@ RMO_NONE
Only confirmed, non-DV direct neighbours.
@ RMO_ANYTHING_GOES
Reliable and unreliable, DV and non-DV are all acceptable.
static int notify_client_queues(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new MONITOR client about all existing queues to peers.
static struct AddressListEntry * create_address_entry(struct TransportClient *tc, struct GNUNET_TIME_Relative expiration, enum GNUNET_NetworkType nt, const char *address, uint32_t aid, size_t slen)
static void extract_box_cb(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void backtalker_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a backtalker by PEERSTORE.
static void queue_burst(void *cls)
static void handle_monitor_start(void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
Initialize a monitor client.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static void finish_cmc_handling(struct CommunicatorMessageContext *cmc)
static int learn_dv_path(const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
We have learned a path through the network to some other peer, add it to our DV data structure (retur...
static void store_pi(void *cls)
Ask peerstore to store our address.
#define FC_NO_CHANGE_REPLY_PROBABILITY
What is the 1:n chance that we send a Flow control response when receiving a flow control message tha...
static void notify_monitors(const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Send information in me about a peer's status with respect to some address to all monitors that care.
static struct GNUNET_TIME_Relative route_via_neighbour(const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Pick a queue of n under constraints options and schedule transmission of hdr.
#define RECV_WINDOW_SIZE
Window size.
static int check_known_challenge(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the challenge from cls.
static void store_signed_address(struct PilsAddressSignContext *pc, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Turn the signed address into a HELLO URI and hand it to PEERSTORE.
static unsigned int check_for_queue_with_higher_prio(struct Queue *queue, struct Queue *queue_head)
Check if there is another queue to the same neighbour, over a different communicator,...
#define GOODPUT_AGING_SLOTS
Number of slots we keep of historic data for computation of goodput / message loss ratio.
static int free_validation_state_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free validation state.
static int free_neighbour_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free neighbour entry.
static void handle_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static void decaps_dv_box_cont(struct CommunicatorMessageContext *cmc, const struct TransportDVBoxMessage *dvb, const struct GNUNET_ShortHashCode *km)
Open the DV box dvb addressed to us, using the key material km decapsulated from its ephemeral key.
static enum GNUNET_GenericReturnValue burst_running
Is there a burst running?
struct GNUNET_HELLO_Builder * GST_my_hello
Our HELLO.
static void start_burst(void *cls)
#define DV_QUALITY_RTT_THRESHOLD
We only consider queues as "quality" connections when suppressing the generation of DV initiation mes...
static struct TransportClient * clients_head
Head of linked list of all clients to this service.
static void handle_validation_challenge(void *cls, const struct TransportValidationChallengeMessage *tvc)
Communicator gave us a transport address validation challenge.
static struct PilsRequest * pils_requests_head
PILS Operation DLL.
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT
How many messages can we have pending for a given communicator process before we start to throttle th...
static void free_reassembly_context(struct ReassemblyContext *rc)
Free rc.
static struct VirtualLink * lookup_virtual_link(const struct GNUNET_PeerIdentity *pid)
Lookup virtual link for peer pid.
static int check_connection_quality(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counte...
static void reorder_root_pm(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
static void core_env_sent_cb(void *cls)
Function called when we are done giving a message of a certain size to CORE and should thus decrement...
static unsigned int ir_total
Length of the DLL starting at ir_head.
static int in_shutdown
Indication if we have received a shutdown signal and are in the process of cleaning up.
static struct GNUNET_TIME_Relative validation_challenge_freq(const struct GNUNET_PeerIdentity *pid)
How slow are we allowed to get with challenges for pid?
static void select_best_pending_from_link(struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
Select the best pending message from vl for transmission via queue.
static void suggest_to_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Signature of a function called with a communicator address of a peer pid that an application wants us...
static void free_timedout_queue_entry(void *cls)
static void handle_send_message_ack(void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
Message was transmitted.
static void update_pd_age(struct PerformanceData *pd, unsigned int age)
Check if we have advanced to another age since the last time.
#define DV_LEARN_BASE_FREQUENCY
What is the non-randomized base frequency at which we would initiate DV learn messages?
struct GNUNET_SCHEDULER_Task * burst_timeout_task
static void free_pending_acknowledgement(struct PendingAcknowledgement *pa)
Release pa data structure.
static struct GNUNET_CONTAINER_MultiUuidmap * pending_acks
Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgemen...
static struct GNUNET_CONTAINER_MultiShortmap * dvlearn_map
Map from challenges to struct LearnLaunchEntry values.
#define DV_FORWARD_TIMEOUT
If a DVBox could not be forwarded after this number of seconds we drop it.
static void finish_handling_raw_message(struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
static void handle_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static void update_queue_performance(struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via q, update metrics.
static void schedule_transmit_on_queue(struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
Called whenever something changed that might effect when we try to do the next transmission on queue ...
static void set_pending_message_uuid(struct PendingMessage *pm)
If necessary, generates the UUID for a pm.
static void free_pending_message(struct PendingMessage *pm)
Release memory associated with pm and remove pm from associated data structures.
static void revalidation_start_cb(void *cls)
static void backtalker_monotime_store_cb(void *cls, int success)
Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
static int free_reassembly_cb(void *cls, uint32_t key, void *value)
function called to free_reassembly_context().
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Called whenever a client connects.
#define DV_PATH_VALIDITY_TIMEOUT
How long do we consider a DV path valid if we see no further updates on it? Note: the value chosen he...
static enum GNUNET_GenericReturnValue sign_ephemeral(struct DistanceVector *dv)
Sign the ephemeral key in dv, and mark it current.
#define RING_BUFFER_SIZE
Size of ring buffer to cache CORE and forwarded DVBox messages.
static void check_vl_transmission(struct VirtualLink *vl)
There is a message at the head of the pending messages for vl which may be ready for transmission.
static int find_by_message_uuid(void *cls, uint32_t key, void *value)
Iterator called to find a reassembly context by the message UUID in the multihashmap32.
static struct TransportClient * lookup_communicator(const char *prefix)
Find transport client providing communication service for the protocol prefix.
static unsigned int ring_buffer_head
Head of the ring buffer.
#define MAX_ADDRESS_VALID_UNTIL
When do we forget an invalid address for sure?
static void handle_hello_for_client(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
#define SHUTDOWN_CLIENT_GRACE_PERIOD
How long do we wait during shutdown for our clients to disconnect on their own before we drop them?...
static void transmit_dv_init(struct TransportDVLearnMessage dvl, struct LearnLaunchEntry *lle, struct QueueQualityContext qqc)
Finish and transmit the DV learn message dvl we initiated.
static void handle_suggest_cancel(void *cls, const struct ExpressPreferenceMessage *msg)
An application client no longer wants us to connect to a peer it asked for earlier.
static void update_performance_data(struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully tran...
static void forward_dv_box(struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
Create a DV Box message and queue it for transmission to next_hop.
static void handle_validation_response(void *cls, const struct TransportValidationResponseMessage *tvr)
Communicator gave us a transport address validation response.
static void handle_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static int free_virtual_link_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free virtual link entry.
static void send_msg_from_cache(struct VirtualLink *vl)
static void free_address_list_entry(struct AddressListEntry *ale)
Free ale.
static void free_burst_cls(struct GNUNET_StartBurstCls *sb_cls)
Release a burst closure, detaching it from its virtual link and from the scheduled burst_task (if tha...
static unsigned int pick_random_dv_hops(const struct DistanceVector *dv, enum RouteMessageOptions options, struct DistanceVectorHop **hops_array, unsigned int hops_array_length)
Pick hops_array_length random DV paths satisfying options.
static void handle_burst_finished(void *cls, const struct GNUNET_TRANSPORT_BurstFinished *bf)
The burst finished.
static void hello_for_incoming_sync_cb(void *cls)
static enum GNUNET_GenericReturnValue resume_communicators(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define FC_KEEPALIVE_INTERVAL
How long may a confirmed virtual link go without us sending anything on it before we transmit an othe...
static struct PilsRequest * pils_requests_tail
PILS Operation DLL.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Map from PIDs to struct Neighbour entries.
static void release_stalled_cmc(struct VirtualLink *vl, struct CommunicatorMessageContext *cmc)
Take cmc off the list of messages waiting on vl's CORE receive window, release the flow control credi...
static void transmit_on_queue(void *cls)
We believe we are ready to transmit a message on a queue.
static void handle_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void iterate_address_start_burst(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void disconnect_and_free_virtual_link(struct VirtualLink *vl)
Tell CORE clients the link to vl is gone, then release it.
static struct Queue * find_queue(const struct GNUNET_PeerIdentity *pid, const char *address)
Find the queue matching pid and address.
static void activate_core_visible_dv_path(struct DistanceVectorHop *hop)
The hop is a validated path to the respective target peer and we should tell core about it – and sche...
static void free_dv_route(struct DistanceVector *dv)
Free entry in dv_routes.
static unsigned int is_ring_buffer_dv_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static int check_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
#define DEFAULT_WINDOW_SIZE
How big is the flow control window size by default; limits per-neighbour RAM utilization.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate transport service.
#define MAX_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges?
static void cancel_address_store(struct AddressListEntry *ale)
Abort the asynchronous sign-and-store chain (if any) that is currently running for ale and release it...
static void handle_queue_create_ok(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue "worked", that is setting up the queue is no...
static enum GNUNET_GenericReturnValue sign_by_my_identity(const struct GNUNET_CRYPTO_SignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
Sign purpose with the private key of our current peer identity.
static int notify_client_connect_info(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new CORE client about all existing connections to peers.
static void core_fc_stalled(void *cls)
CORE never returned the flow control credit for the messages we handed it for cls,...
static void shc_cont(void *cls, int success)
static void handle_raw_message(void *cls, const struct GNUNET_MessageHeader *mh)
Communicator gave us an unencapsulated message to pass as-is to CORE.
static void handle_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
static struct Queue * find_queue_by_ip(const struct GNUNET_PeerIdentity *pid, const char *address)
Find a queue to pid whose address has the same IP as address, but possibly a different port.
static unsigned long long logging_uuid_gen
Generator of logging_uuid in struct PendingMessage.
static int check_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Client notified us about transmission from a peer.
#define REASSEMBLY_EXPIRATION
How long do we keep partially reassembled messages around before giving up?
static void update_next_challenge_time(struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
Set the time for next_challenge of vs to new_time.
static struct Neighbour * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup neighbour for peer pid.
static void peerstore_store_own_cb(void *cls, int success)
Function called when peerstore is done storing our address.
static struct RingBufferEntry * ring_buffer[RING_BUFFER_SIZE]
Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
#define MIN_DELAY_ADDRESS_VALIDATION
What is the maximum frequency at which we do address validation? A random value between 0 and this va...
static void handle_acknowledged(struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
The pa was acknowledged, process the acknowledgement.
static struct GNUNET_CONTAINER_MultiPeerMap * backtalkers
Map from PIDs to struct Backtalker entries.
static struct GNUNET_TIME_Absolute hello_mono_time
Monotonic time we use for HELLOs generated at this time.
static int check_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static char * communicator_list(struct Neighbour *n, unsigned int *num_queues)
Build the 0-terminated, comma-separated list of address prefixes of the communicators that own the qu...
static void handle_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct GNUNET_CONTAINER_MultiHashMap * revalidation_map
Map from addresses to struct ValidationState entries describing addresses we are aware of and their v...
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
static enum GNUNET_GenericReturnValue revalidate_map_it(void *cls, const struct GNUNET_HashCode *key, void *value)
#define DEFAULT_ACK_WAIT_DURATION
Default value for how long we wait for reliability ack.
static struct PendingMessage * reliability_box_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Reliability-box the given pm.
static int free_backtalker_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Callback to free backtalker records.
static enum GNUNET_GenericReturnValue contains_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void path_cleanup_cb(void *cls)
Task called when we should check if any of the DV paths we have learned to a target are due for garba...
#define FAST_VALIDATION_CHALLENGE_FREQ
What is the fastest rate at which we send challenges if we keep learning an address (gossip,...
static int check_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void demultiplex_with_cmc(struct CommunicatorMessageContext *cmc)
Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the ri...
#define MAX_DV_LEARN_PENDING
Maximum number of DV learning activities we may have pending at the same time.
static void hello_for_client_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void validation_start_cb(void *cls)
Task run periodically to validate some address based on validation_heap.
#define VALIDATION_RTT_BUFFER_FACTOR
How many network RTTs before an address validation expires should we begin trying to revalidate?...
static void handle_client_recv_ok(void *cls, const struct RecvOkMessage *rom)
Client confirms that it is done handling message(s) to a particular peer.
static void feed_addresses_to_pils(void *cls)
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
static int check_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static int check_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct TransportClient * clients_tail
Tail of linked list of all clients to this service.
static struct GNUNET_CONTAINER_MultiPeerMap * ack_cummulators
Map from PIDs to struct AcknowledgementCummulators.
static void transmit_cummulative_ack_cb(void *cls)
Do the transmission of a cumulative acknowledgement now.
static int check_validation_request_pending(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
A new queue has been created, check if any address validation requests have been waiting for it.
static void resume_cmc_client(struct CommunicatorMessageContext *cmc)
Let the communicator that delivered cmc give us its next message.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static const struct GNUNET_MessageHeader * hello_from_record(const struct GNUNET_PEERSTORE_Record *record)
Obtain the HELLO message stored in record, if record actually carries one.
static struct GNUNET_SCHEDULER_Task * burst_task
The task to start the burst.
static void send_t_validation_response(struct CommunicatorMessageContext *cmc, struct TransportValidationResponseMessage tvr)
Route the signed validation response tvr back to the challenger and release cmc.
void print_address_list(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_TIME_Relative encapsulate_for_dv(struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
Pick a path of dv under constraints options and schedule transmission of hdr.
static void suggest_retry_cb(void *cls)
Task run for as long as an application client wants a link to pid that we do not have.
static void neighbour_store_dvmono_cb(void *cls, int success)
Function called when peerstore is done storing a DV monotonic time.
static void handle_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
A client encountered an address of another peer.
static void free_queue_entry(struct QueueEntry *qe, struct TransportClient *tc)
static void pils_sign_hello_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Get HELLO signature and create message to store in PEERSTORE.
static void check_for_global_natted_sync_cb(void *cls)
#define UNCONFIRMED_LINK_TIMEOUT
How long do we keep a virtual link that only exists because some peer sent us a FLOW_CONTROL message,...
static void handle_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void notify_monitor(struct TransportClient *tc, const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Notify monitor tc about an event.
static void check_for_burst_address(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
static unsigned int check_next_attempt_tree(struct PendingMessage *pm, struct PendingMessage *root)
static void hello_for_incoming_error_cb(void *cls)
static struct GNUNET_StartBurstCls * burst_task_cls
Closure of the currently scheduled burst_task, or NULL.
static void send_ok_to_client(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Return one unit of send window credit for pid to tc.
static void queue_send_msg(struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
Send the message payload on queue.
static void handle_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
#define MIN_ADDRESS_REFRESH_INTERVAL
How often are we willing to re-sign and re-store one of our own addresses in PEERSTORE,...
static int check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void handle_hello_for_incoming(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void try_to_bring_link_up(const struct GNUNET_PeerIdentity *pid)
Ask for everything that could give us a confirmed virtual link to pid: revalidate the addresses we al...
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static int check_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void iterate_address_and_compare_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validi...
static struct GNUNET_TIME_Relative dvlearn_pils_backoff
Backoff for start_dv_learn() while PILS still owes us an identity.
#define MIN_FC_RETRANSMIT_DELAY
Lower bound on the delay between two flow control transmissions on the same virtual link.
static int free_dv_routes_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free DV route entry.
static enum GNUNET_GenericReturnValue add_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR
Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope...
static void handle_queue_create_fail(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue failed.
static void check_link_down(void *cls)
Task run to check whether the hops of the cls still are validated, or if we need to core about discon...
static void check_for_global_natted_error_cb(void *cls)
static void finish_cmc_handling_with_continue(struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
Send ACK to communicator (if requested) and free cmc.
static void forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
Build and forward a DV learn message to next_hop.
static void handle_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Incoming message.
static void validation_transmit_on_queue(struct Queue *q, struct ValidationState *vs)
The queue q (which matches the peer and address in vs) is ready for queueing.
static int free_ack_cummulator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free acknowledgement cummulator.
static void update_pm_next_attempt(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission ...
#define PILS_FEED_ADDRESSES_DELAY
Delay between added/removed addresses and PILS feed call.
static int check_known_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the address from cls.
enum GNUNET_GenericReturnValue use_burst
static struct GNUNET_CONTAINER_MultiPeerMap * dv_routes
Map from PIDs to struct DistanceVector entries describing known paths to the peer.
static void detach_cmcs_from_client(const struct TransportClient *tc)
A communicator client is going away.
static struct GNUNET_TIME_Relative route_control_message_without_fc(struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
We need to transmit hdr to target.
static void free_incoming_request(struct IncomingRequest *ir)
Release ir data structure.
#define MAX_INCOMING_REQUEST
For how many incoming connections do we try to create a virtual link for (at the same time!...
static void neighbour_dv_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a DV initiator by PEERSTORE.
static struct GNUNET_PILS_Handle * pils
Service that manages our peer id.
static void start_peer_request_monitor(struct PeerRequest *pr)
(Re)start the PEERSTORE HELLO monitor of pr.
void(* DVMessageHandler)(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static char * get_address_without_port(const char *address)
Get the IP address without the communicator prefix and the port number.
ClientType
What type of client is the struct TransportClient about?
@ CT_APPLICATION
"Application" telling us where to connect (i.e.
@ CT_MONITOR
It is a monitor, forward monitor data.
@ CT_NONE
We do not know yet (client is fresh).
@ CT_CORE
Is the CORE service, we need to forward traffic to it.
@ CT_COMMUNICATOR
It is a communicator, use for communication.
#define NEIGHBOUR_LIVENESS_TIMEOUT
How long may a direct neighbour stay completely silent before we stop believing that its queues work,...
static int validate_dv_initiator_signature(struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, const struct GNUNET_PeerIdentity *init, const struct GNUNET_CRYPTO_ChallengeNonceP *challenge, const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
#define MAX_REASSEMBLY_CONTEXTS
Maximum number of messages we are willing to reassemble in parallel for a single virtual link.
static void unconfirmed_link_timeout(void *cls)
Discard a virtual link that only ever existed because some peer sent us a FLOW_CONTROL message and th...
static struct IncomingRequest * ir_head
List of incoming connections where we are trying to get a connection back established.
static void free_backtalker(struct Backtalker *b)
Free data structures associated with b.
static void hello_for_client_sync_cb(void *cls)
static void destroy_ack_cummulator(void *cls)
Clean up an idle cumulative acknowledgement data structure.
static void consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define CORE_FC_STALL_TIMEOUT
How long do we wait for CORE to return the flow control credit for the messages we handed it before w...
static unsigned int bsize
static struct GNUNET_TRANSPORT_LinkListContext * llc
Handle to the running listing, NULL once it completed.
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
static struct GNUNET_TIME_Relative duration
Option '-d': duration of the mapping.
Definition gnunet-vpn.c:90
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Helper library for handling HELLO URIs.
API to the peerstore service.
enum GNUNET_GenericReturnValue GNUNET_PILS_enable_private_key(struct GNUNET_PILS_Handle *handle)
Enable local access to the private key of the current peer identity.
Definition pils_api.c:896
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:624
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:647
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_hello(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *builder, struct GNUNET_TIME_Absolute et, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Create HELLO signature.
Definition pils_api.c:851
const struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_PILS_get_private_key(const struct GNUNET_PILS_Handle *handle)
Return the private key of the current peer identity.
Definition pils_api.c:943
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:776
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:875
void GNUNET_PILS_feed_addresses(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *addresses_builder)
Feed a set of addresses to pils so that it will generate a new peer id based on the given set of addr...
Definition pils_api.c:817
uint32_t dim
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE
Signature by a peer affirming that it received a challenge (and stating how long it expects the addre...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
Signature by a peer affirming that the given ephemeral key is currently in use by that peer's transpo...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
Signature by a peer affirming that it originated the DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
Signature by a peer affirming that it is on a DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS
Signature by a peer affirming that this is one of its addresses for the given time period.
API to create, modify and access statistics.
API of the transport service towards the communicator processes.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
GNUNET_TRANSPORT_CommunicatorCharacteristics
What characteristics does this communicator have?
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_LINK_ROUTE_DV
Over a distance vector path.
@ GNUNET_TRANSPORT_LINK_ROUTE_DIRECT
Over one or more queues to a directly connected neighbour.
@ GNUNET_TRANSPORT_CS_DOWN
Connection is down.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
uint64_t GNUNET_CRYPTO_random_u64(uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_decrypt(size_t ct_len, const unsigned char ct[ct_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, const struct GNUNET_CRYPTO_AeadMac *mac, void *pt)
Decrypt the given data using XChaCha20-Poly1305.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_SignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition crypto_ecc.c:646
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_encrypt(size_t pt_len, const unsigned char pt[pt_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, void *ct, struct GNUNET_CRYPTO_AeadMac *mac)
Encrypt the given data using XChaCha20-Poly1305.
void GNUNET_CRYPTO_random_block(void *buffer, size_t length)
Fill block with a random values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
uint32_t GNUNET_CRYPTO_random_u32(uint32_t i)
Produce a random value.
#define GNUNET_CONTAINER_MDLL_remove(mdll, head, tail, element)
Remove an element from a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_tail(mdll, head, tail, element)
Insert an element at the tail of a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_after(mdll, head, tail, other, element)
Insert an element into a MDLL after the given other element.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_MDLL_insert(mdll, head, tail, element)
Insert an element at the head of a MDLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
struct GNUNET_CONTAINER_MultiUuidmap * GNUNET_CONTAINER_multiuuidmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_remove(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
unsigned int GNUNET_CONTAINER_multihashmap32_size(const struct GNUNET_CONTAINER_MultiHashMap32 *map)
Get the number of key-value pairs in the map.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_remove(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, const void *value)
Remove the given key-value pair from the map.
void GNUNET_CONTAINER_multiuuidmap_destroy(struct GNUNET_CONTAINER_MultiUuidmap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_iterate(struct GNUNET_CONTAINER_MultiUuidmap *map, GNUNET_CONTAINER_MultiUuidmapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_put(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multiuuidmap_get(const struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:380
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:398
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:344
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition hello-uri.c:1033
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_parser(const struct GNUNET_HELLO_Parser *parser, struct GNUNET_PeerIdentity *pid)
Allocate builder from parser.
Definition hello-uri.c:361
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_iterate(const struct GNUNET_HELLO_Parser *parser, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a parser.
Definition hello-uri.c:1052
struct GNUNET_MQ_Envelope * GNUNET_HELLO_parser_to_env(const struct GNUNET_HELLO_Parser *parser)
Generate envelope with GNUnet HELLO message (including peer ID) from a parser.
Definition hello-uri.c:980
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_address_list_cmp(const struct GNUNET_HELLO_Builder *abuilder, const struct GNUNET_HELLO_Builder *bbuilder)
Compare address lists of two builders.
Definition hello-uri.c:1408
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_del_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Remove individual address from the builder.
Definition hello-uri.c:1009
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:354
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid)
Parse msg.
Definition hello-uri.c:416
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_add_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Add individual address to the builder.
Definition hello-uri.c:701
char * GNUNET_HELLO_address_to_prefix(const char *address)
Given an address as a string, extract the prefix that identifies the communicator offering transmissi...
Definition hello-uri.c:1139
struct GNUNET_MQ_Envelope * GNUNET_HELLO_builder_to_env(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration_time)
Generate envelope with GNUnet HELLO message (including peer ID) from a builder.
Definition hello-uri.c:1219
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
GNUNET_SCHEDULER_Priority
Valid task priorities.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
#define GNUNET_static_assert(cond)
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_EXTRA_LOGGING
define GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source tree where gnunet_config....
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:337
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition mq.c:317
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_check_boxed_message(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition mq.c:687
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:928
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_try_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Same as GNUNET_MQ_handle_message(), except that a message for which no handler is registered is not l...
Definition mq.c:291
@ GNUNET_MQ_PRIO_BACKGROUND
Lowest priority, i.e.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
@ GNUNET_MQ_PREF_LOW_LATENCY
Flag to indicate that low latency is important.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition nat.c:89
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
void GNUNET_NAT_add_global_address(struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
Add global address to the list of addresses and notify clients.
Definition nat_api.c:460
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
#define GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME
Key used to store sender's monotonic time from backchannel messages.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
#define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME
Key used to store sender's monotonic time from DV learn messages.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
void GNUNET_PEERSTORE_hello_add_cancel(struct GNUNET_PEERSTORE_StoreHelloContext *huc)
Cancel the request to add a hello.
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY
Key used for storing HELLOs in the peerstore.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
struct GNUNET_PEERSTORE_StoreHelloContext * GNUNET_PEERSTORE_hello_add(struct GNUNET_PEERSTORE_Handle *h, const struct GNUNET_MessageHeader *msg, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Add hello to peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
P2P message: transport requests confirmation that an address works.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK
transport acknowledges processing an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_RESPONSE
Information about a single virtual link, in response to a GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_REQ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN
inform transport that a queue was torn down
#define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
Type of the 'struct RequestHelloValidationMessage' send by clients to TRANSPORT to trigger validation...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START
Message from the core saying that the transport server should start giving it messages.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA
Message sent to indicate to a monitor about events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_REQUEST
Request a one-shot listing of the virtual links transport currently has, with their flow control stat...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR
Message sent to indicate to the transport which address prefix is supported by a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
Message telling transport to limit its receive rate.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
Type of a fragment of a CORE message created by transport to adjust message length to a queue's MTU.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL
Response from communicator: address bogus, will not try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
Source-routed transport message based DV information gathered.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
Wrapper around non-fragmented CORE message used to measure RTT and ensure reliability.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to abandon bandwidth prefe...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
Message from TRANSPORT notifying about a message that was received.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION
Message type used between transport services when they internally forward communicator backchannel me...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE
transport tells communicator it wants a queue
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
Message sent for topology discovery at transport level.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
Tell transport that it should assist with exchanging a message between communicators.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
Message from TRANSPORT notifying about a client that disconnected from us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG
inform transport about an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK
Response from communicator: will try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_RESPONSE_END
End of the responses to a GNUNET_MESSAGE_TYPE_TRANSPORT_LINK_LIST_REQUEST.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK
communicator tells transports that message was sent
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS
inform transport to add an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START
Message sent to indicate to the transport that a monitor wants to observe certain events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS
inform transport to delete an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
P2P message: transport proves that an address worked.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG
transport tells communicator it wants to transmit
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
Request to TRANSPORT to transmit a message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
Confirmation from TRANSPORT that message for transmission has been queued (and that the next message ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
Confirmation for a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP
inform transport that a queue was setup to talk to some peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to establish bandwidth pre...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE
inform transport that a queue was updated
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1260
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1213
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition service.c:2512
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2528
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition strings.c:1629
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition time.c:344
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition time.c:264
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition time.c:626
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition time.c:352
#define GNUNET_TIME_relative_cmp(t1, op, t2)
Compare two relative times.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition time.c:368
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:610
struct GNUNET_TIME_Relative GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIME_Relative threshold)
Randomized exponential back-off, starting at 1 ms and going up by a factor of 2+r,...
Definition time.c:830
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition time.c:601
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply_double(struct GNUNET_TIME_Relative rel, double factor)
Multiply relative time by a given factor.
Definition time.c:506
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition time.c:583
struct GNUNET_TIME_Relative GNUNET_TIME_randomize(struct GNUNET_TIME_Relative r)
Return a random time value between 0.5*r and 1.5*r.
Definition time.c:851
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition time.c:471
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition time.c:360
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition time.c:616
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition time.c:452
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:860
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition time.c:548
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:671
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
Data structure in which we track acknowledgements still to be sent to the.
struct GNUNET_SCHEDULER_Task * task
Task scheduled either to transmit the cumulative ACK message, or to clean up this data structure afte...
struct GNUNET_TIME_Absolute min_transmission_time
When is task run (only used if num_acks is non-zero)?
struct TransportCummulativeAckPayload ack_uuids[64]
ACK data being accumulated.
struct GNUNET_PeerIdentity target
Target peer for which we are accumulating ACKs here.
unsigned int num_acks
Number of entries used in ack_uuids.
uint32_t ack_counter
Counter to produce the ack_counter in the struct TransportReliabilityAckMessage.
Unique identifier to map an acknowledgement to a transmission.
struct GNUNET_Uuid value
The UUID value.
size_t size
Capacity of tgnas, so that a drift between the cached ‘number_of_addresses’ / ‘size_of_global_address...
One of the addresses of this peer.
struct GNUNET_TIME_Relative expiration
What is a typical lifetime the communicator expects this address to have? (Always from now....
uint32_t aid
Address identifier used by the communicator.
struct GNUNET_TIME_Relative pils_backoff
Backoff used while waiting for PILS to hand us our peer identity.
size_t signed_address_len
Signed address length.
enum GNUNET_NetworkType nt
Network type offered by this address.
struct AddressListEntry * prev
Kept in a DLL.
struct TransportClient * tc
Which communicator provides this address?
struct AddressListEntry * next
Kept in a DLL.
struct GNUNET_PEERSTORE_StoreHelloContext * shc
Store hello handle.
void * signed_address
Signed address.
struct PilsAddressSignContext * pc
Context of the sign-and-store chain currently running for this entry, or NULL.
const char * address
The actual address.
struct GNUNET_SCHEDULER_Task * st
Task to periodically do st operation.
struct GNUNET_PEERSTORE_StoreContext * sc
Current context for storing this address in the peerstore.
A Backtalker is a peer sending us backchannel messages.
struct GNUNET_TIME_Absolute timeout
When will this entry time out?
struct CommunicatorMessageContext * cmc
Communicator context waiting on this backchannel's get, or NULL.
struct GNUNET_CRYPTO_HpkeEncapsulation last_ephemeral
Last (valid) ephemeral key received from this sender.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation for this pid's monotonic_time.
struct GNUNET_SCHEDULER_Task * task
Task associated with this backtalker.
size_t body_size
Number of bytes of the original message body that follows after this struct.
struct GNUNET_TIME_Absolute monotonic_time
Last (valid) monotonic time received from this sender.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch monotonic_time information from the PEERSTORE, or NULL.
struct GNUNET_PeerIdentity pid
Peer this is about.
Closure for check_known_address.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const char * address
Set to the address we are looking for.
Closure for check_known_challenge.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const struct GNUNET_CRYPTO_ChallengeNonceP * challenge
Set to the challenge we are looking for.
Context from handle_incoming_msg().
unsigned int client_resumed
Did we already call GNUNET_SERVICE_client_continue()? That call is per client, not per message,...
struct CommunicatorMessageContext * next
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
uint16_t total_hops
Number of hops the message has travelled (if DV-routed).
struct GNUNET_TRANSPORT_IncomingMessage im
Additional information for flow control and about the sender.
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
unsigned int ack_sent
Did we already send the flow control ACK to the communicator? The ACK is per-message and expresses CO...
struct CommunicatorMessageContext * prev
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
struct TransportClient * tc
Which communicator provided us with the message.
Message from the transport service to the library informing about neighbors.
Definition transport.h:90
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition transport.h:113
Closure for core_env_sent_cb.
uint16_t isize
By how much should we increment vl's incoming_fc_window_size_used once we are done sending to CORE?...
struct CoreSentContext * next
Kept in a DLL to clear vl in case vl is lost.
struct VirtualLink * vl
Virtual link this is about.
struct CoreSentContext * prev
Kept in a DLL to clear vl in case vl is lost.
uint16_t size
How big was the message.
An entry describing a peer on a path in a struct TransportDVLearnMessage message.
struct GNUNET_CRYPTO_EddsaSignature hop_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity hop
Identity of a peer on the path.
Message from the transport service to the library informing about disconnects.
Definition transport.h:122
One possible hop towards a DV target.
struct PerformanceData pd
Performance data for this transmission possibility.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used our path.
unsigned int distance
Number of hops in total to the target (excluding next_hop and target itself).
struct DistanceVectorHop * next_neighbour
Kept in a MDLL.
struct Neighbour * next_hop
What would be the next hop to target?
struct GNUNET_TIME_Absolute timeout
At what time do we forget about this path unless we see it again while learning?
struct DistanceVector * dv
Distance vector entry this hop belongs with.
const struct GNUNET_PeerIdentity * path
Array of distance hops to the target, excluding next_hop.
struct DistanceVectorHop * next_dv
Kept in a MDLL, sorted by timeout.
struct GNUNET_TIME_Absolute path_valid_until
For how long is the validation of this path considered valid? Set to ZERO if the path is learned by s...
struct DistanceVectorHop * prev_dv
Kept in a MDLL, sorted by timeout.
struct DistanceVectorHop * prev_neighbour
Kept in a MDLL.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used our path.
Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer.
struct DistanceVectorHop * dv_head
Known paths to target.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct GNUNET_TIME_Absolute monotime
What time was sender_sig created.
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature affirming ephemeral_key of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct DistanceVectorHop * dv_tail
Known paths to target.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Our ephemeral key.
struct GNUNET_ShortHashCode * km
Master secret for the setup of the Key material for the backchannel.
struct GNUNET_PeerIdentity target
To which peer is this a route?
struct GNUNET_TIME_Absolute ephemeral_validity
How long is sender_sig valid.
struct GNUNET_SCHEDULER_Task * timeout_task
Task scheduled to purge expired paths from dv_head MDLL.
Content signed by each peer during DV learning.
struct GNUNET_PeerIdentity pred
Identity of the previous peer on the path.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
Body by which a peer confirms that it is using an ephemeral key.
struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time
How long is this signature over the ephemeral key valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_PeerIdentity target
Target's peer identity.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
Application client to TRANSPORT service: we would like to have address suggestions for this peer.
Definition transport.h:948
Closure for find_by_message_uuid.
struct ReassemblyContext * rc
Set to the reassembly context if found.
struct MessageUUIDP message_uuid
UUID to look for.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
Wrapper struct with the average RTT of message to some peer and if this peer und us is ready to sync.
enum GNUNET_GenericReturnValue sync_ready
Is this peer already ready to sync.
struct GNUNET_TIME_RelativeNBO rtt_average
The average RTT for the peer to communicate with.
Handle to a node in a heap.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
type for session keys
type for session keys
Type of a nonce used for challenges.
struct GNUNET_ShortHashCode value
The value of the nonce.
Private ECC key encoded for transmission.
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Context for building (or parsing) HELLO URIs.
Definition hello-uri.c:185
Context for parsing HELLOs.
Definition hello-uri.c:233
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Message handler for a specific message type.
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
Handle to the PEERSTORE service.
Context for a iterate request.
Context for a store request.
Context for a add hello uri request.
A handle for the PILS service.
Definition pils_api.c:86
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition scheduler.c:141
Handle to a client that is connected to a service.
Definition service.c:249
Handle to a service.
Definition service.c:116
Handle for the service.
A 256-bit hashcode.
Struct wrapping information we use for starting the burst.
struct VirtualLink * vl
The VirtualLink of the peer to which we like to burst with.
struct GNUNET_TIME_Relative delay
The delay - calculate from the RTT and which peer was ready to sync first, after we will start the bu...
unsigned int sync_ready
We are ready to start the burst.
struct GNUNET_TIME_Relative rtt
The average RTT between the peers.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds and in network byte order.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Add address to the list.
Definition transport.h:289
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
Definition transport.h:293
struct GNUNET_TIME_RelativeNBO expiration
When does the address expire?
Definition transport.h:303
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:308
uint32_t aid
Address identifier (used during deletion).
Definition transport.h:298
Add queue to the transport.
Definition transport.h:403
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:422
uint32_t mtu
Maximum transmission unit, in NBO.
Definition transport.h:427
uint64_t q_len
Queue length, in NBO.
Definition transport.h:433
uint32_t qid
Queue identifier (used to identify the queue).
Definition transport.h:412
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:417
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
Definition transport.h:407
uint32_t cs
An enum GNUNET_TRANSPORT_ConnectionStatus in NBO.
Definition transport.h:443
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
Definition transport.h:269
uint32_t cc
NBO encoding of enum GNUNET_TRANSPORT_CommunicatorCharacteristics
Definition transport.h:274
uint32_t can_burst
The communicator can do burst msgs.
Definition transport.h:279
Message from transport to communicator passing along a backchannel message from the given peer pid.
Definition transport.h:657
struct GNUNET_PeerIdentity pid
Origin peer.
Definition transport.h:672
Message from communicator to transport service asking for transmission of a backchannel message with ...
Definition transport.h:628
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL.
Definition transport.h:632
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:642
Communicator tells transport how queue creation went down.
Definition transport.h:547
uint32_t request_id
Unique ID for the request.
Definition transport.h:557
Transport tells communicator that it wants a new queue.
Definition transport.h:523
uint32_t request_id
Unique ID for the request.
Definition transport.h:532
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:537
Remove address from the list.
Definition transport.h:318
uint32_t aid
Address identifier.
Definition transport.h:327
Remove queue, it is no longer available.
Definition transport.h:501
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:515
uint32_t qid
Address identifier.
Definition transport.h:510
Transport informs us about being done with an incoming message.
Definition transport.h:376
struct GNUNET_PeerIdentity sender
Sender identifier of the original message.
Definition transport.h:395
uint64_t fc_id
Which message is being ACKed?
Definition transport.h:390
uint32_t reserved
Reserved (0)
Definition transport.h:385
Inform transport about an incoming message.
Definition transport.h:335
struct GNUNET_PeerIdentity neighbour_sender
Direct neighbour sender identifier.
Definition transport.h:365
struct GNUNET_TIME_RelativeNBO expected_address_validity
How long does the communicator believe the address on which the message was received to remain valid?
Definition transport.h:355
struct GNUNET_PeerIdentity sender
Sender identifier.
Definition transport.h:360
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
Definition transport.h:339
uint32_t fc_on
Do we use flow control or not?
Definition transport.h:344
uint64_t fc_id
64-bit number to identify the matching ACK.
Definition transport.h:349
struct GNUNET_MQ_Handle * mq
Queue to talk to the transport service.
Request a one-shot listing of our virtual links.
Definition transport.h:783
State of one virtual link.
Definition transport.h:805
uint32_t stalled
Number of messages whose flow control ACK we are withholding because core_recv_window is exhausted.
Definition transport.h:849
struct GNUNET_TIME_AbsoluteNBO last_fc_transmission
When did we last send a flow control message?
Definition transport.h:910
uint32_t fc_retransmit_count
Number of flow control retransmissions of the running task.
Definition transport.h:859
uint32_t num_queues
Number of queues to the neighbour, 0 if route is GNUNET_TRANSPORT_LINK_ROUTE_DV.
Definition transport.h:836
uint64_t incoming_fc_window_size_ram
RAM currently held for this link.
Definition transport.h:869
uint64_t incoming_fc_window_size_used
How much of incoming_fc_window_size the other peer used.
Definition transport.h:879
uint32_t pending
Number of messages queued for transmission to target.
Definition transport.h:854
int64_t incoming_fc_window_size_loss
Current estimate of the message loss rate for the sender.
Definition transport.h:885
struct GNUNET_TIME_RelativeNBO other_rtt
RTT over all DV paths, as calculated by the target.
Definition transport.h:905
uint64_t outbound_fc_window_size
Window the other peer granted us.
Definition transport.h:890
uint64_t outbound_fc_window_size_used
How much of outbound_fc_window_size we used.
Definition transport.h:895
uint64_t incoming_fc_window_size
Window we last granted the other peer.
Definition transport.h:874
uint32_t route
An ‘enum GNUNET_TRANSPORT_LinkRoute’ in NBO.
Definition transport.h:824
uint32_t distance
Distance of the DV path, 0 if route is GNUNET_TRANSPORT_LINK_ROUTE_DIRECT.
Definition transport.h:830
struct GNUNET_PeerIdentity target
Peer at the other end of the link.
Definition transport.h:814
struct GNUNET_TIME_RelativeNBO last_fc_rtt
RTT of the last flow control exchange.
Definition transport.h:900
uint32_t confirmed
GNUNET_YES if the link is confirmed, i.e.
Definition transport.h:819
int32_t core_recv_window
How many more messages we may hand to CORE before it must acknowledge them.
Definition transport.h:843
uint64_t available_fc_window_size
RAM we are willing to spend on this link.
Definition transport.h:864
uint32_t num_msg_pending
Messages pending (in NBO).
Definition transport.h:768
struct GNUNET_PeerIdentity peer
Target identifier.
Definition transport.h:746
struct GNUNET_TIME_AbsoluteNBO valid_until
Definition transport.h:752
struct GNUNET_TIME_AbsoluteNBO last_validation
Definition transport.h:751
uint32_t num_bytes_pending
Bytes pending (in NBO).
Definition transport.h:773
struct GNUNET_TIME_AbsoluteNBO next_validation
Definition transport.h:753
uint32_t nt
Network type (an enum GNUNET_NetworkType in NBO).
Definition transport.h:741
struct GNUNET_TIME_RelativeNBO rtt
Current round-trip time estimate.
Definition transport.h:758
uint32_t cs
Connection status (in NBO).
Definition transport.h:763
Request to start monitoring.
Definition transport.h:710
Inform transport that message was sent.
Definition transport.h:594
uint32_t status
Success (GNUNET_OK), failure (GNUNET_SYSERR).
Definition transport.h:603
uint64_t mid
Message ID of the original message.
Definition transport.h:608
uint32_t qid
Queue ID for the queue which was used to send the message.
Definition transport.h:613
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:618
Inform communicator about transport's desire to send a message.
Definition transport.h:565
uint32_t qid
Which queue should we use?
Definition transport.h:574
uint64_t mid
Message ID, used for flow control.
Definition transport.h:579
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
Definition transport.h:569
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:584
Message from transport to communicator to start a burst.
Definition transport.h:682
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST.
Definition transport.h:686
struct GNUNET_TIME_RelativeNBO rtt
Definition transport.h:693
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:691
A UUID, a 128 bit "random" value.
Message used to notify the transport API about a message received from the network.
Definition transport.h:145
struct GNUNET_PeerIdentity peer
Which peer sent the message?
Definition transport.h:154
Another peer attempted to talk to us, we should try to establish a connection in the other direction.
struct IncomingRequest * next
Kept in a DLL.
struct IncomingRequest * prev
Kept in a DLL.
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
When did we launch this DV learning activity?
struct LearnLaunchEntry * next
Kept (also) in a DLL sorted by launch time.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge that uniquely identifies this activity.
struct LearnLaunchEntry * prev
Kept (also) in a DLL sorted by launch time.
struct GNUNET_TIME_Absolute launch_time
When did we transmit the DV learn message (used to calculate RTT) and determine freshness of paths le...
Closure for report_link().
int include_unconfirmed
Also report links that are not confirmed?
struct TransportClient * tc
Client asking for the listing.
Unique identifier we attach to a message.
uint64_t uuid
Unique value, generated by incrementing the message_uuid_ctr of struct Neighbour.
Details about what to notify monitors about.
enum GNUNET_TRANSPORT_ConnectionStatus cs
Connection status.
struct GNUNET_TIME_Absolute last_validation
struct GNUNET_TIME_Absolute next_validation
struct GNUNET_TIME_Absolute valid_until
struct GNUNET_TIME_Relative rtt
Current round-trip time estimate.
uint32_t num_msg_pending
Messages pending.
uint32_t num_bytes_pending
Bytes pending.
Closure for dv_neighbour_selection and dv_neighbour_transmission.
const struct TransportDVLearnMessage * dvl
Original message we received.
struct GNUNET_TIME_Absolute in_time
Time we received the message.
const struct DVPathEntryP * hops
The hops taken.
uint16_t bi_history
Bitmap of bidirectional connections encountered.
unsigned int num_eligible
Number of peers eligible for selection.
unsigned int num_selections
Number of peers that were selected for forwarding.
uint32_t selections[MAX_DV_DISCOVERY_SELECTION]
Offsets of the selected peers.
uint16_t nhops
Number of hops in hops.
A neighbour that at least one communicator is connected to.
size_t size_of_global_addresses
Size of all global natted addresses for this neighbour.
struct DistanceVectorHop * dv_tail
Tail of MDLL of DV hops that have this neighbour as next hop.
struct GNUNET_CONTAINER_MultiPeerMap * natted_addresses
Map of struct TransportGlobalNattedAddress for this neighbour.
struct GNUNET_TIME_Absolute last_dv_learn_monotime
Latest DVLearn monotonic time seen from this peer.
int dv_monotime_available
Do we have the latest value for last_dv_learn_monotime from PEERSTORE yet, or are we still waiting fo...
unsigned int number_of_addresses
Number of global natted addresses for this neighbour.
struct Queue * queue_tail
Tail of DLL of queues to this peer.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation to store this pid's last_dv_learn_monotime.
struct DistanceVectorHop * dv_head
Head of MDLL of DV hops that have this neighbour as next hop.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct Queue * queue_head
Head of DLL of queues to this peer.
struct GNUNET_TIME_Absolute last_inbound
When did a communicator last hand us a message that this peer sent us directly (i....
struct GNUNET_PeerIdentity pid
Which peer is this about?
enum GNUNET_GenericReturnValue is_global_natted
A queue of this neighbour has a global natted address.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch last_dv_learn_monotime information from the PEERSTORE,...
Message used to notify the transport service about a message to be transmitted to another peer.
Definition transport.h:231
uint32_t priority
An enum GNUNET_MQ_PriorityPreferences in NBO.
Definition transport.h:240
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND.
Definition transport.h:235
struct GNUNET_PeerIdentity peer
Which peer should receive the message?
Definition transport.h:254
Information per peer and request.
struct GNUNET_BANDWIDTH_Value32NBO bw
How much bandwidth would this tc like to see?
struct TransportClient * tc
Client responsible for the request.
struct GNUNET_SCHEDULER_Task * retry_task
Task that keeps trying to bring the link to pid up for as long as this request exists.
enum GNUNET_MQ_PriorityPreferences pk
What kind of performance preference does this tc have?
struct GSF_PendingRequest * pr
Handle to generic request (generic: from peer or local client).
struct GNUNET_TIME_Relative retry_backoff
Current delay between two runs of retry_task, growing from SUGGEST_RETRY_MIN to SUGGEST_RETRY_MAX.
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
Data structure kept when we are waiting for an acknowledgement.
struct AcknowledgementUUIDP ack_uuid
Unique identifier for this transmission operation.
unsigned int num_send
How often the PendingMessage was send via the Queue of this PendingAcknowledgement.
struct PendingAcknowledgement * next_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingMessage * pm
Message that was transmitted, may be NULL if the message was ACKed via another channel.
struct PendingAcknowledgement * next_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
struct PendingAcknowledgement * next_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct GNUNET_TIME_Absolute transmission_time
Time of the transmission, for RTT calculation.
struct Queue * queue
Queue used for transmission, NULL if the queue has been destroyed (which may happen before we get an ...
struct DistanceVectorHop * dvh
Distance vector path chosen for this transmission, NULL if transmission was to a direct neighbour OR ...
uint16_t message_size
Number of bytes of the original message (to calculate bandwidth).
struct PendingAcknowledgement * prev_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct PendingAcknowledgement * prev_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingAcknowledgement * prev_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
Context for select_best_pending_from_link().
struct GNUNET_TIME_Relative to_early_retry_delay
When will we try to transmit the message again for which it was to early to retry.
struct PendingMessage * best
Set to the best message that was found, NULL for none.
int to_early
There are pending messages, but it was to early to send one of them.
unsigned int consideration_counter
Number of pending messages we seriously considered this time.
struct DistanceVectorHop * dvh
DVH that best should take, or NULL for direct transmission.
size_t real_overhead
What is the estimated total overhead for this message?
unsigned int frags_in_flight
There is a pending messages we are sending fragments at the moment.
int frag
Did we have to fragment?
int relb
Did we have to reliability box?
List containing all messages that are yet to be send.
struct PendingMessage * tail_frag
Tail of a MDLL of fragments created for this core message.
struct PendingMessage * frag_parent
Our parent in the fragmentation tree.
enum GNUNET_MQ_PriorityPreferences prefs
Preferences for this message.
struct TransportClient * client
Client that issued the transmission request, if pmt is PMT_CORE.
struct QueueEntry * qe
Set to non-NULL value if this message is currently being given to a communicator and we are awaiting ...
struct MessageUUIDP msg_uuid
UUID to use for this message (used for reassembly of fragments, only initialized if msg_uuid_set is G...
struct PendingMessage * head_frag
Head of a MDLL of fragments created for this core message.
uint16_t bytes_msg
Size of the original message.
enum PendingMessageType pmt
Type of the pending message.
struct PendingMessage * prev_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
struct PendingMessage * prev_vl
Kept in a MDLL of messages for this vl.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs for this pending message.
struct PendingMessage * next_vl
Kept in a MDLL of messages for this vl.
struct VirtualLink * vl
Target of the request (always the ultimate destination!).
struct PendingAcknowledgement * pa_head
Head of DLL of PAs for this pending message.
struct DistanceVectorHop * used_dvh
If pmt is of type PMT_DV_BOX we store the used path here.
int16_t msg_uuid_set
GNUNET_YES once msg_uuid was initialized
uint32_t frags_in_flight_round
The round we are (re)-sending fragments.
struct PendingMessage * next_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
uint32_t frags_in_flight
Are we sending fragments at the moment?
uint16_t frag_off
Offset at which we should generate the next fragment.
struct PendingMessage * next_frag
Kept in a MDLL of messages from this cpm (if pmt is #PMT_FRAGMENT_BOx)
uint64_t logging_uuid
UUID we use to identify this message in our logs.
uint16_t frag_count
How many fragments do we have?
struct PendingMessage * prev_frag
Kept in a MDLL of messages from this cpm (if pmt is PMT_FRAGMENT_BOX)
struct PendingMessage * bpm
This message, reliability or DV-boxed.
int16_t client_credited
GNUNET_YES once the CORE send window credit for this message has been returned to client.
struct GNUNET_TIME_Absolute next_attempt
What is the earliest time for us to retry transmission of this message?
struct GNUNET_TIME_Absolute timeout
At what time should we give up on the transmission (and no longer retry)?
struct GNUNET_PeerIdentity target
In case of a not validated neighbour, we store the target peer.
Performance data for a transmission possibility.
struct GNUNET_TIME_Relative aged_rtt
Weighted average for the RTT.
struct TransmissionHistoryEntry the[4]
Historic performance data, using a ring buffer of::GOODPUT_AGING_SLOTS entries.
unsigned int last_age
What was the last age when we wrote to the? Used to clear old entries when the age advances.
Helper context struct for HELLO update.
struct GNUNET_TIME_Absolute et
Signature expiration.
struct AddressListEntry * ale
The ale to update.
struct PilsRequest * req
Any pending PILS requests.
struct GNUNET_PILS_Operation * op
The pils operation.
struct PilsRequest * next
DLL.
struct PilsRequest * prev
DLL.
Entry identifying transmission in one of our struct Queue which still awaits an ACK.
struct QueueEntry * next
Kept as a DLL.
struct QueueEntry * prev
Kept as a DLL.
struct GNUNET_TIME_Absolute creation_timestamp
Timestamp this QueueEntry was created.
uint64_t mid
Message ID used for this message with the queue used for transmission.
struct PendingMessage * pm
Pending message this entry is for, or NULL for none.
struct Queue * queue
Queue this entry is queued with.
Closure for check_connection_quality.
unsigned int k
Decremented for each queue, for selection of the k-th queue in q.
struct Queue * q
Set to the k'th queue encountered.
unsigned int num_queues
Set to the total number of queues encountered.
unsigned int quality_count
Set to the number of quality queues encountered.
Handle for a queue.
uint32_t qid
Unique identifier of this queue with the communicator.
struct QueueEntry * queue_tail
End of DLL of unacked transmission requests.
struct Queue * prev_client
Kept in a MDLL.
unsigned int queue_length
Length of the DLL starting at queue_head.
uint32_t num_msg_pending
Messages pending.
struct GNUNET_PEERSTORE_Monitor * mo
Handle for an operation to iterate through all hellos to compare the hello addresses with address whi...
uint64_t q_capacity
Capacity of the queue.
struct Queue * next_neighbour
Kept in a MDLL.
uint32_t num_bytes_pending
Bytes pending.
uint32_t priority
Queue priority.
struct Neighbour * neighbour
Which neighbour is this queue for?
int idle
Set to GNUNET_YES if this queue is idle waiting for some virtual link to give it a pending message.
struct Queue * prev_neighbour
Kept in a MDLL.
struct PerformanceData pd
Performance data for this queue.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_SCHEDULER_Task * transmit_task
Task scheduled for the time when this queue can (likely) transmit the next message.
struct QueueEntry * queue_head
Head of DLL of unacked transmission requests.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used this queue.
struct TransportClient * tc
Which communicator offers this queue?
struct Queue * next_client
Kept in a MDLL.
enum GNUNET_GenericReturnValue is_global_natted
Set to GNUNET_YES, if this queues address is a global natted one.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
uint32_t mtu
Maximum transmission unit supported by this queue.
unsigned int unlimited_length
Is this queue of unlimited length.
enum GNUNET_TRANSPORT_ConnectionStatus cs
The connection status of this queue.
uint64_t mid_gen
Message ID generator for transmissions on this queue to the communicator.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used this queue.
const char * address
Address served by the queue.
Information we keep for a message that we are reassembling.
struct GNUNET_CONTAINER_HeapNode * hn
Entry in the reassembly heap (sorted by expiration).
struct GNUNET_TIME_Absolute last_frag
Time we received the last fragment.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct VirtualLink * virtual_link
Which neighbour is this context for?
uint8_t * bitfield
Bitfield with msg_size bits representing the positions where we have received fragments.
uint16_t msg_size
How big is the message we are reassembling in total?
struct GNUNET_TIME_Absolute reassembly_timeout
At what time will we give up reassembly of this message?
uint16_t msg_missing
How many bytes of the message are still missing? Defragmentation is complete when msg_missing == 0.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:207
struct GNUNET_PeerIdentity peer
Which peer can CORE handle more from now?
Definition transport.h:222
uint32_t increase_window_delta
Number of messages by which to increase the window, greater or equal to one.
Definition transport.h:217
We got an address of another peer, TRANSPORT service should validate it.
Definition transport.h:979
Entry for the ring buffer caching messages send to core, when virtual link is available.
struct CommunicatorMessageContext * cmc
Communicator context for this ring buffer entry.
struct GNUNET_MessageHeader * mh
The message in this entry.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:163
struct GNUNET_PeerIdentity peer
Which peer can send more now?
Definition transport.h:197
Binary block we sign when we sign an address.
struct GNUNET_TIME_AbsoluteNBO mono_time
When was the address generated.
struct GNUNET_HashCode addr_hash GNUNET_PACKED
Hash of the address.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS.
Message from the transport service to the library asking to check if both processes agree about this ...
Definition transport.h:63
Information we keep per GOODPUT_AGING_SLOTS about historic (or current) transmission performance.
uint64_t bytes_received
Number of bytes received and acknowledged by the other peer in the interval.
uint64_t bytes_sent
Number of bytes actually sent in the interval.
Outer layer of an encapsulated backchannel message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
Client connected to the transport service.
enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc
Characteristics of this communicator.
struct PendingMessage * pending_msg_head
Head of list of messages pending for this client, sorted by transmission time ("next_attempt" + possi...
enum ClientType type
What type of client is this?
struct AddressListEntry * addr_tail
Tail of list of the addresses of this peer offered by this communicator.
union TransportClient::@68 details
struct TransportClient * next
Kept in a DLL.
struct GNUNET_MQ_Handle * mq
Message queue to the client.
struct GNUNET_SCHEDULER_Task * free_queue_entry_task
Task to check for timed out QueueEntry.
struct PendingMessage * pending_msg_tail
Tail of list of messages pending for this client.
struct TransportClient::@68::@72 application
Information for type CT_APPLICATION.
struct TransportClient::@68::@70 monitor
Information for type CT_MONITOR.
struct Queue * queue_head
Head of DLL of queues offered by this communicator.
struct AddressListEntry * addr_head
Head of list of the addresses of this peer offered by this communicator.
struct TransportClient::@68::@69 core
Information for type CT_CORE.
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of requests for peers the given client application would like to see connections for.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct TransportClient * prev
Kept in a DLL.
struct TransportClient::@68::@71 communicator
Information for type CT_COMMUNICATOR.
char * address_prefix
If type is CT_COMMUNICATOR, this communicator supports communicating using these addresses.
struct Queue * queue_tail
Tail of DLL of queues offered by this communicator.
unsigned int total_queue_length
Number of queue entries in all queues to this communicator.
int one_shot
Is this a one-shot monitor?
struct GNUNET_PeerIdentity peer
Peer identity to monitor the addresses of.
enum GNUNET_GenericReturnValue can_burst
Can be used for burst messages.
struct GNUNET_TIME_RelativeNBO ack_delay
How long was the ACK delayed for generating cumulative ACKs? Used to calculate the correct network RT...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
struct GNUNET_TIME_Absolute receive_time
When did we receive the message we are ACKing? Used to calculate the delay we introduced by cummulati...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
Outer layer of an encapsulated message send over multiple hops.
struct GNUNET_CRYPTO_AeadNonce iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX.
uint16_t num_hops
Number of hops this messages includes.
uint16_t orig_size
Size this msg had initially.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
struct GNUNET_CRYPTO_AeadMac mac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
uint16_t total_hops
Number of total hops this messages travelled.
uint32_t without_fc
Flag if the payload is a control message.
Plaintext of the variable-size payload that is encrypted within a struct TransportBackchannelEncapsul...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature of the sender over an GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Current monotonic time of the sending transport service.
struct GNUNET_PeerIdentity sender
Sender's peer identity.
Internal message used by transport for distance vector learning.
struct GNUNET_PeerIdentity initiator
Identity of the peer that started this learning activity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN.
struct GNUNET_TIME_RelativeNBO non_network_delay
Peers receiving this message and delaying forwarding to other peers for any reason should increment t...
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EddsaSignature init_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
uint16_t num_hops
Number of hops this messages has travelled, in NBO.
uint16_t bidirectional
Bitmask of the last 16 hops indicating whether they are confirmed available (without DV) in both dire...
Message for Transport-to-Transport Flow control.
uint64_t outbound_window_size
Latest flow control window size we learned from the other peer, in bytes, in NBO.
uint32_t number_of_addresses
Number of TransportGlobalNattedAddress following the struct.
uint64_t inbound_window_size
Flow control window size in bytes, in NBO.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender.
uint32_t seq
Sequence number of the flow control message.
uint32_t size_of_addresses
Size of all the addresses attached to all TransportGlobalNattedAddress.
uint64_t outbound_sent
How many bytes has the sender sent that count for flow control at this time.
struct GNUNET_TIME_RelativeNBO rtt
Average RTT for the DistanceVector of the VirtualLink we tell the target.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL.
uint32_t sync_ready
We tell the target, if we are ready to start the burst.
Outer layer of an encapsulated fragmented application message.
uint16_t frag_off
Offset of this fragment in the overall message.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct AcknowledgementUUIDP ack_uuid
Unique ID of this fragment (and fragment transmission!).
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT.
uint16_t msg_size
Total size of the message that is being fragmented.
struct TransportGlobalNattedAddress * tgna
The struct TransportGlobalNattedAddress to set.
uint32_t address_length
Length of the address following the struct in NBO.
Confirmation that the receiver got a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
uint32_t ack_counter
Counter of ACKs transmitted by the sender to us.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK.
Outer layer of an encapsulated unfragmented application message sent over an unreliable channel.
uint32_t ack_countdown
Number of messages still to be sent before a commulative ACK is requested.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
struct AcknowledgementUUIDP ack_uuid
Unique ID of the message used for signalling receipt of messages sent over possibly unreliable channe...
Message send to another peer to validate that it can indeed receive messages at a particular address.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge to be signed by the receiving peer.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender, to be copied into the reply to allow sender to calculate RTT.
Message signed by a peer to confirm that it can indeed receive messages at a particular address.
struct GNUNET_TIME_RelativeNBO validity_duration
How long does the sender believe the address on which the challenge was received to remain valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge signed by the receiving peer.
Message send to a peer to respond to a #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
The challenge that was signed by the receiving peer.
struct GNUNET_CRYPTO_EddsaSignature signature
The peer's signature matching the GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
struct GNUNET_PEERSTORE_StoreHelloContext * sc
State we keep for validation activities.
struct GNUNET_TIME_Absolute valid_until
How long did the peer claim this address to be valid? Capped at minimum of MAX_ADDRESS_VALID_UNTIL re...
struct GNUNET_PeerIdentity pid
For which peer is address to be validated (or possibly valid)? Serves as key in the validation_map.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
common internal definitions for transport service