GNUnet 0.26.2-24-g10badbb4a
 
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 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_util_lib.h"
79#include "gnunet_pils_service.h"
81#include "gnunet_nat_service.h"
83#include "gnunet_signatures.h"
84#include "transport.h"
85
89#define RING_BUFFER_SIZE 16
90
94#define MAX_FC_RETRANSMIT_COUNT 1000
95
100#define MAX_CUMMULATIVE_ACKS 64
101
114#define FC_NO_CHANGE_REPLY_PROBABILITY 8
115
120#define IN_PACKET_SIZE_WITHOUT_MTU 128
121
126#define GOODPUT_AGING_SLOTS 4
127
132#define DEFAULT_WINDOW_SIZE (128 * 1024)
133
142#define MAX_INCOMING_REQUEST 16
143
148#define MAX_DV_DISCOVERY_SELECTION 16
149
158#define RECV_WINDOW_SIZE 4
159
167#define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
168
172#define MAX_DV_HOPS_ALLOWED 16
173
178#define MAX_DV_LEARN_PENDING 64
179
183#define MAX_DV_PATHS_TO_TARGET 3
184
191#define PILS_FEED_ADDRESSES_DELAY \
192 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
193
199#define DELAY_WARN_THRESHOLD \
200 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
201
206#define DV_FORWARD_TIMEOUT \
207 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
208
212#define DEFAULT_ACK_WAIT_DURATION \
213 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
214
220#define DV_QUALITY_RTT_THRESHOLD \
221 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
222
227#define DV_PATH_VALIDITY_TIMEOUT \
228 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
229
234#define BACKCHANNEL_INACTIVITY_TIMEOUT \
235 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
236
241#define DV_PATH_DISCOVERY_FREQUENCY \
242 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
243
247#define EPHEMERAL_VALIDITY \
248 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
249
253#define REASSEMBLY_EXPIRATION \
254 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
255
260#define FAST_VALIDATION_CHALLENGE_FREQ \
261 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
262
266#define MAX_VALIDATION_CHALLENGE_FREQ \
267 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
268
274#define ACK_CUMMULATOR_TIMEOUT \
275 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
276
281#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
282
287#define DV_LEARN_QUALITY_THRESHOLD 100
288
292#define MAX_ADDRESS_VALID_UNTIL \
293 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
294
298#define ADDRESS_VALIDATION_LIFETIME \
299 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
300
307#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
308
315#define VALIDATION_RTT_BUFFER_FACTOR 3
316
323#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
324
330#define QUEUE_LENGTH_LIMIT 32
331
335#define QUEUE_ENTRY_TIMEOUT \
336 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
337
342#define RTT_DIFF \
343 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
344
346
351{
357};
358
359
370
375{
380
381 /* Followed by *another* message header which is the message to
382 the communicator */
383
384 /* Followed by a 0-terminated name of the communicator */
385};
386
387
425
426
432{
437
443
455
456 /* Followed by a `struct GNUNET_MessageHeader` with a message
457 for the target peer */
458};
459
460
487
488
507
508
517{
522
528
529 /* followed by any number of `struct TransportCummulativeAckPayloadP`
530 messages providing ACKs */
531};
532
533
569
570
614
615
654
655
673
674
689{
694
700
710
717
731
737
742
747
748 /* Followed by @e num_hops `struct DVPathEntryP` values,
749 excluding the initiator of the DV trace; the last entry is the
750 current sender; the current peer must not be included. */
751};
752
753
777{
782
786 unsigned int without_fc;
787
795
802
808
815
822
829
830 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
831 excluding the @e origin and the current peer, the last must be
832 the ultimate target; if @e num_hops is zero, the receiver of this
833 message is the ultimate target. */
834
835 /* Followed by encrypted, variable-size payload, which
836 must begin with a `struct TransportDVBoxPayloadP` */
837
838 /* Followed by the actual message, which itself must not be a
839 a DV_LEARN or DV_BOX message! */
840};
841
842
870
871
894
895
935
937{
941 unsigned int address_length;
942
943 /* Followed by @e address_length bytes of the address. */
944};
945
955{
960
969
975
982
992
1002
1007
1011 unsigned int sync_ready;
1012
1017
1022
1023 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1024};
1025
1027
1028
1033{
1038
1043
1048
1053
1057 CT_APPLICATION = 4
1059
1060
1094
1095
1122
1123
1129{
1133 uint64_t bytes_sent;
1134
1140};
1141
1142
1165
1166
1170struct TransportClient;
1171
1175struct Neighbour;
1176
1181struct DistanceVector;
1182
1187struct Queue;
1188
1192struct PendingMessage;
1193
1197struct DistanceVectorHop;
1198
1207struct VirtualLink;
1208
1209
1254
1255
1271
1272
1277{
1282
1287
1292
1296 uint16_t size;
1297
1304 uint16_t isize;
1305};
1306
1307
1312{
1318
1323
1328
1336 uint8_t *bitfield;
1337
1342
1348
1352 uint16_t msg_size;
1353
1358 uint16_t msg_missing;
1359
1360 /* Followed by @e msg_size bytes of the (partially) defragmented original
1361 * message */
1362
1363 /* Followed by @e bitfield data */
1364};
1365
1366
1376{
1381
1388
1395
1400
1406
1412
1417
1422
1427
1432
1440
1446
1451
1456
1461
1466 unsigned int confirmed;
1467
1471 struct Neighbour *n;
1472
1477
1484
1491
1500
1506
1512
1517
1523
1532
1540
1547
1556
1569
1575
1582
1593
1598 uint32_t fc_seq_gen;
1599
1605 uint32_t last_fc_seq;
1606
1619
1624};
1625
1626
1724
1725
1805
1806
1865
1866
1877{
1882
1887
1891 struct Queue *queue;
1892
1897
1901 uint64_t mid;
1902
1907};
1908
1909
1914struct Queue
1915{
1920
1925
1930
1935
1940
1945
1950
1955
1960
1965
1969 const char *address;
1970
1974 unsigned int unlimited_length;
1975
1981
1990
1995
2001
2006 uint64_t mid_gen;
2007
2011 uint32_t qid;
2012
2016 uint32_t mtu;
2017
2022
2027
2031 unsigned int queue_length;
2032
2036 uint64_t q_capacity;
2037
2041 uint32_t priority;
2042
2047
2052
2057 int idle;
2058
2063};
2064
2065
2148
2149
2176
2177
2181struct PeerRequest
2182{
2187
2192
2197
2204
2209};
2210
2211
2237
2238
2265struct PendingMessage
2266{
2271
2276
2281
2286
2292
2298
2303
2308
2314
2320
2325
2335
2340
2345
2350
2355
2360
2365
2371
2377
2382
2388
2393
2397 uint16_t bytes_msg;
2398
2402 uint16_t frag_off;
2403
2408
2413
2417 uint16_t frag_count;
2418
2423
2424 /* Followed by @e bytes_msg to transmit */
2425};
2426
2427
2444
2445
2486
2487
2554
2555
2560{
2565
2570
2575
2580
2585
2586 union
2587 {
2591 struct
2592 {
2598
2604
2608 struct
2609 {
2616
2622
2623
2627 struct
2628 {
2634
2639
2644
2650
2656
2663
2668
2673
2678
2680
2684 struct
2685 {
2693};
2694
2695
2701{
2707
2715
2721
2728 struct GNUNET_TIME_Absolute first_challenge_use;
2729
2736 struct GNUNET_TIME_Absolute last_challenge_use;
2737
2745 struct GNUNET_TIME_Absolute next_challenge;
2746
2755 struct GNUNET_TIME_Relative challenge_backoff;
2756
2761 struct GNUNET_TIME_Relative validation_rtt;
2762
2770 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2771
2775 struct GNUNET_HashCode hc;
2776
2780 struct GNUNET_SCHEDULER_Task *revalidation_task;
2781
2785 char *address;
2786
2792 struct GNUNET_CONTAINER_HeapNode *hn;
2793
2799
2805 uint32_t last_window_consum_limit;
2806
2811 int awaiting_queue;
2812};
2813
2814
2872
2877
2881static unsigned int ring_buffer_head;
2882
2886static unsigned int is_ring_buffer_full;
2887
2892
2896static unsigned int ring_buffer_dv_head;
2897
2901static unsigned int is_ring_buffer_dv_full;
2902
2907
2912
2917
2922
2927
2932
2938
2944
2950
2956
2962
2968
2974
2980
2985
2989static struct LearnLaunchEntry *lle_head = NULL;
2990
2994static struct LearnLaunchEntry *lle_tail = NULL;
2995
3002
3007
3012
3017
3021struct PilsRequest
3022{
3026 struct PilsRequest *prev;
3027
3031 struct PilsRequest *next;
3032
3036 struct GNUNET_PILS_Operation *op;
3037};
3038
3043
3048
3053
3058
3063
3070
3075
3079static unsigned int ir_total;
3080
3084static unsigned long long logging_uuid_gen;
3085
3090
3100
3105static int in_shutdown;
3106
3111
3113
3115
3126static unsigned int
3128{
3129 struct GNUNET_TIME_Absolute now;
3130
3131 now = GNUNET_TIME_absolute_get ();
3132 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3133}
3134
3135
3141static void
3143{
3145 GNUNET_assert (ir_total > 0);
3146 ir_total--;
3147 if (NULL != ir->nc)
3149 ir->nc = NULL;
3150 GNUNET_free (ir);
3151}
3152
3153
3159static void
3161{
3162 struct Queue *q = pa->queue;
3163 struct PendingMessage *pm = pa->pm;
3164 struct DistanceVectorHop *dvh = pa->dvh;
3165
3167 "free_pending_acknowledgement\n");
3168 if (NULL != q)
3169 {
3170 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3171 pa->queue = NULL;
3172 }
3173 if (NULL != pm)
3174 {
3176 "remove pa from message\n");
3178 "remove pa from message %" PRIu64 "\n",
3179 pm->logging_uuid);
3181 "remove pa from message %u\n",
3182 pm->pmt);
3184 "remove pa from message %s\n",
3186 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3187 pa->pm = NULL;
3188 }
3189 if (NULL != dvh)
3190 {
3191 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3192 pa->queue = NULL;
3193 }
3196 &pa->ack_uuid.value,
3197 pa));
3198 GNUNET_free (pa);
3199}
3200
3201
3210static void
3212{
3213 struct PendingMessage *frag;
3214
3215 while (NULL != (frag = root->head_frag))
3216 {
3217 struct PendingAcknowledgement *pa;
3218
3219 free_fragment_tree (frag);
3220 while (NULL != (pa = frag->pa_head))
3221 {
3222 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3223 pa->pm = NULL;
3224 }
3225 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3226 if (NULL != frag->qe)
3227 {
3228 GNUNET_assert (frag == frag->qe->pm);
3229 frag->qe->pm = NULL;
3230 }
3232 "Free frag %p\n",
3233 frag);
3234 GNUNET_free (frag);
3235 }
3236}
3237
3238
3246static void
3248{
3249 struct TransportClient *tc = pm->client;
3250 struct VirtualLink *vl = pm->vl;
3251 struct PendingAcknowledgement *pa;
3252
3254 "Freeing pm %p\n",
3255 pm);
3256 if (NULL != tc)
3257 {
3259 tc->details.core.pending_msg_head,
3260 tc->details.core.pending_msg_tail,
3261 pm);
3262 }
3263 if ((NULL != vl) && (NULL == pm->frag_parent))
3264 {
3266 "Removing pm %" PRIu64 "\n",
3267 pm->logging_uuid);
3269 vl->pending_msg_head,
3270 vl->pending_msg_tail,
3271 pm);
3272 }
3273 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3274 {
3275 struct PendingMessage *root = pm->frag_parent;
3276
3277 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3278 root = root->frag_parent;
3279
3280 root->frag_count--;
3281 }
3282 while (NULL != (pa = pm->pa_head))
3283 {
3284 if (NULL == pa)
3286 "free pending pa null\n");
3287 if (NULL == pm->pa_tail)
3289 "free pending pa_tail null\n");
3290 if (NULL == pa->prev_pa)
3292 "free pending pa prev null\n");
3293 if (NULL == pa->next_pa)
3295 "free pending pa next null\n");
3296 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3297 pa->pm = NULL;
3298 }
3299
3301 if (NULL != pm->qe)
3302 {
3303 GNUNET_assert (pm == pm->qe->pm);
3304 pm->qe->pm = NULL;
3305 }
3306 if (NULL != pm->bpm)
3307 {
3308 free_fragment_tree (pm->bpm);
3309 if (NULL != pm->bpm->qe)
3310 {
3311 struct QueueEntry *qe = pm->bpm->qe;
3312
3313 qe->pm = NULL;
3314 }
3315 GNUNET_free (pm->bpm);
3316 }
3317
3318 GNUNET_free (pm);
3320 "Freeing pm done\n");
3321}
3322
3323
3329static void
3341
3342
3348static void
3350{
3351 struct VirtualLink *vl = cls;
3352 struct ReassemblyContext *rc;
3353
3354 vl->reassembly_timeout_task = NULL;
3355 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3356 {
3358 .rel_value_us)
3359 {
3361 continue;
3362 }
3367 vl);
3368 return;
3369 }
3370}
3371
3372
3381static int
3382free_reassembly_cb (void *cls, uint32_t key, void *value)
3383{
3384 struct ReassemblyContext *rc = value;
3385
3386 (void) cls;
3387 (void) key;
3389 return GNUNET_OK;
3390}
3391
3392
3398static void
3400{
3401 struct PendingMessage *pm;
3402 struct CoreSentContext *csc;
3403
3405 "free virtual link %p\n",
3406 vl);
3407
3408 if (NULL != vl->reassembly_map)
3409 {
3412 NULL);
3414 vl->reassembly_map = NULL;
3416 vl->reassembly_heap = NULL;
3417 }
3418 if (NULL != vl->reassembly_timeout_task)
3419 {
3422 }
3423 while (NULL != (pm = vl->pending_msg_head))
3427 if (NULL != vl->visibility_task)
3428 {
3430 vl->visibility_task = NULL;
3431 }
3432 if (NULL != vl->fc_retransmit_task)
3433 {
3435 vl->fc_retransmit_task = NULL;
3436 }
3437 while (NULL != (csc = vl->csc_head))
3438 {
3440 GNUNET_assert (vl == csc->vl);
3441 csc->vl = NULL;
3442 }
3443 GNUNET_break (NULL == vl->n);
3444 GNUNET_break (NULL == vl->dv);
3445 GNUNET_free (vl);
3446}
3447
3448
3454static void
3456{
3457 if (NULL != vs->revalidation_task)
3458 {
3459 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3460 vs->revalidation_task = NULL;
3461 }
3462 /*memcpy (&hkey,
3463 &hc,
3464 sizeof (hkey));*/
3466 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3467 GNUNET_h2s (&vs->hc),
3468 vs->address,
3471 &vs->hc));
3474 GNUNET_YES ==
3477 vs->hn = NULL;
3478 if (NULL != vs->sc)
3479 {
3481 "store cancel\n");
3483 vs->sc = NULL;
3484 }
3485 GNUNET_free (vs->address);
3486 GNUNET_free (vs);
3487}
3488
3489
3496static struct Neighbour *
3501
3502
3509static struct VirtualLink *
3514
3515
3548
3549
3558static void
3560{
3561 struct Neighbour *n = dvh->next_hop;
3562 struct DistanceVector *dv = dvh->dv;
3563 struct PendingAcknowledgement *pa;
3564
3565 while (NULL != (pa = dvh->pa_head))
3566 {
3568 pa->dvh = NULL;
3569 }
3570 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3572 GNUNET_free (dvh);
3573}
3574
3575
3582static void
3583check_link_down (void *cls);
3584
3585
3591static void
3593{
3595 "Informing CORE clients about disconnect from %s\n",
3596 GNUNET_i2s (pid));
3597 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3598 {
3599 struct GNUNET_MQ_Envelope *env;
3600 struct DisconnectInfoMessage *dim;
3601
3602 if (CT_CORE != tc->type)
3603 continue;
3605 dim->peer = *pid;
3606 GNUNET_MQ_send (tc->mq, env);
3607 }
3608}
3609
3610
3617static void
3619{
3620 struct DistanceVectorHop *dvh;
3621 struct VirtualLink *vl;
3622
3623 while (NULL != (dvh = dv->dv_head))
3625
3627 GNUNET_YES ==
3629 if (NULL != (vl = dv->vl))
3630 {
3631 GNUNET_assert (dv == vl->dv);
3632 vl->dv = NULL;
3633 if (NULL == vl->n)
3634 {
3636 free_virtual_link (vl);
3637 }
3638 else
3639 {
3642 }
3643 dv->vl = NULL;
3644 }
3645
3646 if (NULL != dv->timeout_task)
3647 {
3649 dv->timeout_task = NULL;
3650 }
3651 GNUNET_free (dv->km);
3652 GNUNET_free (dv);
3653}
3654
3655
3669static void
3671 const struct GNUNET_PeerIdentity *peer,
3672 const char *address,
3674 const struct MonitorEvent *me)
3675{
3676 struct GNUNET_MQ_Envelope *env;
3678 size_t addr_len = strlen (address) + 1;
3679
3681 addr_len,
3683 md->nt = htonl ((uint32_t) nt);
3684 md->peer = *peer;
3685 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3686 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3687 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3688 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3689 md->cs = htonl ((uint32_t) me->cs);
3690 md->num_msg_pending = htonl (me->num_msg_pending);
3691 md->num_bytes_pending = htonl (me->num_bytes_pending);
3692 memcpy (&md[1], address, addr_len);
3693 GNUNET_MQ_send (tc->mq, env);
3694}
3695
3696
3706static void
3708 const char *address,
3710 const struct MonitorEvent *me)
3711{
3712 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3713 {
3714 if (CT_MONITOR != tc->type)
3715 continue;
3716 if (tc->details.monitor.one_shot)
3717 continue;
3718 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3719 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3720 continue;
3722 }
3723}
3724
3725
3735static void *
3737 struct GNUNET_SERVICE_Client *client,
3738 struct GNUNET_MQ_Handle *mq)
3739{
3740 struct TransportClient *tc;
3741
3742 (void) cls;
3743 tc = GNUNET_new (struct TransportClient);
3744 tc->client = client;
3745 tc->mq = mq;
3748 "Client %p of type %u connected\n",
3749 tc,
3750 tc->type);
3751 return tc;
3752}
3753
3754
3755static enum GNUNET_GenericReturnValue
3757 const struct GNUNET_PeerIdentity *pid,
3758 void *value)
3759{
3760 struct TransportGlobalNattedAddress *tgna = value;
3761 (void) cls;
3762
3763 GNUNET_free (tgna);
3764
3765 return GNUNET_OK;
3766}
3767
3768
3775static void
3776free_neighbour (struct Neighbour *neighbour,
3777 enum GNUNET_GenericReturnValue drop_link)
3778{
3779 struct DistanceVectorHop *dvh;
3780 struct VirtualLink *vl;
3781
3782 GNUNET_assert (NULL == neighbour->queue_head);
3785 &neighbour->pid,
3786 neighbour));
3788 "Freeing neighbour\n");
3791 NULL);
3793 while (NULL != (dvh = neighbour->dv_head))
3794 {
3795 struct DistanceVector *dv = dvh->dv;
3796
3798 if (NULL == dv->dv_head)
3799 free_dv_route (dv);
3800 }
3801 if (NULL != neighbour->get)
3802 {
3804 neighbour->get = NULL;
3805 }
3806 if (NULL != neighbour->sc)
3807 {
3809 "store cancel\n");
3810 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3811 neighbour->sc = NULL;
3812 }
3813 if (NULL != (vl = neighbour->vl))
3814 {
3815 GNUNET_assert (neighbour == vl->n);
3816 vl->n = NULL;
3817 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3818 {
3821 }
3822 else
3823 {
3826 }
3827 neighbour->vl = NULL;
3828 }
3829 GNUNET_free (neighbour);
3830}
3831
3832
3839static void
3841 const struct GNUNET_PeerIdentity *pid)
3842{
3843 struct GNUNET_MQ_Envelope *env;
3844 struct ConnectInfoMessage *cim;
3845
3846 GNUNET_assert (CT_CORE == tc->type);
3848 cim->id = *pid;
3849 GNUNET_MQ_send (tc->mq, env);
3850}
3851
3852
3858static void
3860{
3862 "Informing CORE clients about connection to %s\n",
3863 GNUNET_i2s (pid));
3864 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3865 {
3866 if (CT_CORE != tc->type)
3867 continue;
3869 }
3870}
3871
3872
3880static void
3881transmit_on_queue (void *cls);
3882
3883
3887static unsigned int
3889{
3890 for (struct Queue *s = queue_head; NULL != s;
3891 s = s->next_client)
3892 {
3893 if (s->tc->details.communicator.address_prefix !=
3894 queue->tc->details.communicator.address_prefix)
3895 {
3897 "queue address %s qid %u compare with queue: address %s qid %u\n",
3898 queue->address,
3899 queue->qid,
3900 s->address,
3901 s->qid);
3902 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3903 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3904 return GNUNET_YES;
3906 "Lower prio\n");
3907 }
3908 }
3909 return GNUNET_NO;
3910}
3911
3912
3920static void
3922 struct Queue *queue,
3924{
3926
3927 if (queue->validated_until.abs_value_us < now.abs_value_us)
3928 return;
3930 queue->tc->details.communicator.
3931 queue_head))
3932 return;
3933
3934 if (queue->tc->details.communicator.total_queue_length >=
3936 {
3938 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3939 queue->address,
3940 queue->qid);
3942 GST_stats,
3943 "# Transmission throttled due to communicator queue limit",
3944 1,
3945 GNUNET_NO);
3946 queue->idle = GNUNET_NO;
3947 return;
3948 }
3949 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3950 {
3952 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3953 queue->address,
3954 queue->qid);
3956 "# Transmission throttled due to queue queue limit",
3957 1,
3958 GNUNET_NO);
3959 queue->idle = GNUNET_NO;
3960 return;
3961 }
3962 if (0 == queue->q_capacity)
3963 {
3965 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3966 PRIu64 ".\n",
3967 queue->address,
3968 queue->qid,
3969 queue->q_capacity);
3971 "# Transmission throttled due to message queue capacity",
3972 1,
3973 GNUNET_NO);
3974 queue->idle = GNUNET_NO;
3975 return;
3976 }
3977 /* queue might indeed be ready, schedule it */
3978 if (NULL != queue->transmit_task)
3979 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3980 queue->transmit_task =
3982 queue);
3984 "Considering transmission on queue `%s' QID %llu to %s\n",
3985 queue->address,
3986 (unsigned long long) queue->qid,
3987 GNUNET_i2s (&queue->neighbour->pid));
3988}
3989
3990
3997static void
3999{
4000 struct VirtualLink *vl = cls;
4001 struct DistanceVector *dv = vl->dv;
4002 struct Neighbour *n = vl->n;
4003 struct GNUNET_TIME_Absolute dvh_timeout;
4004 struct GNUNET_TIME_Absolute q_timeout;
4005
4007 "Checking if link is down\n");
4008 vl->visibility_task = NULL;
4009 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4010 if (NULL != dv)
4011 {
4012 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4013 pos = pos->next_dv)
4014 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4015 pos->path_valid_until);
4016 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4017 {
4018 vl->dv->vl = NULL;
4019 vl->dv = NULL;
4020 }
4021 }
4022 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4023 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4024 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4026 {
4027 vl->n->vl = NULL;
4028 vl->n = NULL;
4029 }
4030 if ((NULL == vl->n) && (NULL == vl->dv))
4031 {
4033 free_virtual_link (vl);
4034 return;
4035 }
4036 vl->visibility_task =
4037 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4039 vl);
4040}
4041
4042
4048static void
4050{
4051 struct Neighbour *neighbour = queue->neighbour;
4052 struct TransportClient *tc = queue->tc;
4053 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4055 struct QueueEntry *qe;
4056 int maxxed;
4057 struct PendingAcknowledgement *pa;
4058 struct VirtualLink *vl;
4059
4061 "Cleaning up queue %u\n", queue->qid);
4062 if (NULL != queue->mo)
4063 {
4065 queue->mo = NULL;
4066 }
4067 if (NULL != queue->transmit_task)
4068 {
4069 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4070 queue->transmit_task = NULL;
4071 }
4072 while (NULL != (pa = queue->pa_head))
4073 {
4074 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4075 pa->queue = NULL;
4076 }
4077
4079 neighbour->queue_head,
4080 neighbour->queue_tail,
4081 queue);
4083 tc->details.communicator.queue_head,
4084 tc->details.communicator.queue_tail,
4085 queue);
4087 tc->details.communicator.total_queue_length);
4089 "Cleaning up queue with length %u\n",
4090 queue->queue_length);
4091 while (NULL != (qe = queue->queue_head))
4092 {
4093 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4094 queue->queue_length--;
4095 tc->details.communicator.total_queue_length--;
4096 if (NULL != qe->pm)
4097 {
4098 GNUNET_assert (qe == qe->pm->qe);
4099 qe->pm->qe = NULL;
4100 }
4101 GNUNET_free (qe);
4102 }
4103 GNUNET_assert (0 == queue->queue_length);
4104 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4105 tc->details.communicator.total_queue_length))
4106 {
4107 /* Communicator dropped below threshold, resume all _other_ queues */
4109 GST_stats,
4110 "# Transmission throttled due to communicator queue limit",
4111 -1,
4112 GNUNET_NO);
4113 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4114 s = s->next_client)
4116 s,
4118 }
4119 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4121
4122 vl = lookup_virtual_link (&neighbour->pid);
4123 if ((NULL != vl) && (neighbour == vl->n))
4124 {
4126 check_link_down (vl);
4127 }
4128 if (NULL == neighbour->queue_head)
4129 {
4130 free_neighbour (neighbour, GNUNET_NO);
4131 }
4132}
4133
4134
4140static void
4142{
4143 struct TransportClient *tc = ale->tc;
4144
4145 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4146 tc->details.communicator.addr_tail,
4147 ale);
4148 if (NULL != ale->sc)
4149 {
4151 "store cancel\n");
4153 ale->sc = NULL;
4154 }
4155 if (NULL != ale->st)
4156 {
4158 ale->st = NULL;
4159 }
4160 if (NULL != ale->signed_address)
4162 GNUNET_free (ale);
4163}
4164
4165
4174static int
4176 const struct GNUNET_PeerIdentity *pid,
4177 void *value)
4178{
4179 struct TransportClient *tc = cls;
4180 struct PeerRequest *pr = value;
4181
4182 if (NULL != pr->nc)
4184 pr->nc = NULL;
4186 GNUNET_YES ==
4187 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4188 pid,
4189 pr));
4190 GNUNET_free (pr);
4191
4192 return GNUNET_OK;
4193}
4194
4195
4196static void
4197do_shutdown (void *cls);
4198
4207static void
4209 struct GNUNET_SERVICE_Client *client,
4210 void *app_ctx)
4211{
4212 struct TransportClient *tc = app_ctx;
4213
4214 (void) cls;
4215 (void) client;
4217 switch (tc->type)
4218 {
4219 case CT_NONE:
4221 "Unknown Client %p disconnected, cleaning up.\n",
4222 tc);
4223 break;
4224
4225 case CT_CORE: {
4226 struct PendingMessage *pm;
4228 "CORE Client %p disconnected, cleaning up.\n",
4229 tc);
4230
4231
4232 while (NULL != (pm = tc->details.core.pending_msg_head))
4233 {
4235 tc->details.core.pending_msg_head,
4236 tc->details.core.pending_msg_tail,
4237 pm);
4238 pm->client = NULL;
4239 }
4240 }
4241 break;
4242
4243 case CT_MONITOR:
4245 "MONITOR Client %p disconnected, cleaning up.\n",
4246 tc);
4247
4248 break;
4249
4250 case CT_COMMUNICATOR: {
4251 struct Queue *q;
4252 struct AddressListEntry *ale;
4253
4255 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4256 tc);
4257
4258 if (NULL != tc->details.communicator.free_queue_entry_task)
4260 tc->details.communicator.free_queue_entry_task);
4261 while (NULL != (q = tc->details.communicator.queue_head))
4262 free_queue (q);
4263 while (NULL != (ale = tc->details.communicator.addr_head))
4265 GNUNET_free (tc->details.communicator.address_prefix);
4266 }
4267 break;
4268
4269 case CT_APPLICATION:
4271 "APPLICATION Client %p disconnected, cleaning up.\n",
4272 tc);
4273
4274 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4276 tc);
4277 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4278 break;
4279 }
4280 GNUNET_free (tc);
4281 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4282 {
4284 "Our last client disconnected\n");
4285 do_shutdown (cls);
4286 }
4287}
4288
4289
4299static int
4301 const struct GNUNET_PeerIdentity *pid,
4302 void *value)
4303{
4304 struct TransportClient *tc = cls;
4305 struct VirtualLink *vl = value;
4306
4307 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4308 return GNUNET_OK;
4309
4311 "Telling new CORE client about existing connection to %s\n",
4312 GNUNET_i2s (pid));
4314 return GNUNET_OK;
4315}
4316
4317
4323static void
4325 unsigned
4326 int free_cmc);
4327
4328static enum GNUNET_GenericReturnValue
4330 const struct GNUNET_PeerIdentity *pid,
4331 void *value)
4332{
4333 struct VirtualLink *vl = value;
4334 struct CommunicatorMessageContext *cmc;
4335
4336 /* resume communicators */
4337 while (NULL != (cmc = vl->cmc_tail))
4338 {
4340 if (GNUNET_NO == cmc->continue_send)
4342 }
4343 return GNUNET_OK;
4344}
4345
4346
4355static void
4356handle_client_start (void *cls, const struct StartMessage *start)
4357{
4358 struct TransportClient *tc = cls;
4359 // uint32_t options;
4360 //
4361 // FIXME ignore the check of the peer ids for now.
4362 // (also deprecate the old way of obtaining our own peer ID)
4363 // options = ntohl (start->options);
4364 // if ((0 != (1 & options)) &&
4365 // (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4366 // {
4367 // /* client thinks this is a different peer, reject */
4368 // GNUNET_break (0);
4369 // GNUNET_SERVICE_client_drop (tc->client);
4370 // return;
4371 // }
4372 if (CT_NONE != tc->type)
4373 {
4374 GNUNET_break (0);
4376 return;
4377 }
4378 tc->type = CT_CORE;
4380 "New CORE client with PID %s registered\n",
4381 GNUNET_i2s (&start->self));
4384 tc);
4387 NULL);
4389}
4390
4391
4398static int
4399check_client_send (void *cls, const struct OutboundMessage *obm)
4400{
4401 struct TransportClient *tc = cls;
4402 uint16_t size;
4403 const struct GNUNET_MessageHeader *obmm;
4404
4405 if (CT_CORE != tc->type)
4406 {
4407 GNUNET_break (0);
4408 return GNUNET_SYSERR;
4409 }
4410 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4411 if (size < sizeof(struct GNUNET_MessageHeader))
4412 {
4413 GNUNET_break (0);
4414 return GNUNET_SYSERR;
4415 }
4416 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4417 if (size != ntohs (obmm->size))
4418 {
4419 GNUNET_break (0);
4420 return GNUNET_SYSERR;
4421 }
4422 return GNUNET_OK;
4423}
4424
4425
4433static void
4435{
4436 struct TransportClient *tc = pm->client;
4437 struct VirtualLink *vl = pm->vl;
4438
4440 "client send response\n");
4441 if (NULL != tc)
4442 {
4443 struct GNUNET_MQ_Envelope *env;
4444 struct SendOkMessage *so_msg;
4445
4447 so_msg->peer = vl->target;
4449 "Confirming transmission of <%" PRIu64 "> to %s\n",
4450 pm->logging_uuid,
4451 GNUNET_i2s (&vl->target));
4452 GNUNET_MQ_send (tc->mq, env);
4453 }
4455}
4456
4457
4467static unsigned int
4470 struct DistanceVectorHop **hops_array,
4471 unsigned int hops_array_length)
4472{
4473 uint64_t choices[hops_array_length];
4474 uint64_t num_dv;
4475 unsigned int dv_count;
4476
4477 /* Pick random vectors, but weighted by distance, giving more weight
4478 to shorter vectors */
4479 num_dv = 0;
4480 dv_count = 0;
4481 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4482 pos = pos->next_dv)
4483 {
4484 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4485 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4486 .rel_value_us == 0))
4487 continue; /* pos unconfirmed and confirmed required */
4488 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4489 dv_count++;
4490 }
4491 if (0 == dv_count)
4492 return 0;
4493 if (dv_count <= hops_array_length)
4494 {
4495 dv_count = 0;
4496 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4497 pos = pos->next_dv)
4498 hops_array[dv_count++] = pos;
4499 return dv_count;
4500 }
4501 for (unsigned int i = 0; i < hops_array_length; i++)
4502 {
4503 int ok = GNUNET_NO;
4504 while (GNUNET_NO == ok)
4505 {
4506 choices[i] =
4508 ok = GNUNET_YES;
4509 for (unsigned int j = 0; j < i; j++)
4510 if (choices[i] == choices[j])
4511 {
4512 ok = GNUNET_NO;
4513 break;
4514 }
4515 }
4516 }
4517 dv_count = 0;
4518 num_dv = 0;
4519 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4520 pos = pos->next_dv)
4521 {
4522 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4523
4524 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4525 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4526 .rel_value_us == 0))
4527 continue; /* pos unconfirmed and confirmed required */
4528 for (unsigned int i = 0; i < hops_array_length; i++)
4529 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4530 hops_array[dv_count++] = pos;
4531 num_dv += delta;
4532 }
4533 return dv_count;
4534}
4535
4536
4543static int
4545 void *cls,
4547{
4548 struct TransportClient *tc = cls;
4549 uint16_t size;
4550
4551 if (CT_NONE != tc->type)
4552 {
4553 GNUNET_break (0);
4554 return GNUNET_SYSERR;
4555 }
4556 tc->type = CT_COMMUNICATOR;
4557 size = ntohs (cam->header.size) - sizeof(*cam);
4558 if (0 == size)
4559 return GNUNET_OK; /* receive-only communicator */
4561 return GNUNET_OK;
4562}
4563
4564
4570static void
4572 unsigned
4573 int free_cmc)
4574{
4575 if (0 != ntohl (cmc->im.fc_on))
4576 {
4577 /* send ACK when done to communicator for flow control! */
4578 struct GNUNET_MQ_Envelope *env;
4580
4582 "Acknowledge message with flow control id %" PRIu64 "\n",
4583 cmc->im.fc_id);
4585 ack->reserved = htonl (0);
4586 ack->fc_id = cmc->im.fc_id;
4587 ack->sender = cmc->im.neighbour_sender;
4588 GNUNET_MQ_send (cmc->tc->mq, env);
4589 }
4590
4592
4593 if (GNUNET_YES == free_cmc)
4594 {
4595 GNUNET_free (cmc);
4596 }
4597}
4598
4599
4600static void
4605
4606
4616static void
4617handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4618{
4619 struct TransportClient *tc = cls;
4620 struct VirtualLink *vl;
4621 uint32_t delta;
4622 struct CommunicatorMessageContext *cmc;
4623
4624 if (CT_CORE != tc->type)
4625 {
4626 GNUNET_break (0);
4628 return;
4629 }
4630 vl = lookup_virtual_link (&rom->peer);
4631 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4632 {
4634 "# RECV_OK dropped: virtual link unknown",
4635 1,
4636 GNUNET_NO);
4638 return;
4639 }
4640 delta = ntohl (rom->increase_window_delta);
4641 vl->core_recv_window += delta;
4643 "CORE ack receiving message, increased CORE recv window to %d\n",
4644 vl->core_recv_window);
4646 if (vl->core_recv_window <= 0)
4647 return;
4648 /* resume communicators */
4649 while (NULL != (cmc = vl->cmc_tail))
4650 {
4652 if (GNUNET_NO == cmc->continue_send)
4654 }
4655}
4656
4657
4664static void
4666 void *cls,
4668{
4669 struct TransportClient *tc = cls;
4670 uint16_t size;
4671
4672 size = ntohs (cam->header.size) - sizeof(*cam);
4673 if (0 == size)
4674 {
4676 "Receive-only communicator connected\n");
4677 return; /* receive-only communicator */
4678 }
4679 tc->details.communicator.address_prefix =
4680 GNUNET_strdup ((const char *) &cam[1]);
4681 tc->details.communicator.cc = ntohl (cam->cc);
4682 tc->details.communicator.can_burst = ntohl (cam->can_burst);
4684 "Communicator for peer %s with prefix '%s' connected %s\n",
4686 tc->details.communicator.address_prefix,
4687 tc->details.communicator.can_burst ? "can burst" :
4688 "can not burst");
4690}
4691
4692
4700static int
4702 void *cls,
4704{
4705 const struct GNUNET_MessageHeader *inbox;
4706 const char *is;
4707 uint16_t msize;
4708 uint16_t isize;
4709
4710 (void) cls;
4711 msize = ntohs (cb->header.size) - sizeof(*cb);
4712 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4713 isize = ntohs (inbox->size);
4714 if (isize >= msize)
4715 {
4716 GNUNET_break (0);
4717 return GNUNET_SYSERR;
4718 }
4719 is = (const char *) inbox;
4720 is += isize;
4721 msize -= isize;
4722 GNUNET_assert (0 < msize);
4723 if ('\0' != is[msize - 1])
4724 {
4725 GNUNET_break (0);
4726 return GNUNET_SYSERR;
4727 }
4728 return GNUNET_OK;
4729}
4730
4731
4733{
4736};
4737
4738
4739static void
4740sign_dv_cb (void *cls,
4741 const struct GNUNET_PeerIdentity *pid,
4742 const struct GNUNET_CRYPTO_EddsaSignature *sig)
4743{
4744 struct SignDvCls *sign_dv_cls = cls;
4745 struct DistanceVector *dv = sign_dv_cls->dv;
4746 struct PilsRequest *pr = sign_dv_cls->req;
4747
4748 pr->op = NULL;
4751 pr);
4752 GNUNET_free (pr);
4753
4754 dv->sender_sig = *sig;
4755}
4756
4757
4763static void
4765{
4766 struct EphemeralConfirmationPS ec;
4767 struct SignDvCls *sign_dv_cls;
4768
4773 ec.target = dv->target;
4776 ec.purpose.size = htonl (sizeof(ec));
4777 sign_dv_cls = GNUNET_new (struct SignDvCls);
4778 sign_dv_cls->req = GNUNET_new (struct PilsRequest);
4779 sign_dv_cls->dv = dv;
4782 sign_dv_cls->req);
4784 &ec.purpose,
4785 sign_dv_cb,
4786 sign_dv_cls);
4787}
4788
4789
4790static void
4792 struct TransportClient *tc);
4793
4794
4795static void
4797{
4798 struct TransportClient *tc = cls;
4800
4802 "freeing timedout queue entries\n");
4803
4804 tc->details.communicator.free_queue_entry_task = NULL;
4805 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4806 queue = queue->next_client)
4807 {
4808 struct QueueEntry *qep = queue->queue_head;
4809
4811 "checking QID %u for timedout queue entries\n",
4812 queue->qid);
4813 while (NULL != qep)
4814 {
4815 struct QueueEntry *pos = qep;
4817 pos->creation_timestamp, now);
4818 qep = qep->next;
4819
4821 "diff to now %s \n",
4824 {
4826 "Freeing timed out QueueEntry with MID %" PRIu64
4827 " and QID %u\n",
4828 pos->mid,
4829 queue->qid);
4830 free_queue_entry (pos, tc);
4831 }
4832 }
4833 }
4834}
4835
4836
4846static void
4848 struct PendingMessage *pm,
4849 const void *payload,
4850 size_t payload_size)
4851{
4852 struct Neighbour *n = queue->neighbour;
4854 struct GNUNET_MQ_Envelope *env;
4855 struct PendingAcknowledgement *pa;
4856
4857 GNUNET_log (
4859 "Queueing %u bytes of payload for transmission <%" PRIu64
4860 "> on queue %llu to %s\n",
4861 (unsigned int) payload_size,
4862 (NULL == pm) ? 0 : pm->logging_uuid,
4863 (unsigned long long) queue->qid,
4864 GNUNET_i2s (&queue->neighbour->pid));
4865 env = GNUNET_MQ_msg_extra (smt,
4866 payload_size,
4868 smt->qid = htonl (queue->qid);
4869 smt->mid = GNUNET_htonll (queue->mid_gen);
4870 smt->receiver = n->pid;
4871 memcpy (&smt[1], payload, payload_size);
4872 {
4873 /* Pass the env to the communicator of queue for transmission. */
4874 struct QueueEntry *qe;
4875
4876 qe = GNUNET_new (struct QueueEntry);
4877 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4878 qe->mid = queue->mid_gen;
4880 "Create QueueEntry with MID %" PRIu64
4881 " and QID %u and prefix %s\n",
4882 qe->mid,
4883 queue->qid,
4884 queue->tc->details.communicator.address_prefix);
4885 queue->mid_gen++;
4886 qe->queue = queue;
4887 if (NULL != pm)
4888 {
4889 qe->pm = pm;
4890 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4891 // GNUNET_assert (NULL == pm->qe);
4892 if (NULL != pm->qe)
4893 {
4895 "Retransmitting message <%" PRIu64
4896 "> remove pm from qe with MID: %llu \n",
4897 pm->logging_uuid,
4898 (unsigned long long) pm->qe->mid);
4899 pm->qe->pm = NULL;
4900 }
4901 pm->qe = qe;
4902 }
4903 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4904 if (0 == queue->q_capacity)
4905 {
4906 // Messages without FC or fragments can get here.
4907 if (NULL != pm)
4908 {
4910 "Message %" PRIu64
4911 " (pm type %u) was not send because queue has no capacity.\n",
4912 pm->logging_uuid,
4913 pm->pmt);
4914 pm->qe = NULL;
4915 }
4916 GNUNET_free (env);
4917 GNUNET_free (qe);
4918 return;
4919 }
4920 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4921 queue->queue_length++;
4922 queue->tc->details.communicator.total_queue_length++;
4923 if (GNUNET_NO == queue->unlimited_length)
4924 queue->q_capacity--;
4926 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4927 queue->address,
4928 queue->qid,
4929 queue->q_capacity);
4931 queue->tc->details.communicator.total_queue_length)
4932 queue->idle = GNUNET_NO;
4933 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4934 queue->idle = GNUNET_NO;
4935 if (0 == queue->q_capacity)
4936 queue->idle = GNUNET_NO;
4937
4938 if (GNUNET_NO == queue->idle)
4939 {
4940 struct TransportClient *tc = queue->tc;
4941
4942 if (NULL == tc->details.communicator.free_queue_entry_task)
4943 tc->details.communicator.free_queue_entry_task =
4945 &
4947 tc);
4948 }
4949 if (NULL != pm && NULL != (pa = pm->pa_head))
4950 {
4951 while (pm != pa->pm)
4952 pa = pa->next_pa;
4953 pa->num_send++;
4954 }
4955 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4957 "Sending message MID %" PRIu64
4958 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4959 PRIu64 "\n",
4960 GNUNET_ntohll (smt->mid),
4961 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4962 ntohs (smt->header.size),
4963 (unsigned long) payload_size,
4964 queue->tc->mq,
4965 queue->address,
4966 queue->qid,
4967 (NULL == pm) ? 0 : pm->logging_uuid);
4968 GNUNET_MQ_send (queue->tc->mq, env);
4969 }
4970}
4971
4972
4983static struct GNUNET_TIME_Relative
4985 const struct GNUNET_MessageHeader *hdr,
4987{
4988 struct GNUNET_TIME_Absolute now;
4989 unsigned int candidates;
4990 unsigned int sel1;
4991 unsigned int sel2;
4992 struct GNUNET_TIME_Relative rtt;
4993
4994 /* Pick one or two 'random' queues from n (under constraints of options) */
4995 now = GNUNET_TIME_absolute_get ();
4996 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4997 weight in the future; weight could be assigned by observed
4998 bandwidth (note: not sure if we should do this for this type
4999 of control traffic though). */
5000 candidates = 0;
5001 for (struct Queue *pos = n->queue_head; NULL != pos;
5002 pos = pos->next_neighbour)
5003 {
5004 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5005 (pos->validated_until.abs_value_us > now.abs_value_us))
5006 candidates++;
5007 }
5008 if (0 == candidates)
5009 {
5010 /* This can happen rarely if the last confirmed queue timed
5011 out just as we were beginning to process this message. */
5013 "Could not route message of type %u to %s: no valid queue\n",
5014 ntohs (hdr->type),
5015 GNUNET_i2s (&n->pid));
5017 "# route selection failed (all no valid queue)",
5018 1,
5019 GNUNET_NO);
5021 }
5022
5025 if (0 == (options & RMO_REDUNDANT))
5026 sel2 = candidates; /* picks none! */
5027 else
5029 candidates = 0;
5030 for (struct Queue *pos = n->queue_head; NULL != pos;
5031 pos = pos->next_neighbour)
5032 {
5033 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5034 (pos->validated_until.abs_value_us > now.abs_value_us))
5035 {
5036 if ((sel1 == candidates) || (sel2 == candidates))
5037 {
5039 "Routing message of type %u to %s using %s (#%u)\n",
5040 ntohs (hdr->type),
5041 GNUNET_i2s (&n->pid),
5042 pos->address,
5043 (sel1 == candidates) ? 1 : 2);
5044 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5045 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5046 }
5047 candidates++;
5048 }
5049 }
5050 return rtt;
5051}
5052
5053
5058{
5062 gcry_cipher_hd_t cipher;
5063
5067 struct
5068 {
5073
5077 char aes_key[256 / 8];
5078
5082 char aes_ctr[128 / 8];
5084};
5085
5086
5095static void
5097 const struct GNUNET_ShortHashCode *iv,
5098 struct DVKeyState *key)
5099{
5100 /* must match what we defive from decapsulated key */
5103 &key->material,
5104 sizeof(key->material),
5105 km,
5106 GNUNET_CRYPTO_kdf_arg_string ("gnunet-transport-dv-key"),
5110 "Deriving backchannel key based on KM %s and IV %s\n",
5111 GNUNET_sh2s (km),
5112 GNUNET_sh2s (iv));
5113 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5114 GCRY_CIPHER_AES256 /* low level: go for speed */
5115 ,
5116 GCRY_CIPHER_MODE_CTR,
5117 0 /* flags */));
5118 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5119 &key->material.aes_key,
5120 sizeof(key->material.aes_key)));
5121 gcry_cipher_setctr (key->cipher,
5122 &key->material.aes_ctr,
5123 sizeof(key->material.aes_ctr));
5124}
5125
5126
5136static void
5137dv_hmac (const struct DVKeyState *key,
5138 struct GNUNET_HashCode *hmac,
5139 const void *data,
5140 size_t data_size)
5141{
5142 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5143}
5144
5145
5155static void
5156dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5157{
5158 GNUNET_assert (0 ==
5159 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5160}
5161
5162
5173static enum GNUNET_GenericReturnValue
5175 void *out,
5176 const void *ciph,
5177 size_t out_size)
5178{
5179 return (0 ==
5180 gcry_cipher_decrypt (key->cipher,
5181 out, out_size,
5182 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5183}
5184
5185
5191static void
5193{
5194 gcry_cipher_close (key->cipher);
5195 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5196}
5197
5198
5209typedef void (*DVMessageHandler) (void *cls,
5210 struct Neighbour *next_hop,
5211 const struct GNUNET_MessageHeader *hdr,
5213
5228static struct GNUNET_TIME_Relative
5230 unsigned int num_dvhs,
5231 struct DistanceVectorHop **dvhs,
5232 const struct GNUNET_MessageHeader *hdr,
5233 DVMessageHandler use,
5234 void *use_cls,
5236 enum GNUNET_GenericReturnValue without_fc)
5237{
5238 struct TransportDVBoxMessage box_hdr;
5239 struct TransportDVBoxPayloadP payload_hdr;
5240 uint16_t enc_body_size = ntohs (hdr->size);
5241 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5242 struct DVKeyState *key;
5243 struct GNUNET_TIME_Relative rtt;
5244 struct GNUNET_ShortHashCode km;
5245
5246 key = GNUNET_new (struct DVKeyState);
5247 /* Encrypt payload */
5249 box_hdr.total_hops = htons (0);
5250 box_hdr.without_fc = htons (without_fc);
5251 // update_ephemeral (dv);
5252 if (0 ==
5253 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5254 {
5255 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5256 &dv->ephemeral_key,
5257 &km);
5258 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5259 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5260 sign_ephemeral (dv);
5261 }
5262 box_hdr.ephemeral_key = dv->ephemeral_key;
5263 payload_hdr.sender_sig = dv->sender_sig;
5264
5266 &box_hdr.iv,
5267 sizeof(box_hdr.iv));
5268 // We are creating this key, so this must work.
5269 // FIXME: Possibly also add return values here. We are processing
5270 // Input from other peers...
5271 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5272 payload_hdr.sender = *GST_my_identity;
5273 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5274 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5275 dv_encrypt (key,
5276 hdr,
5277 &enc[sizeof(struct TransportDVBoxPayloadP)],
5278 enc_body_size);
5279 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5280 dv_key_clean (key);
5282 /* For each selected path, take the pre-computed header and body
5283 and add the path in the middle of the message; then send it. */
5284 for (unsigned int i = 0; i < num_dvhs; i++)
5285 {
5286 struct DistanceVectorHop *dvh = dvhs[i];
5287 unsigned int num_hops = dvh->distance + 1;
5288 char buf[sizeof(struct TransportDVBoxMessage)
5289 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5290 + sizeof(struct TransportDVBoxPayloadP)
5291 + enc_body_size] GNUNET_ALIGN;
5292 struct GNUNET_PeerIdentity *dhops;
5293
5294 box_hdr.header.size = htons (sizeof(buf));
5295 box_hdr.orig_size = htons (sizeof(buf));
5296 box_hdr.num_hops = htons (num_hops);
5297 memcpy (buf, &box_hdr, sizeof(box_hdr));
5298 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5299 memcpy (dhops,
5300 dvh->path,
5301 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5302 dhops[dvh->distance] = dv->target;
5303 if (GNUNET_EXTRA_LOGGING > 0)
5304 {
5305 char *path;
5306
5308 for (unsigned int j = 0; j < num_hops; j++)
5309 {
5310 char *tmp;
5311
5312 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5313 GNUNET_free (path);
5314 path = tmp;
5315 }
5317 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5318 ntohs (hdr->type),
5319 GNUNET_i2s (&dv->target),
5320 i + 1,
5321 num_dvhs,
5322 path);
5323 GNUNET_free (path);
5324 }
5325 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5326 memcpy (&dhops[num_hops], enc, sizeof(enc));
5327 use (use_cls,
5328 dvh->next_hop,
5329 (const struct GNUNET_MessageHeader *) buf,
5330 options);
5331 GNUNET_free (key);
5332 }
5333 return rtt;
5334}
5335
5336
5346static void
5348 struct Neighbour *next_hop,
5349 const struct GNUNET_MessageHeader *hdr,
5351{
5352 (void) cls;
5353 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5354}
5355
5356
5368static struct GNUNET_TIME_Relative
5370// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5371 const struct GNUNET_MessageHeader *hdr,
5373{
5374 // struct VirtualLink *vl;
5375 struct Neighbour *n;
5376 struct DistanceVector *dv;
5377 struct GNUNET_TIME_Relative rtt1;
5378 struct GNUNET_TIME_Relative rtt2;
5379 const struct GNUNET_PeerIdentity *target = &vl->target;
5380
5382 "Trying to route message of type %u to %s without fc\n",
5383 ntohs (hdr->type),
5384 GNUNET_i2s (target));
5385
5386 // TODO Do this elsewhere. vl should be given as parameter to method.
5387 // vl = lookup_virtual_link (target);
5388 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5389 if (NULL == vl)
5391 n = vl->n;
5392 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5393 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5394 {
5395 /* if confirmed is required, and we do not have anything
5396 confirmed, drop respective options */
5397 if (NULL == n)
5398 n = lookup_neighbour (target);
5399 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5401 }
5402 if ((NULL == n) && (NULL == dv))
5403 {
5405 "Cannot route message of type %u to %s: no route\n",
5406 ntohs (hdr->type),
5407 GNUNET_i2s (target));
5409 "# Messages dropped in routing: no acceptable method",
5410 1,
5411 GNUNET_NO);
5413 }
5415 "Routing message of type %u to %s with options %X\n",
5416 ntohs (hdr->type),
5417 GNUNET_i2s (target),
5418 (unsigned int) options);
5419 /* If both dv and n are possible and we must choose:
5420 flip a coin for the choice between the two; for now 50/50 */
5421 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5422 {
5424 n = NULL;
5425 else
5426 dv = NULL;
5427 }
5428 if ((NULL != n) && (NULL != dv))
5429 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5430 enough for redundancy, so clear the flag. */
5433 if (NULL != n)
5434 {
5436 "Try to route message of type %u to %s without fc via neighbour\n",
5437 ntohs (hdr->type),
5438 GNUNET_i2s (target));
5439 rtt1 = route_via_neighbour (n, hdr, options);
5440 }
5441 if (NULL != dv)
5442 {
5443 struct DistanceVectorHop *hops[2];
5444 unsigned int res;
5445
5447 options,
5448 hops,
5449 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5450 if (0 == res)
5451 {
5453 "Failed to route message, could not determine DV path\n");
5454 return rtt1;
5455 }
5457 "encapsulate_for_dv 1\n");
5458 rtt2 = encapsulate_for_dv (dv,
5459 res,
5460 hops,
5461 hdr,
5463 NULL,
5465 GNUNET_YES);
5466 }
5467 return GNUNET_TIME_relative_min (rtt1, rtt2);
5468}
5469
5470
5471static void
5472consider_sending_fc (void *cls);
5473
5480static void
5482{
5483 struct VirtualLink *vl = cls;
5484 vl->fc_retransmit_task = NULL;
5485 consider_sending_fc (cls);
5486}
5487
5488
5489static char *
5490get_address_without_port (const char *address);
5491
5492
5494{
5495 size_t off;
5496 char *tgnas;
5497};
5498
5499
5500static enum GNUNET_GenericReturnValue
5502 const struct GNUNET_PeerIdentity *pid,
5503 void *value)
5504{
5505 struct AddGlobalAddressesContext *ctx = cls;
5506 struct TransportGlobalNattedAddress *tgna = value;
5507 char *addr = (char *) &tgna[1];
5508
5510 "sending address %s length %u\n",
5511 addr,
5512 ntohl (tgna->address_length));
5513 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5515 + ntohl (tgna->address_length));
5516 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5518
5519 return GNUNET_OK;
5520}
5521
5522
5523static struct GNUNET_TIME_Relative
5524calculate_rtt (struct DistanceVector *dv);
5525
5526
5533static void
5535{
5536 struct VirtualLink *vl = cls;
5537 struct GNUNET_TIME_Absolute monotime;
5538 struct TransportFlowControlMessage *fc;
5540 struct GNUNET_TIME_Relative rtt;
5541 struct GNUNET_TIME_Relative rtt_average;
5542 struct Neighbour *n = vl->n;
5543
5544 if (NULL != n && 0 < n->number_of_addresses)
5545 {
5546 size_t addresses_size =
5547 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5548 ->size_of_global_addresses;
5549 char *tgnas = GNUNET_malloc (addresses_size);
5551 ctx.off = 0;
5552 ctx.tgnas = tgnas;
5553
5555 + addresses_size);
5556 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5557 + addresses_size);
5558 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5559 fc->number_of_addresses = htonl (n->number_of_addresses);
5560 GNUNET_CONTAINER_multipeermap_iterate (n->natted_addresses,
5562 &ctx);
5565 }
5566 else
5567 {
5568 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5569 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5570 }
5571
5573 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5574 it always! */
5575 /* For example, we should probably ONLY do this if a bit more than
5576 an RTT has passed, or if the window changed "significantly" since
5577 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5578 need an estimate for the bandwidth-delay-product for the entire
5579 VL, as that determines "significantly". We have the delay, but
5580 the bandwidth statistics need to be added for the VL!*/(void) duration;
5581
5582 if (NULL != vl->dv)
5583 rtt_average = calculate_rtt (vl->dv);
5584 else
5585 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5586 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5588 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5589 (unsigned int) vl->fc_seq_gen,
5590 GNUNET_i2s (&vl->target),
5591 (unsigned long long) vl->incoming_fc_window_size,
5592 (unsigned long) rtt_average.rel_value_us,
5593 vl->sync_ready);
5595 vl->last_fc_transmission = monotime;
5596 fc->sync_ready = vl->sync_ready;
5598 fc->seq = htonl (vl->fc_seq_gen++);
5599 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5602 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5603 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5604 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5606 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5607 {
5610 "FC retransmission to %s failed, will retry in %s\n",
5611 GNUNET_i2s (&vl->target),
5614 }
5615 else
5616 {
5617 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5618 vl->last_fc_rtt = rtt;
5619 }
5620 if (NULL != vl->fc_retransmit_task)
5623 {
5625 vl->fc_retransmit_count = 0;
5626 }
5627 vl->fc_retransmit_task =
5629 vl->fc_retransmit_count++;
5630 GNUNET_free (fc);
5631}
5632
5633
5650static void
5652{
5653 struct Neighbour *n = vl->n;
5654 struct DistanceVector *dv = vl->dv;
5655 struct GNUNET_TIME_Absolute now;
5656 struct VirtualLink *vl_next_hop;
5657 int elig;
5658
5660 "check_vl_transmission to target %s\n",
5661 GNUNET_i2s (&vl->target));
5662 /* Check that we have an eligible pending message!
5663 (cheaper than having #transmit_on_queue() find out!) */
5664 elig = GNUNET_NO;
5665 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5666 pm = pm->next_vl)
5667 {
5669 "check_vl_transmission loop\n");
5670 if (NULL != pm->qe)
5671 continue; /* not eligible, is in a queue! */
5672 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5674 {
5676 "Stalled message %" PRIu64
5677 " transmission on VL %s due to flow control: %llu < %llu\n",
5678 pm->logging_uuid,
5679 GNUNET_i2s (&vl->target),
5680 (unsigned long long) vl->outbound_fc_window_size,
5681 (unsigned long long) (pm->bytes_msg
5684 return; /* We have a message, but flow control says "nope" */
5685 }
5687 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5688 GNUNET_i2s (&vl->target));
5689 /* Notify queues at direct neighbours that we are interested */
5690 now = GNUNET_TIME_absolute_get ();
5691 if (NULL != n)
5692 {
5693 for (struct Queue *queue = n->queue_head; NULL != queue;
5694 queue = queue->next_neighbour)
5695 {
5696 if ((GNUNET_YES == queue->idle) &&
5697 (queue->validated_until.abs_value_us > now.abs_value_us))
5698 {
5700 "Direct neighbour %s not stalled\n",
5701 GNUNET_i2s (&n->pid));
5703 queue,
5705 elig = GNUNET_YES;
5706 }
5707 else
5709 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5710 queue->qid,
5711 queue->idle);
5712 }
5713 }
5714 /* Notify queues via DV that we are interested */
5715 if (NULL != dv)
5716 {
5717 /* Do DV with lower scheduler priority, which effectively means that
5718 IF a neighbour exists and is available, we prefer it. */
5719 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5720 pos = pos->next_dv)
5721 {
5722 struct Neighbour *nh_iter = pos->next_hop;
5723
5724
5725 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5726 continue; /* skip this one: path not validated */
5727 else
5728 {
5729 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5730 GNUNET_assert (NULL != vl_next_hop);
5731 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5732 vl_next_hop->outbound_fc_window_size)
5733 {
5735 "Stalled message %" PRIu64
5736 " transmission on next hop %s due to flow control: %llu < %llu\n",
5737 pm->logging_uuid,
5738 GNUNET_i2s (&vl_next_hop->target),
5739 (unsigned long
5740 long) vl_next_hop->outbound_fc_window_size,
5741 (unsigned long long) (pm->bytes_msg
5742 + vl_next_hop->
5743 outbound_fc_window_size_used));
5744 consider_sending_fc (vl_next_hop);
5745 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5746 }
5747 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5748 queue = queue->next_neighbour)
5749 if ((GNUNET_YES == queue->idle) &&
5750 (queue->validated_until.abs_value_us > now.abs_value_us))
5751 {
5753 "Next hop neighbour %s not stalled\n",
5754 GNUNET_i2s (&nh_iter->pid));
5756 queue,
5758 elig = GNUNET_YES;
5759 }
5760 else
5762 "DV Queue QID: %u (%u) busy or invalid\n",
5763 queue->qid,
5764 queue->idle);
5765 }
5766 }
5767 }
5768 if (GNUNET_YES == elig)
5770 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5771 pm->logging_uuid,
5772 pm->bytes_msg,
5773 GNUNET_i2s (&vl->target),
5774 (unsigned long long) vl->outbound_fc_window_size,
5775 (unsigned long long) (pm->bytes_msg
5777 break;
5778 }
5779}
5780
5781
5788static void
5789handle_client_send (void *cls, const struct OutboundMessage *obm)
5790{
5791 struct TransportClient *tc = cls;
5792 struct PendingMessage *pm;
5793 const struct GNUNET_MessageHeader *obmm;
5794 uint32_t bytes_msg;
5795 struct VirtualLink *vl;
5797
5798 GNUNET_assert (CT_CORE == tc->type);
5799 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5800 bytes_msg = ntohs (obmm->size);
5801 pp = ntohl (obm->priority);
5802 vl = lookup_virtual_link (&obm->peer);
5803 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5804 {
5806 "Don't have %s as a neighbour (anymore).\n",
5807 GNUNET_i2s (&obm->peer));
5808 /* Failure: don't have this peer as a neighbour (anymore).
5809 Might have gone down asynchronously, so this is NOT
5810 a protocol violation by CORE. Still count the event,
5811 as this should be rare. */
5814 "# messages dropped (neighbour unknown)",
5815 1,
5816 GNUNET_NO);
5817 return;
5818 }
5819
5820 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5822 "1 created pm %p storing vl %p\n",
5823 pm,
5824 vl);
5825 pm->logging_uuid = logging_uuid_gen++;
5826 pm->prefs = pp;
5827 pm->client = tc;
5828 pm->vl = vl;
5829 pm->bytes_msg = bytes_msg;
5830 memcpy (&pm[1], obmm, bytes_msg);
5832 "Sending message of type %u with %u bytes as <%" PRIu64
5833 "> to %s\n",
5834 ntohs (obmm->type),
5835 bytes_msg,
5836 pm->logging_uuid,
5837 GNUNET_i2s (&obm->peer));
5839 tc->details.core.pending_msg_head,
5840 tc->details.core.pending_msg_tail,
5841 pm);
5843 vl->pending_msg_head,
5844 vl->pending_msg_tail,
5845 pm);
5848}
5849
5850
5860static void
5862 void *cls,
5864{
5865 struct Neighbour *n;
5866 struct VirtualLink *vl;
5867 struct TransportClient *tc = cls;
5868 const struct GNUNET_MessageHeader *inbox =
5869 (const struct GNUNET_MessageHeader *) &cb[1];
5870 uint16_t isize = ntohs (inbox->size);
5871 const char *is = ((const char *) &cb[1]) + isize;
5872 size_t slen = strlen (is) + 1;
5873 char
5874 mbuf[slen + isize
5875 + sizeof(struct
5879
5880 /* 0-termination of 'is' was checked already in
5881 #check_communicator_backchannel() */
5883 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5884 GNUNET_i2s (&cb->pid),
5885 is,
5886 ntohs (inbox->type),
5887 ntohs (inbox->size));
5888 /* encapsulate and encrypt message */
5889 be->header.type =
5891 be->header.size = htons (sizeof(mbuf));
5892 memcpy (&be[1], inbox, isize);
5893 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5894 + isize],
5895 is,
5896 strlen (is) + 1);
5897 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5898 vl = lookup_virtual_link (&cb->pid);
5899 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5900 {
5902 }
5903 else
5904 {
5905 /* Use route via neighbour */
5906 n = lookup_neighbour (&cb->pid);
5907 if (NULL != n)
5909 n,
5910 &be->header,
5911 RMO_NONE);
5912 }
5914}
5915
5916
5924static int
5926 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5927{
5928 struct TransportClient *tc = cls;
5929
5930 if (CT_COMMUNICATOR != tc->type)
5931 {
5932 GNUNET_break (0);
5933 return GNUNET_SYSERR;
5934 }
5936 return GNUNET_OK;
5937}
5938
5939
5945static void
5946store_pi (void *cls);
5947
5948
5953{
5954
5959
5964
5965
5970};
5971
5972
5973static void
5974shc_cont (void *cls, int success)
5975{
5976 struct PilsAddressSignContext *pc = cls;
5977
5978 GNUNET_assert (NULL == pc->req);
5979 if (GNUNET_OK != success)
5980 {
5982 "Failed to store our address `%s' with peerstore\n",
5983 pc->ale->address);
5984 if (NULL == pc->ale->st)
5985 {
5987 &store_pi,
5988 pc->ale);
5989 }
5990 }
5991 GNUNET_free (pc);
5992}
5993
5994
5998static void
6000 const struct GNUNET_PeerIdentity *pid,
6001 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6002{
6003 struct PilsAddressSignContext *pc = cls;
6004 struct GNUNET_MQ_Envelope *env;
6005 const struct GNUNET_MessageHeader *msg;
6006
6007 pc->req->op = NULL;
6010 pc->req);
6011 GNUNET_free (pc->req);
6012 pc->req = NULL;
6015 pid,
6016 sig,
6017 pc->et);
6020 "store_pi 1\n");
6022 msg,
6023 shc_cont,
6024 pc);
6025 GNUNET_free (env);
6026}
6027
6028
6035static void
6036peerstore_store_own_cb (void *cls, int success)
6037{
6038 struct PilsAddressSignContext *pc = cls;
6039
6040 pc->ale->sc = NULL;
6041 if (GNUNET_YES != success)
6043 "Failed to store our own address `%s' in peerstore!\n",
6044 pc->ale->address);
6045 else
6047 "Successfully stored our own address `%s' in peerstore!\n",
6048 pc->ale->address);
6049 /* refresh period is 1/4 of expiration time, that should be plenty
6050 without being excessive. */
6051 if (NULL == pc->ale->st)
6052 {
6053 pc->ale->st =
6055 GNUNET_TIME_relative_divide (pc->ale->expiration,
6056 4ULL),
6057 &store_pi,
6058 pc->ale);
6059 }
6060
6061 /* Now we have to update our HELLO! */
6063 pc->req = GNUNET_new (struct PilsRequest);
6066 pc->req);
6067 pc->req->op = GNUNET_PILS_sign_hello (pils,
6069 pc->et,
6071 pc);
6072}
6073
6074
6075// This function
6076static void
6078 const struct GNUNET_PeerIdentity *pid,
6079 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6080{
6081 struct PilsAddressSignContext *pc = cls;
6082 char *sig_str;
6083 void *result;
6084 size_t result_size;
6085
6086 pc->req->op = NULL;
6089 pc->req);
6090 GNUNET_free (pc->req);
6091 sig_str = NULL;
6092 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6093 result_size =
6094 1 + GNUNET_asprintf (
6095 (char **) &result,
6096 "%s;%llu;%u;%s",
6097 sig_str,
6098 (unsigned long long) pc->et.abs_value_us,
6099 (unsigned int) pc->ale->nt,
6100 pc->ale->address);
6101 GNUNET_free (sig_str);
6102
6104 "Build our HELLO URI `%s'\n",
6105 (char*) result);
6106
6107 pc->ale->signed_address = result;
6108 pc->ale->signed_address_len = result_size;
6110
6111 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6113 "transport",
6114 GST_my_identity, // FIXME
6116 result,
6117 result_size,
6118 expiration,
6121 pc);
6122}
6123
6124
6145
6146
6160void
6162 struct AddressListEntry *ale,
6163 struct GNUNET_TIME_Absolute mono_time)
6164{
6165 struct SignedAddress sa;
6166 struct PilsAddressSignContext *pc;
6167
6169 sa.purpose.size = htonl (sizeof(sa));
6170 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6171 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6173 pc->ale = ale;
6174 pc->et = mono_time;
6175 pc->req = GNUNET_new (struct PilsRequest);
6177 &sa.purpose,
6179 pc);
6182 pc->req);
6183}
6184
6185
6191static void
6192store_pi (void *cls)
6193{
6194 struct AddressListEntry *ale = cls;
6195 const char *dash;
6196 char *address_uri;
6197 char *prefix;
6198 unsigned int add_success;
6199
6200 if (NULL == GST_my_identity)
6201 {
6203 &store_pi,
6204 ale);
6205 return;
6206 }
6208 dash = strchr (ale->address, '-');
6209 GNUNET_assert (NULL != dash);
6210 dash++;
6211 GNUNET_asprintf (&address_uri,
6212 "%s://%s",
6213 prefix,
6214 dash);
6216 ale->st = NULL;
6218 "Storing our address `%s' in peerstore until %s!\n",
6219 ale->address,
6222 address_uri);
6223 if (GNUNET_OK != add_success)
6224 {
6226 "Storing our address `%s' %s\n",
6227 address_uri,
6228 GNUNET_NO == add_success ? "not done" : "failed");
6229 GNUNET_free (address_uri);
6230 return;
6231 }
6232 else
6233 {
6234
6236 "Storing our address `%s'\n",
6237 address_uri);
6238 }
6239 // FIXME hello_mono_time used here?? What about expiration in ale?
6240 pils_sign_address (ale,
6242 // TODO keep track of op and potentially cancel/clean
6243 GNUNET_free (address_uri);
6244}
6245
6246
6247static struct AddressListEntry *
6251 const char *address,
6252 uint32_t aid,
6253 size_t slen)
6254{
6255 struct AddressListEntry *ale;
6256 char *address_without_port;
6257
6258 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6259 ale->tc = tc;
6260 ale->address = (const char *) &ale[1];
6261 ale->expiration = expiration;
6262 ale->aid = aid;
6263 ale->nt = nt;
6264 memcpy (&ale[1], address, slen);
6265 address_without_port = get_address_without_port (ale->address);
6267 "Is this %s a local address (%s)\n",
6268 address_without_port,
6269 ale->address);
6270 if (0 != strcmp ("127.0.0.1", address_without_port))
6271 {
6272 if (NULL != ale->st)
6273 {
6275 }
6276 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6277 }
6278 GNUNET_free (address_without_port);
6279
6280 return ale;
6281}
6282
6283
6284static void
6286{
6287
6289 "Feeding addresses to PILS\n");
6290 pils_feed_task = NULL;
6291
6293 GST_my_hello);
6294}
6295
6296
6303static void
6305 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6306{
6307 struct TransportClient *tc = cls;
6308 struct AddressListEntry *ale;
6309 size_t slen;
6310 char *address;
6311
6312 /* 0-termination of &aam[1] was checked in #check_add_address */
6314 "Communicator added address `%s'!\n",
6315 (const char *) &aam[1]);
6316 slen = ntohs (aam->header.size) - sizeof(*aam);
6317 address = GNUNET_malloc (slen);
6318 memcpy (address, &aam[1], slen);
6319 ale = create_address_entry (tc,
6321 ntohl (aam->nt),
6322 address,
6323 aam->aid,
6324 slen);
6325 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6326 tc->details.communicator.addr_tail,
6327 ale);
6328 {
6329 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6330 (NULL != iter && NULL != iter->next);
6331 iter = iter->next)
6332 {
6333 char *address_uri;
6334 char *dash = strchr (ale->address, '-');
6336 GNUNET_assert (NULL != dash);
6337 dash++;
6338 GNUNET_asprintf (&address_uri,
6339 "%s://%s",
6340 prefix,
6341 dash);
6344 GNUNET_free (address_uri);
6345 }
6346 if (NULL != pils_feed_task)
6350 NULL);
6351 }
6354}
6355
6356
6363static void
6365 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6366{
6367 struct TransportClient *tc = cls;
6368 struct AddressListEntry *alen;
6369
6370 if (CT_COMMUNICATOR != tc->type)
6371 {
6372 GNUNET_break (0);
6374 return;
6375 }
6376 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6377 NULL != ale;
6378 ale = alen)
6379 {
6380 alen = ale->next;
6381 if (dam->aid != ale->aid)
6382 continue;
6383 GNUNET_assert (ale->tc == tc);
6385 "Communicator deleted address `%s'!\n",
6386 ale->address);
6388 ale->address);
6389 if (NULL != pils_feed_task)
6393 NULL);
6396 return;
6397 }
6399 "Communicator removed address we did not even have.\n");
6401 // GNUNET_SERVICE_client_drop (tc->client);
6402}
6403
6404
6412static void
6414
6415
6423static void
6425{
6426 struct CoreSentContext *ctx = cls;
6427 struct VirtualLink *vl = ctx->vl;
6428
6429 if (NULL == vl)
6430 {
6431 /* lost the link in the meantime, ignore */
6432 GNUNET_free (ctx);
6433 return;
6434 }
6437 vl->incoming_fc_window_size_ram -= ctx->size;
6438 vl->incoming_fc_window_size_used += ctx->isize;
6440 GNUNET_free (ctx);
6441}
6442
6443
6444static void
6446 const struct GNUNET_MessageHeader *mh,
6447 struct CommunicatorMessageContext *cmc,
6448 unsigned int free_cmc)
6449{
6450 uint16_t size = ntohs (mh->size);
6451 int have_core;
6452
6453 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6454 {
6456 "# CORE messages dropped (FC arithmetic overflow)",
6457 1,
6458 GNUNET_NO);
6460 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6461 (unsigned int) ntohs (mh->type),
6462 (unsigned int) ntohs (mh->size));
6463 if (GNUNET_YES == free_cmc)
6465 return;
6466 }
6468 {
6470 "# CORE messages dropped (FC window overflow)",
6471 1,
6472 GNUNET_NO);
6474 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6475 (unsigned int) ntohs (mh->type),
6476 (unsigned int) ntohs (mh->size));
6477 if (GNUNET_YES == free_cmc)
6479 return;
6480 }
6481
6482 /* Forward to all CORE clients */
6483 have_core = GNUNET_NO;
6484 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6485 {
6486 struct GNUNET_MQ_Envelope *env;
6487 struct InboundMessage *im;
6488 struct CoreSentContext *ctx;
6489
6490 if (CT_CORE != tc->type)
6491 continue;
6494 ctx = GNUNET_new (struct CoreSentContext);
6495 ctx->vl = vl;
6496 ctx->size = size;
6497 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6498 have_core = GNUNET_YES;
6501 im->peer = cmc->im.sender;
6502 memcpy (&im[1], mh, size);
6503 GNUNET_MQ_send (tc->mq, env);
6505 }
6506 if (GNUNET_NO == have_core)
6507 {
6509 "Dropped message to CORE: no CORE client connected!\n");
6510 /* Nevertheless, count window as used, as it is from the
6511 perspective of the other peer! */
6513 /* TODO-M1 */
6515 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6516 (unsigned int) ntohs (mh->type),
6517 (unsigned int) ntohs (mh->size));
6518 if (GNUNET_YES == free_cmc)
6520 return;
6521 }
6523 "Delivered message from %s of type %u to CORE recv window %d\n",
6524 GNUNET_i2s (&cmc->im.sender),
6525 ntohs (mh->type),
6527 if (vl->core_recv_window > 0)
6528 {
6529 if (GNUNET_YES == free_cmc)
6531 return;
6532 }
6533 /* Wait with calling #finish_cmc_handling(cmc) until the message
6534 was processed by CORE MQs (for CORE flow control)! */
6535 if (GNUNET_YES == free_cmc)
6537}
6538
6539
6548static void
6550{
6551 struct CommunicatorMessageContext *cmc = cls;
6552 // struct CommunicatorMessageContext *cmc_copy =
6553 // GNUNET_new (struct CommunicatorMessageContext);
6554 struct GNUNET_MessageHeader *mh_copy;
6555 struct RingBufferEntry *rbe;
6556 struct VirtualLink *vl;
6557 uint16_t size = ntohs (mh->size);
6558
6560 "Handling raw message of type %u with %u bytes\n",
6561 (unsigned int) ntohs (mh->type),
6562 (unsigned int) ntohs (mh->size));
6563
6564 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6565 (size < sizeof(struct GNUNET_MessageHeader)))
6566 {
6567 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6568
6569 GNUNET_break (0);
6570 finish_cmc_handling (cmc);
6572 return;
6573 }
6574 vl = lookup_virtual_link (&cmc->im.sender);
6575 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6576 {
6577 /* FIXME: sender is giving us messages for CORE but we don't have
6578 the link up yet! I *suspect* this can happen right now (i.e.
6579 sender has verified us, but we didn't verify sender), but if
6580 we pass this on, CORE would be confused (link down, messages
6581 arrive). We should investigate more if this happens often,
6582 or in a persistent manner, and possibly do "something" about
6583 it. Thus logging as error for now. */
6584
6585 mh_copy = GNUNET_malloc (size);
6586 rbe = GNUNET_new (struct RingBufferEntry);
6587 rbe->cmc = cmc;
6588 /*cmc_copy->tc = cmc->tc;
6589 cmc_copy->im = cmc->im;*/
6590 GNUNET_memcpy (mh_copy, mh, size);
6591
6592 rbe->mh = mh_copy;
6593
6595 {
6596 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6597 GNUNET_free (rbe_old->cmc);
6598 GNUNET_free (rbe_old->mh);
6599 GNUNET_free (rbe_old);
6600 }
6601 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6602 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6603 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6605 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6606 GNUNET_i2s (&cmc->im.sender),
6607 (unsigned int) ntohs (mh->type),
6608 (unsigned int) ntohs (mh_copy->type),
6612 {
6613 ring_buffer_head = 0;
6615 }
6616 else
6618
6620 "%u items stored in ring buffer\n",
6623
6624 /*GNUNET_break_op (0);
6625 GNUNET_STATISTICS_update (GST_stats,
6626 "# CORE messages dropped (virtual link still down)",
6627 1,
6628 GNUNET_NO);
6629
6630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6631 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6632 (unsigned int) ntohs (mh->type),
6633 (unsigned int) ntohs (mh->size));
6634 finish_cmc_handling (cmc);*/
6637 // GNUNET_free (cmc);
6638 return;
6639 }
6641}
6642
6643
6651static int
6653{
6654 uint16_t size = ntohs (fb->header.size);
6655 uint16_t bsize = size - sizeof(*fb);
6656
6657 (void) cls;
6658 if (0 == bsize)
6659 {
6660 GNUNET_break_op (0);
6661 return GNUNET_SYSERR;
6662 }
6663 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6664 {
6665 GNUNET_break_op (0);
6666 return GNUNET_SYSERR;
6667 }
6668 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6669 {
6670 GNUNET_break_op (0);
6671 return GNUNET_SYSERR;
6672 }
6673 return GNUNET_YES;
6674}
6675
6676
6682static void
6684{
6685 struct AcknowledgementCummulator *ac = cls;
6686
6687 ac->task = NULL;
6688 GNUNET_assert (0 == ac->num_acks);
6690 GNUNET_YES ==
6692 GNUNET_free (ac);
6693}
6694
6695
6701static void
6703{
6704 struct Neighbour *n;
6705 struct VirtualLink *vl;
6706 struct AcknowledgementCummulator *ac = cls;
6707 char buf[sizeof(struct TransportReliabilityAckMessage)
6708 + ac->num_acks
6710 struct TransportReliabilityAckMessage *ack =
6711 (struct TransportReliabilityAckMessage *) buf;
6713
6714 ac->task = NULL;
6716 "Sending ACK with %u components to %s\n",
6717 ac->num_acks,
6718 GNUNET_i2s (&ac->target));
6719 GNUNET_assert (0 < ac->num_acks);
6721 ack->header.size =
6722 htons (sizeof(*ack)
6723 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6724 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6725 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6726 for (unsigned int i = 0; i < ac->num_acks; i++)
6727 {
6728 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6731 }
6732 /*route_control_message_without_fc (
6733 &ac->target,
6734 &ack->header,
6735 RMO_DV_ALLOWED);*/
6736 vl = lookup_virtual_link (&ac->target);
6737 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6738 {
6740 vl,
6741 &ack->header,
6743 }
6744 else
6745 {
6746 /* Use route via neighbour */
6747 n = lookup_neighbour (&ac->target);
6748 if (NULL != n)
6750 n,
6751 &ack->header,
6752 RMO_NONE);
6753 }
6754 ac->num_acks = 0;
6757 ac);
6758}
6759
6760
6769static void
6771 const struct AcknowledgementUUIDP *ack_uuid,
6772 struct GNUNET_TIME_Absolute max_delay)
6773{
6774 struct AcknowledgementCummulator *ac;
6775
6777 "Scheduling ACK %s for transmission to %s\n",
6778 GNUNET_uuid2s (&ack_uuid->value),
6779 GNUNET_i2s (pid));
6781 if (NULL == ac)
6782 {
6784 ac->target = *pid;
6785 ac->min_transmission_time = max_delay;
6789 &ac->target,
6790 ac,
6792 }
6793 else
6794 {
6795 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6796 {
6797 /* must run immediately, ack buffer full! */
6799 }
6803 }
6806 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6807 ac->num_acks++;
6810 ac);
6811}
6812
6813
6829
6830
6840static int
6841find_by_message_uuid (void *cls, uint32_t key, void *value)
6842{
6843 struct FindByMessageUuidContext *fc = cls;
6844 struct ReassemblyContext *rc = value;
6845
6846 (void) key;
6847 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6848 {
6849 fc->rc = rc;
6850 return GNUNET_NO;
6851 }
6852 return GNUNET_YES;
6853}
6854
6855
6863static void
6865{
6866 struct CommunicatorMessageContext *cmc = cls;
6867 struct VirtualLink *vl;
6868 struct ReassemblyContext *rc;
6869 const struct GNUNET_MessageHeader *msg;
6870 uint16_t msize;
6871 uint16_t fsize;
6872 uint16_t frag_off;
6873 char *target;
6874 struct GNUNET_TIME_Relative cdelay;
6875 struct FindByMessageUuidContext fc;
6876
6877 vl = lookup_virtual_link (&cmc->im.sender);
6878 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6879 {
6880 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6881
6883 "No virtual link for %s to handle fragment\n",
6884 GNUNET_i2s (&cmc->im.sender));
6885 GNUNET_break (0);
6886 finish_cmc_handling (cmc);
6888 return;
6889 }
6890 if (NULL == vl->reassembly_map)
6891 {
6893 vl->reassembly_heap =
6898 vl);
6899 }
6900 msize = ntohs (fb->msg_size);
6901 fc.message_uuid = fb->msg_uuid;
6902 fc.rc = NULL;
6904 fb->msg_uuid.uuid,
6906 &fc);
6907 fsize = ntohs (fb->header.size) - sizeof(*fb);
6908 if (NULL == (rc = fc.rc))
6909 {
6910 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6911 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6912 rc->msg_uuid = fb->msg_uuid;
6913 rc->virtual_link = vl;
6914 rc->msg_size = msize;
6915 rc->reassembly_timeout =
6919 rc,
6923 vl->reassembly_map,
6924 rc->msg_uuid.uuid,
6925 rc,
6927 target = (char *) &rc[1];
6928 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6929 if (fsize != rc->msg_size)
6930 rc->msg_missing = rc->msg_size;
6931 else
6932 rc->msg_missing = 0;
6934 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6935 PRIu64 "\n",
6936 fsize,
6937 ntohs (fb->frag_off),
6938 msize,
6939 rc->msg_missing,
6940 GNUNET_i2s (&cmc->im.sender),
6941 fb->msg_uuid.uuid);
6942 }
6943 else
6944 {
6945 target = (char *) &rc[1];
6947 "Received fragment at offset %u/%u from %s for message %u\n",
6948 ntohs (fb->frag_off),
6949 msize,
6950 GNUNET_i2s (&cmc->im.sender),
6951 (unsigned int) fb->msg_uuid.uuid);
6952 }
6953 if (msize != rc->msg_size)
6954 {
6955 GNUNET_break (0);
6956 finish_cmc_handling (cmc);
6957 return;
6958 }
6959
6960 /* reassemble */
6961 if (0 == fsize)
6962 {
6963 GNUNET_break (0);
6964 finish_cmc_handling (cmc);
6965 return;
6966 }
6967 frag_off = ntohs (fb->frag_off);
6968 if (frag_off + fsize > msize)
6969 {
6970 /* Fragment (plus fragment size) exceeds message size! */
6971 GNUNET_break_op (0);
6972 finish_cmc_handling (cmc);
6973 return;
6974 }
6975 memcpy (&target[frag_off], &fb[1], fsize);
6976 /* update bitfield and msg_missing */
6977 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6978 {
6979 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6980 {
6981 rc->bitfield[i / 8] |= (1 << (i % 8));
6982 rc->msg_missing--;
6983 }
6984 }
6985
6986 /* Compute cumulative ACK */
6988 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6989 if (0 == rc->msg_missing)
6990 cdelay = GNUNET_TIME_UNIT_ZERO;
6991 cummulative_ack (&cmc->im.sender,
6992 &fb->ack_uuid,
6995 /* is reassembly complete? */
6996 if (0 != rc->msg_missing)
6997 {
6998 finish_cmc_handling (cmc);
6999 return;
7000 }
7001 /* reassembly is complete, verify result */
7002 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7003 if (ntohs (msg->size) != rc->msg_size)
7004 {
7005 GNUNET_break (0);
7007 finish_cmc_handling (cmc);
7008 return;
7009 }
7010 /* successful reassembly */
7012 "Fragment reassembly complete for message %u\n",
7013 (unsigned int) fb->msg_uuid.uuid);
7014 /* FIXME: check that the resulting msg is NOT a
7015 DV Box or Reliability Box, as that is NOT allowed! */
7016 cmc->mh = msg;
7018 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
7019 en-route and we forget that we finished this reassembly immediately!
7020 -> keep around until timeout?
7021 -> shorten timeout based on ACK? */
7023}
7024
7025
7033static int
7035 const struct TransportReliabilityBoxMessage *rb)
7036{
7037 const struct GNUNET_MessageHeader *box = (const struct
7038 GNUNET_MessageHeader *) &rb[1];
7039 (void) cls;
7040
7042 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7043 ntohs (rb->header.size),
7044 ntohs (box->type),
7045 ntohs (box->size),
7046 sizeof (struct TransportReliabilityBoxMessage),
7047 sizeof (struct GNUNET_MessageHeader));
7049 return GNUNET_YES;
7050}
7051
7052
7060static void
7062 const struct TransportReliabilityBoxMessage *rb)
7063{
7064 struct CommunicatorMessageContext *cmc = cls;
7065 const struct GNUNET_MessageHeader *inbox =
7066 (const struct GNUNET_MessageHeader *) &rb[1];
7067 struct GNUNET_TIME_Relative rtt;
7068
7070 "Received reliability box from %s with UUID %s of type %u\n",
7071 GNUNET_i2s (&cmc->im.sender),
7073 (unsigned int) ntohs (inbox->type));
7074 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
7075 do not really have an RTT for the
7076 * incoming* queue (should we have
7077 the sender add it to the rb message?) */
7079 &cmc->im.sender,
7080 &rb->ack_uuid,
7081 (0 == ntohl (rb->ack_countdown))
7084 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
7085 /* continue with inner message */
7086 /* FIXME: check that inbox is NOT a DV Box, fragment or another
7087 reliability box (not allowed!) */
7088 cmc->mh = inbox;
7090}
7091
7092
7101static void
7102update_pd_age (struct PerformanceData *pd, unsigned int age)
7103{
7104 unsigned int sage;
7105
7106 if (age == pd->last_age)
7107 return; /* nothing to do */
7108 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7109 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7110 {
7111 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7112
7113 the->bytes_sent = 0;
7114 the->bytes_received = 0;
7115 }
7116 pd->last_age = age;
7117}
7118
7119
7128static void
7130 struct GNUNET_TIME_Relative rtt,
7131 uint16_t bytes_transmitted_ok)
7132{
7133 uint64_t nval = rtt.rel_value_us;
7134 uint64_t oval = pd->aged_rtt.rel_value_us;
7135 unsigned int age = get_age ();
7136 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7137
7138 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7139 pd->aged_rtt = rtt;
7140 else
7141 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7142 update_pd_age (pd, age);
7143 the->bytes_received += bytes_transmitted_ok;
7144}
7145
7146
7154static void
7156 struct GNUNET_TIME_Relative rtt,
7157 uint16_t bytes_transmitted_ok)
7158{
7159 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7160}
7161
7162
7170static void
7172 struct GNUNET_TIME_Relative rtt,
7173 uint16_t bytes_transmitted_ok)
7174{
7175 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7176}
7177
7178
7186static void
7188{
7189 struct PendingMessage *pos;
7190
7192 "Complete transmission of message %" PRIu64 " %u\n",
7193 pm->logging_uuid,
7194 pm->pmt);
7195 switch (pm->pmt)
7196 {
7197 case PMT_CORE:
7199 /* Full message sent, we are done */
7201 return;
7202
7203 case PMT_FRAGMENT_BOX:
7204 /* Fragment sent over reliable channel */
7205 pos = pm->frag_parent;
7209 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7210 (unsigned long) pos->frag_off,
7211 (unsigned long) pos->bytes_msg,
7212 pos->pmt,
7213 NULL == pos->frag_parent ? 1 : 0);
7214 /* check if subtree is done */
7215 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7216 - sizeof(struct
7218 &&
7219 (NULL != pos->frag_parent))
7220 {
7221 pm = pos;
7222 pos = pm->frag_parent;
7223 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7224 {
7226 return;
7227 }
7228 else if (PMT_DV_BOX == pm->pmt)
7229 {
7231 return;
7232 }
7235 }
7236
7237 /* Was this the last applicable fragment? */
7238 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7239 pos->pmt) &&
7240 (pos->frag_off == pos->bytes_msg))
7242 return;
7243
7244 case PMT_DV_BOX:
7246 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7247 pm->logging_uuid);
7248 if (NULL != pm->frag_parent)
7249 {
7250 pos = pm->frag_parent;
7252 pos->bpm = NULL;
7254 }
7255 else
7257 return;
7258 }
7259}
7260
7261
7269static void
7271 struct GNUNET_TIME_Relative ack_delay)
7272{
7273 struct GNUNET_TIME_Relative delay;
7274
7276 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7277 if (NULL != pa->queue && 1 == pa->num_send)
7279 if (NULL != pa->dvh && 1 == pa->num_send)
7280 update_dvh_performance (pa->dvh, delay, pa->message_size);
7281 if (NULL != pa->pm)
7284}
7285
7286
7294static int
7296 const struct TransportReliabilityAckMessage *ra)
7297{
7298 unsigned int n_acks;
7299
7300 (void) cls;
7301 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7302 / sizeof(struct TransportCummulativeAckPayloadP);
7303 if (0 == n_acks)
7304 {
7305 GNUNET_break_op (0);
7306 return GNUNET_SYSERR;
7307 }
7308 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7309 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7310 {
7311 GNUNET_break_op (0);
7312 return GNUNET_SYSERR;
7313 }
7314 return GNUNET_OK;
7315}
7316
7317
7325static void
7327 const struct TransportReliabilityAckMessage *ra)
7328{
7329 struct CommunicatorMessageContext *cmc = cls;
7330 const struct TransportCummulativeAckPayloadP *ack;
7331 unsigned int n_acks;
7332 uint32_t ack_counter;
7333
7334 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7335 / sizeof(struct TransportCummulativeAckPayloadP);
7336 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7337 for (unsigned int i = 0; i < n_acks; i++)
7338 {
7339 struct PendingAcknowledgement *pa =
7341 if (NULL == pa)
7342 {
7344 "Received ACK from %s with UUID %s which is unknown to us!\n",
7345 GNUNET_i2s (&cmc->im.sender),
7346 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7348 GST_stats,
7349 "# FRAGMENT_ACKS dropped, no matching pending message",
7350 1,
7351 GNUNET_NO);
7352 continue;
7353 }
7355 "Received ACK from %s with UUID %s\n",
7356 GNUNET_i2s (&cmc->im.sender),
7357 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7358 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7359 }
7360
7361 ack_counter = htonl (ra->ack_counter);
7362 (void) ack_counter; /* silence compiler warning for now */
7363 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7364 // (DV and/or Neighbour?)
7365 finish_cmc_handling (cmc);
7366}
7367
7368
7376static int
7378 void *cls,
7380{
7381 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7382 const struct GNUNET_MessageHeader *inbox =
7383 (const struct GNUNET_MessageHeader *) &be[1];
7384 const char *is;
7385 uint16_t isize;
7386
7387 (void) cls;
7388 if (ntohs (inbox->size) >= size)
7389 {
7390 GNUNET_break_op (0);
7391 return GNUNET_SYSERR;
7392 }
7393 isize = ntohs (inbox->size);
7394 is = ((const char *) inbox) + isize;
7395 size -= isize;
7396 if ('\0' != is[size - 1])
7397 {
7398 GNUNET_break_op (0);
7399 return GNUNET_SYSERR;
7400 }
7401 return GNUNET_YES;
7402}
7403
7404
7413static void
7415 void *cls,
7417{
7418 struct CommunicatorMessageContext *cmc = cls;
7420 struct GNUNET_MQ_Envelope *env;
7421 struct TransportClient *tc;
7422 const struct GNUNET_MessageHeader *inbox =
7423 (const struct GNUNET_MessageHeader *) &be[1];
7424 uint16_t isize = ntohs (inbox->size);
7425 const char *target_communicator = ((const char *) inbox) + isize;
7426 char *sender;
7427 char *self;
7428
7429 GNUNET_asprintf (&sender,
7430 "%s",
7431 GNUNET_i2s (&cmc->im.sender));
7432 GNUNET_asprintf (&self,
7433 "%s",
7435
7436 /* Find client providing this communicator */
7437 for (tc = clients_head; NULL != tc; tc = tc->next)
7438 if ((CT_COMMUNICATOR == tc->type) &&
7439 (0 ==
7440 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7441 break;
7442 if (NULL == tc)
7443 {
7444 char *stastr;
7445
7447 &stastr,
7448 "# Backchannel message dropped: target communicator `%s' unknown",
7449 target_communicator);
7451 GNUNET_free (stastr);
7452 finish_cmc_handling (cmc);
7453 return;
7454 }
7455 /* Finally, deliver backchannel message to communicator */
7457 "Delivering backchannel message from %s to %s of type %u to %s\n",
7458 sender,
7459 self,
7460 ntohs (inbox->type),
7461 target_communicator);
7463 cbi,
7464 isize,
7466 cbi->pid = cmc->im.sender;
7467 memcpy (&cbi[1], inbox, isize);
7468 GNUNET_MQ_send (tc->mq, env);
7469 finish_cmc_handling (cmc);
7470}
7471
7472
7482static void
7484{
7485 struct DistanceVector *dv = cls;
7486 struct DistanceVectorHop *pos;
7487
7488 dv->timeout_task = NULL;
7489 while (NULL != (pos = dv->dv_head))
7490 {
7491 GNUNET_assert (dv == pos->dv);
7493 break;
7495 }
7496 if (NULL == pos)
7497 {
7498 free_dv_route (dv);
7499 return;
7500 }
7501 dv->timeout_task =
7503}
7504
7505
7506static void
7508{
7509
7510 const struct GNUNET_PeerIdentity target = vl->target;
7511
7512
7514 {
7515 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7516 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7517 0;
7518 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7521 struct CommunicatorMessageContext *cmc;
7522 struct RingBufferEntry *rbe;
7523 struct GNUNET_MessageHeader *mh;
7524
7526 "Sending from ring buffer, which has %u items\n",
7527 head);
7528
7529 ring_buffer_head = 0;
7530 for (unsigned int i = 0; i < head; i++)
7531 {
7532 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7533 cmc = rbe->cmc;
7534 mh = rbe->mh;
7535
7536 im = cmc->im;
7537 // mh = cmc->mh;
7539 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7540 mh->type,
7541 GNUNET_i2s (&im.sender),
7542 GNUNET_i2s2 (&target),
7543 (i + tail) % RING_BUFFER_SIZE);
7544 if (0 == GNUNET_memcmp (&target, &im.sender))
7545 {
7547 "Finish handling message of type %u and size %u\n",
7548 (unsigned int) ntohs (mh->type),
7549 (unsigned int) ntohs (mh->size));
7551 GNUNET_free (mh);
7552 GNUNET_free (rbe->cmc);
7553 GNUNET_free (rbe);
7554 }
7555 else
7556 {
7557 ring_buffer_copy[ring_buffer_head] = rbe;
7559 }
7560 }
7561
7564 {
7566 }
7567
7568 for (unsigned int i = 0; i < ring_buffer_head; i++)
7569 {
7570 ring_buffer[i] = ring_buffer_copy[i];
7572 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7573 i,
7574 ring_buffer_copy[i]->mh->type);
7576 "ring_buffer[i]->mh->type for i %u %u\n",
7577 i,
7578 ring_buffer[i]->mh->type);
7579 }
7580
7582 "%u items still in ring buffer\n",
7584 }
7585
7587 {
7588 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7589 struct PendingMessage *pm;
7590 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7592 0;
7593 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7596
7598 "Sending from ring buffer dv, which has %u items\n",
7599 head);
7600
7602 for (unsigned int i = 0; i < head; i++)
7603 {
7604 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7605
7607 "Sending to ring buffer target %s using vl target %s\n",
7608 GNUNET_i2s (&pm->target),
7609 GNUNET_i2s2 (&target));
7610 if (0 == GNUNET_memcmp (&target, &pm->target))
7611 {
7613 "Adding PendingMessage to vl, checking transmission.\n");
7614 pm->vl = vl;
7618 pm);
7619
7621 }
7622 else
7623 {
7624 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7626 }
7627 }
7628
7630 {
7632 }
7633
7634 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7635 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7636
7638 "%u items still in ring buffer dv.\n",
7640
7641 }
7642}
7643
7644
7652static void
7654{
7655 struct DistanceVector *dv = hop->dv;
7656 struct VirtualLink *vl;
7657
7658 vl = lookup_virtual_link (&dv->target);
7659 if (NULL == vl)
7660 {
7661
7662 vl = GNUNET_new (struct VirtualLink);
7664 "Creating new virtual link %p to %s using DV!\n",
7665 vl,
7666 GNUNET_i2s (&dv->target));
7667 vl->burst_addr = NULL;
7668 vl->confirmed = GNUNET_YES;
7669 vl->message_uuid_ctr =
7671 vl->target = dv->target;
7677 links,
7678 &vl->target,
7679 vl,
7681 vl->dv = dv;
7682 dv->vl = vl;
7683 vl->visibility_task =
7686 /* We lacked a confirmed connection to the target
7687 before, so tell CORE about it (finally!) */
7690 }
7691 else
7692 {
7693 /* Link was already up, remember dv is also now available and we are done */
7694 vl->dv = dv;
7695 dv->vl = vl;
7696 if (GNUNET_NO == vl->confirmed)
7697 {
7698 vl->confirmed = GNUNET_YES;
7699 vl->visibility_task =
7702 /* We lacked a confirmed connection to the target
7703 before, so tell CORE about it (finally!) */
7706 }
7707 else
7709 "Virtual link to %s could now also use DV!\n",
7710 GNUNET_i2s (&dv->target));
7711 }
7712}
7713
7714
7740static int
7742 unsigned int path_len,
7743 struct GNUNET_TIME_Relative network_latency,
7744 struct GNUNET_TIME_Absolute path_valid_until)
7745{
7746 struct DistanceVectorHop *hop;
7747 struct DistanceVector *dv;
7748 struct Neighbour *next_hop;
7749 unsigned int shorter_distance;
7750
7751 if (path_len < 3)
7752 {
7753 /* what a boring path! not allowed! */
7754 GNUNET_break (0);
7755 return GNUNET_SYSERR;
7756 }
7757 GNUNET_assert (0 == GNUNET_memcmp (GST_my_identity, &path[0]));
7758 next_hop = lookup_neighbour (&path[1]);
7759 if (NULL == next_hop)
7760 {
7761 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7762 GNUNET_break (0);
7763 return GNUNET_SYSERR;
7764 }
7765 for (unsigned int i = 2; i < path_len; i++)
7766 {
7767 struct Neighbour *n = lookup_neighbour (&path[i]);
7768 struct GNUNET_TIME_Absolute q_timeout;
7769
7770 if (NULL != n)
7771 {
7772 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7773 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7774 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7776 "remaining %lu to %s\n",
7777 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7778 .rel_value_us,
7779 GNUNET_i2s (&n->pid));
7780 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7781 {
7782 /* Useless path: we have a direct active connection to some hop
7783 in the middle of the path, so this one is not even
7784 terribly useful for redundancy */
7786 "Path of %u hops useless: directly link to hop %u (%s)\n",
7787 path_len,
7788 i,
7789 GNUNET_i2s (&path[i]));
7791 "# Useless DV path ignored: hop is neighbour",
7792 1,
7793 GNUNET_NO);
7794 return GNUNET_SYSERR;
7795 }
7796 }
7797 }
7798 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7799 if (NULL == dv)
7800 {
7801 dv = GNUNET_new (struct DistanceVector);
7802 dv->target = path[path_len - 1];
7805 dv);
7808 dv_routes,
7809 &dv->target,
7810 dv,
7812 }
7813 /* Check if we have this path already! */
7814 shorter_distance = 0;
7815 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7816 pos = pos->next_dv)
7817 {
7818 if (pos->distance < path_len - 3)
7819 shorter_distance++;
7820 /* Note that the distances in 'pos' excludes us (path[0]),
7821 the next_hop (path[1]) and the target so we need to subtract three
7822 and check next_hop explicitly */
7823 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7824 {
7825 int match = GNUNET_YES;
7826
7827 for (unsigned int i = 0; i < pos->distance; i++)
7828 {
7829 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7830 {
7831 match = GNUNET_NO;
7832 break;
7833 }
7834 }
7835 if (GNUNET_YES == match)
7836 {
7837 struct GNUNET_TIME_Relative last_timeout;
7838
7839 /* Re-discovered known path, update timeout */
7841 "# Known DV path refreshed",
7842 1,
7843 GNUNET_NO);
7844 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7845 pos->timeout =
7847 pos->path_valid_until =
7848 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7849 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7850 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7851 if (0 <
7854 if (last_timeout.rel_value_us <
7857 .rel_value_us)
7858 {
7859 /* Some peer send DV learn messages too often, we are learning
7860 the same path faster than it would be useful; do not forward! */
7862 "Rediscovered path too quickly, not forwarding further\n")
7863 ;
7864 return GNUNET_NO;
7865 }
7867 "Refreshed known path to %s valid until %s, forwarding further\n",
7868 GNUNET_i2s (&dv->target),
7870 pos->path_valid_until));
7871 return GNUNET_YES;
7872 }
7873 }
7874 }
7875 /* Count how many shorter paths we have (incl. direct
7876 neighbours) before simply giving up on this one! */
7877 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7878 {
7879 /* We have a shorter path already! */
7881 "Have many shorter DV paths %s, not forwarding further\n",
7882 GNUNET_i2s (&dv->target));
7883 return GNUNET_NO;
7884 }
7885 /* create new DV path entry */
7887 "Discovered new DV path to %s valid until %s\n",
7888 GNUNET_i2s (&dv->target),
7889 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7890 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7891 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7892 hop->next_hop = next_hop;
7893 hop->dv = dv;
7894 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7895 memcpy (&hop[1],
7896 &path[2],
7897 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7899 hop->path_valid_until = path_valid_until;
7900 hop->distance = path_len - 3;
7901 hop->pd.aged_rtt = network_latency;
7902 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7904 next_hop->dv_head,
7905 next_hop->dv_tail,
7906 hop);
7907 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7909 return GNUNET_YES;
7910}
7911
7912
7920static int
7921check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7922{
7923 uint16_t size = ntohs (dvl->header.size);
7924 uint16_t num_hops = ntohs (dvl->num_hops);
7925 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7926
7927 (void) cls;
7928 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7929 {
7930 GNUNET_break_op (0);
7931 return GNUNET_SYSERR;
7932 }
7933 if (num_hops > MAX_DV_HOPS_ALLOWED)
7934 {
7935 GNUNET_break_op (0);
7936 return GNUNET_SYSERR;
7937 }
7938 for (unsigned int i = 0; i < num_hops; i++)
7939 {
7940 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7941 {
7942 GNUNET_break_op (0);
7943 return GNUNET_SYSERR;
7944 }
7945 if (0 == GNUNET_memcmp (GST_my_identity, &hops[i].hop))
7946 {
7947 GNUNET_break_op (0);
7948 return GNUNET_SYSERR;
7949 }
7950 }
7951 return GNUNET_YES;
7952}
7953
7954
7963
7964
7965static void
7966sign_dhp_cp (void *cls,
7967 const struct GNUNET_PeerIdentity *pid,
7968 const struct GNUNET_CRYPTO_EddsaSignature *sig)
7969{
7970 struct SignDhpCls *sign_dhp_cls = cls;
7971 struct VirtualLink *vl;
7972 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
7973 uint16_t nhops = sign_dhp_cls->nhops;
7974 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
7975 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
7976 struct Neighbour *n;
7977
7978 sign_dhp_cls->pr->op = NULL;
7981 sign_dhp_cls->pr);
7982 GNUNET_free (sign_dhp_cls->pr);
7983 dhops[nhops].hop_sig = *sig;
7984
7985 /*route_control_message_without_fc (next_hop,
7986 &fwd->header,
7987 RMO_UNCONFIRMED_ALLOWED);*/
7988 vl = lookup_virtual_link (next_hop);
7989 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7990 {
7992 &fwd->header,
7994 }
7995 else
7996 {
7997 /* Use route via neighbour */
7998 n = lookup_neighbour (next_hop);
7999 if (NULL != n)
8001 n,
8002 &fwd->header,
8004 }
8005 GNUNET_free (sign_dhp_cls);
8006}
8007
8008
8020static void
8022 const struct TransportDVLearnMessage *msg,
8023 uint16_t bi_history,
8024 uint16_t nhops,
8025 const struct DVPathEntryP *hops,
8026 struct GNUNET_TIME_Absolute in_time)
8027{
8028 struct DVPathEntryP *dhops;
8029 char buf[sizeof(struct TransportDVLearnMessage)
8030 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8031 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
8032 struct GNUNET_TIME_Relative nnd;
8033
8034 /* compute message for forwarding */
8036 "Forwarding DV learn message originating from %s to %s\n",
8037 GNUNET_i2s (&msg->initiator),
8038 GNUNET_i2s2 (next_hop));
8041 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8042 + (nhops + 1) * sizeof(struct DVPathEntryP));
8043 fwd->num_hops = htons (nhops + 1);
8044 fwd->bidirectional = htons (bi_history);
8047 msg->non_network_delay));
8049 fwd->init_sig = msg->init_sig;
8050 fwd->initiator = msg->initiator;
8051 fwd->challenge = msg->challenge;
8052 fwd->monotonic_time = msg->monotonic_time;
8053 dhops = (struct DVPathEntryP *) &fwd[1];
8054 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8055 dhops[nhops].hop = *GST_my_identity;
8056 {
8057 struct DvHopPS dhp = {
8059 .purpose.size = htonl (sizeof(dhp)),
8060 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8061 .succ = *next_hop,
8062 .challenge = msg->challenge
8063 };
8064 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
8065 sign_dhp_cls->dhops = dhops;
8066 sign_dhp_cls->nhops = nhops;
8067 sign_dhp_cls->next_hop = next_hop;
8068 sign_dhp_cls->fwd = fwd;
8069 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
8072 sign_dhp_cls->pr);
8073 sign_dhp_cls->pr->op =
8075 &dhp.purpose,
8077 sign_dhp_cls);
8078 }
8079}
8080
8081
8091static int
8093 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
8094 const struct GNUNET_PeerIdentity *init,
8095 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
8096 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
8097{
8098 struct DvInitPS ip = { .purpose.purpose = htonl (
8100 .purpose.size = htonl (sizeof(ip)),
8101 .monotonic_time = sender_monotonic_time,
8102 .challenge = *challenge };
8103
8104 if (
8105 GNUNET_OK !=
8107 &ip,
8108 init_sig,
8109 &init->public_key))
8110 {
8111 GNUNET_break_op (0);
8112 return GNUNET_SYSERR;
8113 }
8114 return GNUNET_OK;
8115}
8116
8117
8122{
8127
8131 const struct DVPathEntryP *hops;
8132
8137
8142
8146 unsigned int num_eligible;
8147
8151 unsigned int num_selections;
8152
8156 uint16_t nhops;
8157
8161 uint16_t bi_history;
8162};
8163
8164
8173static int
8175 const struct GNUNET_PeerIdentity *pid,
8176 void *value)
8177{
8178 struct NeighbourSelectionContext *nsc = cls;
8179
8180 (void) value;
8181 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8182 return GNUNET_YES; /* skip initiator */
8183 for (unsigned int i = 0; i < nsc->nhops; i++)
8184 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8185 return GNUNET_YES;
8186 /* skip peers on path */
8187 nsc->num_eligible++;
8188 return GNUNET_YES;
8189}
8190
8191
8202static int
8204 const struct GNUNET_PeerIdentity *pid,
8205 void *value)
8206{
8207 struct NeighbourSelectionContext *nsc = cls;
8208
8210 "transmission %s\n",
8211 GNUNET_i2s (pid));
8212 (void) value;
8213 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8214 return GNUNET_YES; /* skip initiator */
8215 for (unsigned int i = 0; i < nsc->nhops; i++)
8216 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8217 return GNUNET_YES;
8218 /* skip peers on path */
8219 for (unsigned int i = 0; i < nsc->num_selections; i++)
8220 {
8221 if (nsc->selections[i] == nsc->num_eligible)
8222 {
8224 nsc->dvl,
8225 nsc->bi_history,
8226 nsc->nhops,
8227 nsc->hops,
8228 nsc->in_time);
8229 break;
8230 }
8231 }
8232 nsc->num_eligible++;
8233 return GNUNET_YES;
8234}
8235
8236
8280static unsigned int
8281calculate_fork_degree (unsigned int hops_taken,
8282 unsigned int neighbour_count,
8283 unsigned int eligible_count)
8284{
8285 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8286 double eligible_ratio =
8287 ((double) eligible_count) / ((double) neighbour_count);
8288 double boost_factor = eligible_ratio * eligible_ratio;
8289 unsigned int rnd;
8290 double left;
8291
8292 if (hops_taken >= 64)
8293 {
8294 GNUNET_break (0);
8295 return 0; /* precaution given bitshift below */
8296 }
8297 for (unsigned int i = 1; i < hops_taken; i++)
8298 {
8299 /* For each hop, subtract the expected number of targets
8300 reached at distance d (so what remains divided by 2^d) */
8301 target_total -= (target_total * boost_factor / (1LLU << i));
8302 }
8303 rnd =
8304 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8305 /* round up or down probabilistically depending on how close we were
8306 when floor()ing to rnd */
8307 left = target_total - (double) rnd;
8308 if (UINT32_MAX * left >
8310 rnd++; /* round up */
8312 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8313 hops_taken,
8314 rnd,
8315 eligible_count,
8316 neighbour_count);
8317 return rnd;
8318}
8319
8320
8327static void
8328neighbour_store_dvmono_cb (void *cls, int success)
8329{
8330 struct Neighbour *n = cls;
8331
8332 n->sc = NULL;
8333 if (GNUNET_YES != success)
8335 "Failed to store other peer's monotonic time in peerstore!\n");
8336}
8337
8338
8339static struct GNUNET_TIME_Relative
8341{
8342 struct GNUNET_TIME_Relative host_latency_sum;
8343 struct GNUNET_TIME_Relative latency;
8344 struct GNUNET_TIME_Relative network_latency;
8345 uint16_t nhops = ntohs (dvl->num_hops);;
8346
8347 /* We initiated this, learn the forward path! */
8348 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8349
8350 // Need also something to lookup initiation time
8351 // to compute RTT! -> add RTT argument here?
8353 dvl->monotonic_time));
8354 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8355 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8356 // (based on dvl->challenge, we can identify time of origin!)
8357
8358 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8359 /* assumption: latency on all links is the same */
8360 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8361
8362 return network_latency;
8363}
8364
8365
8373static void
8374handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8375{
8376 struct CommunicatorMessageContext *cmc = cls;
8378 int bi_hop;
8379 uint16_t nhops;
8380 uint16_t bi_history;
8381 const struct DVPathEntryP *hops;
8382 int do_fwd;
8383 int did_initiator;
8384 struct GNUNET_TIME_Absolute in_time;
8385 struct Neighbour *n;
8386
8387 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8388 bi_history = ntohs (dvl->bidirectional);
8389 hops = (const struct DVPathEntryP *) &dvl[1];
8390 if (0 == nhops)
8391 {
8392 /* sanity check */
8393 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8394 {
8395 GNUNET_break (0);
8396 finish_cmc_handling (cmc);
8397 return;
8398 }
8399 }
8400 else
8401 {
8403 "handle dv learn message last hop %s\n",
8404 GNUNET_i2s (&hops[nhops - 1].hop));
8405 /* sanity check */
8406 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8407 {
8408 GNUNET_break (0);
8409 finish_cmc_handling (cmc);
8410 return;
8411 }
8412 }
8413
8415 cc = cmc->tc->details.communicator.cc;
8416 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8417 cc); // FIXME: add bi-directional flag to cc?
8418 in_time = GNUNET_TIME_absolute_get ();
8419
8420 /* continue communicator here, everything else can happen asynchronous! */
8421 finish_cmc_handling (cmc);
8422
8423 n = lookup_neighbour (&dvl->initiator);
8424 if (NULL != n)
8425 {
8426 if ((n->dv_monotime_available == GNUNET_YES) &&
8429 {
8431 "DV learn from %s discarded due to time travel",
8432 GNUNET_i2s (&dvl->initiator));
8434 "# DV learn discarded due to time travel",
8435 1,
8436 GNUNET_NO);
8437 return;
8438 }
8440 &dvl->initiator,
8441 &dvl->challenge,
8442 &dvl->init_sig))
8443 {
8445 "DV learn signature from %s invalid\n",
8446 GNUNET_i2s (&dvl->initiator));
8447 GNUNET_break_op (0);
8448 return;
8449 }
8452 {
8453 if (NULL != n->sc)
8454 {
8456 "store cancel\n");
8458 }
8459 n->sc =
8461 "transport",
8462 &dvl->initiator,
8464 &dvl->monotonic_time,
8465 sizeof(dvl->monotonic_time),
8469 n);
8470 }
8471 }
8472 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8473 If signature verification load too high, implement random drop strategy */
8474 for (unsigned int i = 0; i < nhops; i++)
8475 {
8476 struct DvHopPS dhp = { .purpose.purpose =
8478 .purpose.size = htonl (sizeof(dhp)),
8479 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8480 .succ = (nhops == i + 1) ? *GST_my_identity
8481 : hops[i + 1].hop,
8482 .challenge = dvl->challenge };
8483
8484 if (GNUNET_OK !=
8486 &dhp,
8487 &hops[i].hop_sig,
8488 &hops[i].hop.public_key))
8489 {
8491 "DV learn from %s signature of hop %u invalid\n",
8492 GNUNET_i2s (&dvl->initiator),
8493 i);
8495 "signature of hop %s invalid\n",
8496 GNUNET_i2s (&hops[i].hop));
8498 "pred %s\n",
8499 GNUNET_i2s (&dhp.pred));
8501 "succ %s\n",
8502 GNUNET_i2s (&dhp.succ));
8504 "hash %s\n",
8505 GNUNET_sh2s (&dhp.challenge.value));
8506 GNUNET_break_op (0);
8507 return;
8508 }
8509 }
8510 if (GNUNET_EXTRA_LOGGING > 0)
8511 {
8512 char *path;
8513
8514 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8515 for (unsigned int i = 0; i < nhops; i++)
8516 {
8517 char *tmp;
8518
8519 GNUNET_asprintf (&tmp,
8520 "%s%s%s",
8521 path,
8522 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8523 GNUNET_i2s (&hops[i].hop));
8524 GNUNET_free (path);
8525 path = tmp;
8526 }
8528 "Received DVInit via %s%s%s\n",
8529 path,
8530 bi_hop ? "<->" : "-->",
8532 GNUNET_free (path);
8533 }
8534 do_fwd = GNUNET_YES;
8535 if (0 == GNUNET_memcmp (GST_my_identity, &dvl->initiator))
8536 {
8537 struct GNUNET_PeerIdentity path[nhops + 1];
8538 struct GNUNET_TIME_Relative network_latency;
8539
8540 /* We initiated this, learn the forward path! */
8541 path[0] = *GST_my_identity;
8542 path[1] = hops[0].hop;
8543
8544 network_latency = get_network_latency (dvl);
8545
8546 for (unsigned int i = 2; i <= nhops; i++)
8547 {
8548 struct GNUNET_TIME_Relative ilat;
8549
8550 /* assumption: linear latency increase per hop */
8551 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8552 path[i] = hops[i - 1].hop;
8554 "Learned path with %u hops to %s with latency %s\n",
8555 i,
8556 GNUNET_i2s (&path[i]),
8558 learn_dv_path (path,
8559 i + 1,
8560 ilat,
8563 }
8564 /* as we initiated, do not forward again (would be circular!) */
8565 do_fwd = GNUNET_NO;
8566 return;
8567 }
8568 if (bi_hop)
8569 {
8570 /* last hop was bi-directional, we could learn something here! */
8571 struct GNUNET_PeerIdentity path[nhops + 2];
8572 struct GNUNET_TIME_Relative ilat;
8573 struct GNUNET_TIME_Relative network_latency;
8574
8575 path[0] = *GST_my_identity;
8576 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8577 for (unsigned int i = 0; i < nhops; i++)
8578 {
8579 int iret;
8580
8581 if (0 == (bi_history & (1 << i)))
8582 break; /* i-th hop not bi-directional, stop learning! */
8583 if (i == nhops - 1)
8584 {
8585 path[i + 2] = dvl->initiator;
8586 }
8587 else
8588 {
8589 path[i + 2] = hops[nhops - i - 2].hop;
8590 }
8591
8593 "Learned inverse path with %u hops to %s\n",
8594 i + 2,
8595 GNUNET_i2s (&path[i + 2]));
8596 network_latency = get_network_latency (dvl);
8597 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8598 iret = learn_dv_path (path,
8599 i + 3,
8600 ilat,
8603 if (GNUNET_SYSERR == iret)
8604 {
8605 /* path invalid or too long to be interesting for US, thus should also
8606 not be interesting to our neighbours, cut path when forwarding to
8607 'i' hops, except of course for the one that goes back to the
8608 initiator */
8610 "# DV learn not forwarded due invalidity of path",
8611 1,
8612 GNUNET_NO);
8613 do_fwd = GNUNET_NO;
8614 break;
8615 }
8616 if ((GNUNET_NO == iret) && (nhops == i + 1))
8617 {
8618 /* we have better paths, and this is the longest target,
8619 so there cannot be anything interesting later */
8621 "# DV learn not forwarded, got better paths",
8622 1,
8623 GNUNET_NO);
8624 do_fwd = GNUNET_NO;
8625 break;
8626 }
8627 }
8628 }
8629 if (MAX_DV_HOPS_ALLOWED == nhops)
8630 {
8631 /* At limit, we're out of here! */
8632 return;
8633 }
8634
8635 /* Forward to initiator, if path non-trivial and possible */
8636 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8637 did_initiator = GNUNET_NO;
8638 if ((1 <= nhops) &&
8639 (GNUNET_YES ==
8641 {
8642 /* send back to origin! */
8644 "Sending DVL back to initiator %s\n",
8645 GNUNET_i2s (&dvl->initiator));
8646 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8647 did_initiator = GNUNET_YES;
8648 }
8649 /* We forward under two conditions: either we still learned something
8650 ourselves (do_fwd), or the path was darn short and thus the initiator is
8651 likely to still be very interested in this (and we did NOT already
8652 send it back to the initiator) */
8653 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8654 (GNUNET_NO == did_initiator)))
8655 {
8656 /* Pick random neighbours that are not yet on the path */
8657 struct NeighbourSelectionContext nsc;
8658 unsigned int n_cnt;
8659
8661 nsc.nhops = nhops;
8662 nsc.dvl = dvl;
8663 nsc.bi_history = bi_history;
8664 nsc.hops = hops;
8665 nsc.in_time = in_time;
8666 nsc.num_eligible = 0;
8669 &nsc);
8670 if (0 == nsc.num_eligible)
8671 return; /* done here, cannot forward to anyone else */
8673 nsc.num_selections =
8676 "Forwarding DVL to %u other peers\n",
8677 nsc.num_selections);
8678 for (unsigned int i = 0; i < nsc.num_selections; i++)
8679 nsc.selections[i] =
8680 (nsc.num_selections == n_cnt)
8681 ? i /* all were selected, avoid collisions by chance */
8683 nsc.num_eligible = 0;
8686 &nsc);
8687 }
8688}
8689
8690
8698static int
8699check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8700{
8701 uint16_t size = ntohs (dvb->header.size);
8702 uint16_t num_hops = ntohs (dvb->num_hops);
8703 const struct GNUNET_PeerIdentity *hops =
8704 (const struct GNUNET_PeerIdentity *) &dvb[1];
8705
8706 (void) cls;
8707 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8708 + sizeof(struct GNUNET_MessageHeader))
8709 {
8710 GNUNET_break_op (0);
8711 return GNUNET_SYSERR;
8712 }
8713 /* This peer must not be on the path */
8714 for (unsigned int i = 0; i < num_hops; i++)
8715 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
8716 {
8717 GNUNET_break_op (0);
8718 return GNUNET_SYSERR;
8719 }
8720 return GNUNET_YES;
8721}
8722
8723
8736static void
8737forward_dv_box (struct Neighbour *next_hop,
8738 struct TransportDVBoxMessage *hdr,
8739 uint16_t total_hops,
8740 uint16_t num_hops,
8741 const struct GNUNET_PeerIdentity *hops,
8742 const void *enc_payload,
8743 uint16_t enc_payload_size)
8744{
8745 struct VirtualLink *vl = next_hop->vl;
8746 struct PendingMessage *pm;
8747 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8748 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8749 + enc_payload_size;
8750 char *buf;
8751 char msg_buf[msg_size] GNUNET_ALIGN;
8752 struct GNUNET_PeerIdentity *dhops;
8753
8754 hdr->num_hops = htons (num_hops);
8755 hdr->total_hops = htons (total_hops);
8756 hdr->header.size = htons (msg_size);
8757 memcpy (msg_buf, hdr, sizeof(*hdr));
8758 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8760 ;
8761 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8762 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8763
8764 if (GNUNET_YES == ntohs (hdr->without_fc))
8765 {
8767 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8768 enc_payload_size,
8769 GNUNET_i2s (&next_hop->pid),
8770 (unsigned int) num_hops,
8771 (unsigned int) total_hops);
8772 route_via_neighbour (next_hop, (const struct
8773 GNUNET_MessageHeader *) msg_buf,
8775 }
8776 else
8777 {
8778 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8780 "2 created pm %p storing vl %p \n",
8781 pm,
8782 vl);
8783 pm->pmt = PMT_DV_BOX;
8784 pm->vl = vl;
8785 pm->target = next_hop->pid;
8787 pm->logging_uuid = logging_uuid_gen++;
8789 pm->bytes_msg = msg_size;
8790 buf = (char *) &pm[1];
8791 memcpy (buf, msg_buf, msg_size);
8792
8794 "Created pending message %" PRIu64
8795 " for DV Box with next hop %s (%u/%u)\n",
8796 pm->logging_uuid,
8797 GNUNET_i2s (&next_hop->pid),
8798 (unsigned int) num_hops,
8799 (unsigned int) total_hops);
8800
8801 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8802 {
8804 vl->pending_msg_head,
8805 vl->pending_msg_tail,
8806 pm);
8807
8809 }
8810 else
8811 {
8813 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8814
8816 {
8818
8819 GNUNET_free (pm_old);
8820 }
8823 {
8826 }
8827 else
8829
8831 "%u items stored in DV ring buffer\n",
8834 }
8835 }
8836}
8837
8838
8844static void
8846{
8847 if (NULL != b->get)
8848 {
8850 b->get = NULL;
8851 GNUNET_assert (NULL != b->cmc);
8853 b->cmc = NULL;
8854 }
8855 if (NULL != b->task)
8856 {
8858 b->task = NULL;
8859 }
8860 if (NULL != b->sc)
8861 {
8863 "store cancel\n");
8865 b->sc = NULL;
8866 }
8868 "Removing backtalker for %s\n",
8869 GNUNET_i2s (&b->pid));
8871 GNUNET_YES ==
8873 GNUNET_free (b);
8874}
8875
8876
8885static int
8887 const struct GNUNET_PeerIdentity *pid,
8888 void *value)
8889{
8890 struct Backtalker *b = value;
8891
8892 (void) cls;
8893 (void) pid;
8894 free_backtalker (b);
8895 return GNUNET_OK;
8896}
8897
8898
8904static void
8906{
8907 struct Backtalker *b = cls;
8908
8910 "backtalker timeout.\n");
8911 b->task = NULL;
8913 {
8915 return;
8916 }
8917 GNUNET_assert (NULL == b->sc);
8918 free_backtalker (b);
8919}
8920
8921
8930static void
8932 const struct GNUNET_PEERSTORE_Record *record,
8933 const char *emsg)
8934{
8935 struct Backtalker *b = cls;
8936 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8937 struct GNUNET_TIME_Absolute mt;
8938
8939 (void) emsg;
8940 if (NULL == record)
8941 {
8942 /* we're done with #backtalker_monotime_cb() invocations,
8943 continue normal processing */
8944 b->get = NULL;
8945 GNUNET_assert (NULL != b->cmc);
8946 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8947 if (0 != b->body_size)
8949 else
8951 b->cmc = NULL;
8952 return;
8953 }
8954 if (sizeof(*mtbe) != record->value_size)
8955 {
8957 GNUNET_break (0);
8958 return;
8959 }
8960 mtbe = record->value;
8961 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8963 {
8965 "Backtalker message from %s dropped, monotime in the past\n",
8966 GNUNET_i2s (&b->pid));
8968 GST_stats,
8969 "# Backchannel messages dropped: monotonic time not increasing",
8970 1,
8971 GNUNET_NO);
8972 b->monotonic_time = mt;
8973 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8974 */
8975 b->body_size = 0;
8976 }
8978}
8979
8980
8988static void
8989backtalker_monotime_store_cb (void *cls, int success)
8990{
8991 struct Backtalker *b = cls;
8992
8993 if (GNUNET_OK != success)
8994 {
8996 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8997 }
8998 b->sc = NULL;
8999 if (NULL != b->task)
9000 {
9002 b->task = NULL;
9003 }
9005}
9006
9007
9013static void
9015{
9016 struct GNUNET_TIME_AbsoluteNBO mtbe;
9017
9018 if (NULL != b->sc)
9019 {
9021 "store cancel before store with sc %p\n",
9022 b->sc);
9023 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9024 b->sc = NULL;*/
9026 "store cancel before store with sc %p is null\n",
9027 b->sc);
9028 }
9029 else
9030 {
9032 b->task = NULL;
9033 }
9035 b->sc =
9037 "transport",
9038 &b->pid,
9040 &mtbe,
9041 sizeof(mtbe),
9045 b);
9046}
9047
9048
9055
9056
9057static void
9058decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
9059{
9060 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
9061 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
9062 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
9063 struct DVKeyState key;
9064 const char *hdr;
9065 size_t hdr_len;
9066 struct GNUNET_HashCode hmac;
9067
9068 decaps_dv_box_cls->pr->op = NULL;
9071 decaps_dv_box_cls->pr);
9072 GNUNET_free (decaps_dv_box_cls->pr);
9073 if (NULL == km)
9074 {
9075 GNUNET_break_op (0);
9076 finish_cmc_handling (cmc);
9077 return;
9078 }
9079 dv_setup_key_state_from_km (km, &dvb->iv, &key);
9080 hdr = (const char *) &dvb[1];
9081 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
9083 * ntohs (dvb->total_hops);
9084
9085 dv_hmac (&key, &hmac, hdr, hdr_len);
9086 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
9087 {
9088 /* HMAC mismatch, discard! */
9089 GNUNET_break_op (0);
9090 finish_cmc_handling (cmc);
9091 return;
9092 }
9093 /* begin actual decryption */
9094 {
9095 struct Backtalker *b;
9096 struct GNUNET_TIME_Absolute monotime;
9097 struct TransportDVBoxPayloadP ppay = { 0 };
9098 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
9099 const struct GNUNET_MessageHeader *mh;
9100
9101 GNUNET_assert (hdr_len >=
9102 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
9103 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
9104 {
9106 "Error decrypting DV payload header\n");
9107 GNUNET_break_op (0);
9108 finish_cmc_handling (cmc);
9109 return;
9110 }
9111 if (GNUNET_OK != dv_decrypt (&key, body,
9112 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
9113 {
9115 "Error decrypting DV payload\n");
9116 GNUNET_break_op (0);
9117 finish_cmc_handling (cmc);
9118 return;
9119 }
9120 mh = (const struct GNUNET_MessageHeader *) body;
9121 dv_key_clean (&key);
9122 if (ntohs (mh->size) != sizeof(body))
9123 {
9124 GNUNET_break_op (0);
9125 finish_cmc_handling (cmc);
9126 return;
9127 }
9128 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9129 switch (ntohs (mh->type))
9130 {
9132 GNUNET_break_op (0);
9133 finish_cmc_handling (cmc);
9134 return;
9135
9137 GNUNET_break_op (0);
9138 finish_cmc_handling (cmc);
9139 return;
9140
9141 default:
9142 /* permitted, continue */
9143 break;
9144 }
9145 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
9147 "Decrypted backtalk from %s\n",
9148 GNUNET_i2s (&ppay.sender));
9150 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9151 {
9153 GST_stats,
9154 "# Backchannel messages dropped: monotonic time not increasing",
9155 1,
9156 GNUNET_NO);
9157 finish_cmc_handling (cmc);
9158 return;
9159 }
9160 if ((NULL == b) ||
9161 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9162 {
9163 /* Check signature */
9164 struct EphemeralConfirmationPS ec;
9165
9167 ec.target = *GST_my_identity;
9168 ec.ephemeral_key = dvb->ephemeral_key;
9169 ec.purpose.size = htonl (sizeof(ec));
9171 if (
9172 GNUNET_OK !=
9175 &ec,
9176 &ppay.sender_sig,
9177 &ppay.sender.public_key))
9178 {
9179 /* Signature invalid, discard! */
9180 GNUNET_break_op (0);
9181 finish_cmc_handling (cmc);
9182 return;
9183 }
9184 }
9185 /* Update sender, we now know the real origin! */
9187 "DVBox received for me from %s via %s\n",
9188 GNUNET_i2s2 (&ppay.sender),
9189 GNUNET_i2s (&cmc->im.sender));
9190 cmc->im.sender = ppay.sender;
9191
9192 if (NULL != b)
9193 {
9194 /* update key cache and mono time */
9195 b->last_ephemeral = dvb->ephemeral_key;
9196 b->monotonic_time = monotime;
9198 b->timeout =
9200 cmc->mh = mh;
9202 return;
9203 }
9204 /* setup data structure to cache signature AND check
9205 monotonic time with PEERSTORE before forwarding backchannel payload */
9206 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
9207 b->pid = ppay.sender;
9208 b->body_size = sizeof(body);
9209 memcpy (&b[1], body, sizeof(body));
9213 &b->pid,
9214 b,
9216 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9217 b->cmc = cmc;
9218 b->timeout =
9221 b->get =
9223 "transport",
9224 &b->pid,
9227 b);
9228 } /* end actual decryption */
9229}
9230
9231
9239static void
9240handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9241{
9242 struct CommunicatorMessageContext *cmc = cls;
9243 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9244 uint16_t num_hops = ntohs (dvb->num_hops);
9245 const struct GNUNET_PeerIdentity *hops =
9246 (const struct GNUNET_PeerIdentity *) &dvb[1];
9247 const char *enc_payload = (const char *) &hops[num_hops];
9248 uint16_t enc_payload_size =
9249 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9250 struct DecapsDvBoxCls *decaps_dv_box_cls;
9251
9252 if (GNUNET_EXTRA_LOGGING > 0)
9253 {
9254 char *path;
9255
9257 for (unsigned int i = 0; i < num_hops; i++)
9258 {
9259 char *tmp;
9260
9261 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9262 GNUNET_free (path);
9263 path = tmp;
9264 }
9266 "Received DVBox with remaining path %s\n",
9267 path);
9268 GNUNET_free (path);
9269 }
9270
9271 if (num_hops > 0)
9272 {
9273 /* We're trying from the end of the hops array, as we may be
9274 able to find a shortcut unknown to the origin that way */
9275 for (int i = num_hops - 1; i >= 0; i--)
9276 {
9277 struct Neighbour *n;
9278
9279 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
9280 {
9281 GNUNET_break_op (0);
9282 finish_cmc_handling (cmc);
9283 return;
9284 }
9285 n = lookup_neighbour (&hops[i]);
9286 if (NULL == n)
9287 continue;
9289 "Skipping %u/%u hops ahead while routing DV Box\n",
9290 i,
9291 num_hops);
9292
9293 forward_dv_box (n,
9294 (struct TransportDVBoxMessage *) dvb,
9295 ntohs (dvb->total_hops) + 1,
9296 num_hops - i - 1, /* number of hops left */
9297 &hops[i + 1], /* remaining hops */
9298 enc_payload,
9299 enc_payload_size);
9301 "# DV hops skipped routing boxes",
9302 i,
9303 GNUNET_NO);
9305 "# DV boxes routed (total)",
9306 1,
9307 GNUNET_NO);
9308 finish_cmc_handling (cmc);
9309 return;
9310 }
9311 /* Woopsie, next hop not in neighbours, drop! */
9313 "# DV Boxes dropped: next hop unknown",
9314 1,
9315 GNUNET_NO);
9316 finish_cmc_handling (cmc);
9317 return;
9318 }
9319 /* We are the target. Unbox and handle message. */
9321 "# DV boxes opened (ultimate target)",
9322 1,
9323 GNUNET_NO);
9324 cmc->total_hops = ntohs (dvb->total_hops);
9325
9326 {
9327 // DH key derivation with received DV, could be garbage.
9328 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9329 decaps_dv_box_cls->cmc = cmc;
9330 decaps_dv_box_cls->dvb = dvb;
9331 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9332
9335 decaps_dv_box_cls->pr);
9336 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9337 &dvb->ephemeral_key,
9339 decaps_dv_box_cls);
9340 }
9341 // TODO keep track of cls and potentially clean
9342}
9343
9344
9352static int
9354 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9355{
9356 struct TransportClient *tc = cls;
9357
9358 if (CT_COMMUNICATOR != tc->type)
9359 {
9360 GNUNET_break (0);
9361 return GNUNET_SYSERR;
9362 }
9364 return GNUNET_OK;
9365}
9366
9367
9372{
9376 const char *address;
9377
9382};
9383
9384
9394static int
9396 const struct GNUNET_PeerIdentity *pid,
9397 void *value)
9398{
9399 struct CheckKnownAddressContext *ckac = cls;
9400 struct ValidationState *vs = value;
9401
9402 (void) pid;
9403 if (0 != strcmp (vs->address, ckac->address))
9404 return GNUNET_OK;
9405 ckac->vs = vs;
9406 return GNUNET_NO;
9407}
9408
9409
9415static void
9416validation_start_cb (void *cls);
9417
9418
9426static void
9428 struct GNUNET_TIME_Absolute new_time)
9429{
9431
9432 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9433 return; /* be lazy */
9434 vs->next_challenge = new_time;
9435 if (NULL == vs->hn)
9436 vs->hn =
9438 else
9441 (NULL != validation_task))
9442 return;
9443 if (NULL != validation_task)
9445 /* randomize a bit */
9448 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9449 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9452}
9453
9454
9461static void
9463 const char *address)
9464{
9465 struct GNUNET_TIME_Absolute now;
9466 struct ValidationState *vs;
9467 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9468
9470 pid,
9472 &ckac);
9473 if (NULL != (vs = ckac.vs))
9474 {
9475 /* if 'vs' is not currently valid, we need to speed up retrying the
9476 * validation */
9477 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9478 {
9479 /* reduce backoff as we got a fresh advertisement */
9480 vs->challenge_backoff =
9483 vs->challenge_backoff,
9484 2));
9487 vs->challenge_backoff));
9488 }
9489 return;
9490 }
9492 vs = GNUNET_new (struct ValidationState);
9493 vs->pid = *pid;
9494 vs->valid_until =
9496 vs->first_challenge_use = now;
9497 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9499 &vs->challenge,
9500 sizeof(vs->challenge));
9501 vs->address = GNUNET_strdup (address);
9502 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9504 "Starting address validation `%s' of peer %s using challenge %s\n",
9505 address,
9506 GNUNET_i2s (pid),
9507 GNUNET_sh2s (&vs->challenge.value));
9511 &vs->pid,
9512 vs,
9515}
9516
9517
9518static struct Queue *
9519find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9520
9521
9522static void
9523suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9524
9525
9526static void
9528 const struct GNUNET_PeerIdentity *pid,
9529 const char *uri)
9530{
9531 struct Queue *q;
9532 int pfx_len;
9533 const char *eou;
9534 char *address;
9535 (void) cls;
9536
9537 eou = strstr (uri,
9538 "://");
9539 pfx_len = eou - uri;
9540 eou += 3;
9542 "%.*s-%s",
9543 pfx_len,
9544 uri,
9545 eou);
9546
9548 "helo for client %s\n",
9549 address);
9550 q = find_queue (pid, address);
9551 if (NULL == q)
9552 {
9554 }
9555 else
9558}
9559
9560
9568static void
9570 const struct GNUNET_PEERSTORE_Record *record,
9571 const char *emsg)
9572{
9573 struct IncomingRequest *ir = cls;
9574 struct GNUNET_HELLO_Parser *parser;
9575 struct GNUNET_MessageHeader *hello;
9576
9577 if (NULL != emsg)
9578 {
9580 "Got failure from PEERSTORE: %s\n",
9581 emsg);
9582 return;
9583 }
9584 hello = record->value;
9585 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
9586 {
9588 return;
9589 }
9590 parser = GNUNET_HELLO_parser_from_msg (hello);
9593 NULL);
9594 GNUNET_HELLO_parser_free (parser);
9595}
9596
9597
9598static void
9600{
9602 "Error in PEERSTORE monitoring\n");
9603}
9604
9605
9606static void
9608{
9610 "Done with initial PEERSTORE iteration during monitoring\n");
9611}
9612
9613
9620
9621
9622static void
9624 const struct GNUNET_PeerIdentity *pid,
9625 const struct GNUNET_CRYPTO_EddsaSignature *sig)
9626{
9627 struct SignTValidationCls *sign_t_validation_cls = cls;
9628 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9629 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9630 struct VirtualLink *vl;
9631 struct Neighbour *n;
9632 struct IncomingRequest *ir;
9633 struct GNUNET_PeerIdentity sender;
9634
9635 sign_t_validation_cls->pr->op = NULL;
9638 sign_t_validation_cls->pr);
9639 GNUNET_free (sign_t_validation_cls->pr);
9640 tvr.signature = *sig;
9641 sender = cmc->im.sender;
9642 vl = lookup_virtual_link (&sender);
9643 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9644 {
9645 // route_control_message_without_fc (&cmc->im.sender,
9647 &tvr.header,
9649 }
9650 else
9651 {
9652 /* Use route via neighbour */
9653 n = lookup_neighbour (&sender);
9654 if (NULL != n)
9655 route_via_neighbour (n, &tvr.header,
9658 }
9659
9660 finish_cmc_handling (cmc);
9661 if (NULL != vl)
9662 return;
9663
9664 /* For us, the link is still down, but we need bi-directional
9665 connections (for flow-control and for this to be useful for
9666 CORE), so we must try to bring the link up! */
9667
9668 /* (1) Check existing queues, if any, we may be lucky! */
9669 n = lookup_neighbour (&sender);
9670 if (NULL != n)
9671 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9672 start_address_validation (&sender, q->address);
9673 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9674 we could use */
9675 for (ir = ir_head; NULL != ir; ir = ir->next)
9676 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9677 return;
9678 /* we are already trying */
9679 ir = GNUNET_new (struct IncomingRequest);
9680 ir->pid = sender;
9682
9684 GNUNET_YES,
9685 "peerstore",
9686 NULL,
9689 NULL,
9691 NULL,
9693 ir);
9694 ir_total++;
9695 /* Bound attempts we do in parallel here, might otherwise get excessive */
9698};
9699
9700
9709static void
9711 void *cls,
9712 const struct TransportValidationChallengeMessage *tvc)
9713{
9714 struct CommunicatorMessageContext *cmc = cls;
9715 struct TransportValidationResponseMessage tvr = { 0 };
9716 struct GNUNET_TIME_RelativeNBO validity_duration;
9717
9718 /* DV-routed messages are not allowed for validation challenges */
9719 if (cmc->total_hops > 0)
9720 {
9721 GNUNET_break_op (0);
9722 finish_cmc_handling (cmc);
9723 return;
9724 }
9725 validity_duration = cmc->im.expected_address_validity;
9727 "Received address validation challenge %s\n",
9728 GNUNET_sh2s (&tvc->challenge.value));
9729 /* If we have a virtual link, we use this mechanism to signal the
9730 size of the flow control window, and to allow the sender
9731 to ask for increases. If for us the virtual link is still down,
9732 we will always give a window size of zero. */
9733 tvr.header.type =
9735 tvr.header.size = htons (sizeof(tvr));
9736 tvr.reserved = htonl (0);
9737 tvr.challenge = tvc->challenge;
9738 tvr.origin_time = tvc->sender_time;
9739 tvr.validity_duration = validity_duration;
9740 {
9741 /* create signature */
9742 struct TransportValidationPS tvp = {
9744 .purpose.size = htonl (sizeof(tvp)),
9745 .validity_duration = validity_duration,
9746 .challenge = tvc->challenge
9747 };
9748 struct SignTValidationCls *sign_t_validation_cls;
9749
9750 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9751 sign_t_validation_cls->cmc = cmc;
9752 sign_t_validation_cls->tvr = tvr;
9753 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9756 sign_t_validation_cls->pr);
9757 sign_t_validation_cls->pr->op =
9759 &tvp.purpose,
9761 sign_t_validation_cls);
9762 }
9763}
9764
9765
9781
9782
9792static int
9794 const struct GNUNET_PeerIdentity *pid,
9795 void *value)
9796{
9797 struct CheckKnownChallengeContext *ckac = cls;
9798 struct ValidationState *vs = value;
9799
9800 (void) pid;
9801 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9802 return GNUNET_OK;
9803 ckac->vs = vs;
9804 return GNUNET_NO;
9805}
9806
9807
9815static void
9816peerstore_store_validation_cb (void *cls, int success)
9817{
9818 struct ValidationState *vs = cls;
9819
9820 vs->sc = NULL;
9821 if (GNUNET_YES == success)
9822 return;
9824 "# Peerstore failed to store foreign address",
9825 1,
9826 GNUNET_NO);
9827}
9828
9829
9837static struct Queue *
9838find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9839{
9840 struct Neighbour *n;
9841
9842 n = lookup_neighbour (pid);
9843 if (NULL == n)
9844 return NULL;
9845 for (struct Queue *pos = n->queue_head; NULL != pos;
9846 pos = pos->next_neighbour)
9847 {
9848 if (0 == strcmp (pos->address, address))
9849 return pos;
9850 }
9851 return NULL;
9852}
9853
9854
9855static void
9857
9858static void
9860{
9861 struct ValidationState *vs = cls;
9862 struct Queue *q;
9863 struct GNUNET_TIME_Absolute now;
9864
9865 vs->revalidation_task = NULL;
9866 q = find_queue (&vs->pid, vs->address);
9867 if (NULL == q)
9868 {
9869 now = GNUNET_TIME_absolute_get ();
9870 vs->awaiting_queue = GNUNET_YES;
9871 suggest_to_connect (&vs->pid, vs->address);
9873 }
9874 else
9876}
9877
9878
9879static enum GNUNET_GenericReturnValue
9881 void *cls,
9882 const struct GNUNET_HashCode *key,
9883 void *value)
9884{
9885 (void) cls;
9887 "Key in revalidate map %s \n",
9888 GNUNET_h2s (key));
9889 return GNUNET_YES;
9890}
9891
9892
9901static void
9903 void *cls,
9904 const struct TransportValidationResponseMessage *tvr)
9905{
9906 struct CommunicatorMessageContext *cmc = cls;
9907 struct ValidationState *vs;
9908 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9909 .vs = NULL};
9910 struct GNUNET_TIME_Absolute origin_time;
9911 struct Queue *q;
9912 struct Neighbour *n;
9913 struct VirtualLink *vl;
9915 GST_cfg);
9916
9917 /* check this is one of our challenges */
9919 &cmc->im.sender,
9921 &ckac);
9922 if (NULL == (vs = ckac.vs))
9923 {
9924 /* This can happen simply if we 'forgot' the challenge by now,
9925 i.e. because we received the validation response twice */
9927 "# Validations dropped, challenge unknown",
9928 1,
9929 GNUNET_NO);
9931 "Validation response %s dropped, challenge unknown\n",
9932 GNUNET_sh2s (&tvr->challenge.value));
9933 finish_cmc_handling (cmc);
9934 return;
9935 }
9936
9937 /* sanity check on origin time */
9938 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9939 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9940 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9941 {
9943 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9944 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9945 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9946 GNUNET_break_op (0);
9947 finish_cmc_handling (cmc);
9948 return;
9949 }
9950
9951 {
9952 /* check signature */
9953 struct TransportValidationPS tvp = {
9955 .purpose.size = htonl (sizeof(tvp)),
9956 .validity_duration = tvr->validity_duration,
9957 .challenge = tvr->challenge
9958 };
9959
9960 if (
9961 GNUNET_OK !=
9963 &tvp,
9964 &tvr->signature,
9965 &cmc->im.sender.public_key))
9966 {
9967 GNUNET_break_op (0);
9968 finish_cmc_handling (cmc);
9969 return;
9970 }
9971 }
9972
9973 /* validity is capped by our willingness to keep track of the
9974 validation entry and the maximum the other peer allows */
9977 tvr->validity_duration),
9979 vs->validated_until =
9983 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9984 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9986 &vs->challenge,
9987 sizeof(vs->challenge));
9988 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9989 vs->validated_until,
9990 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9992 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9993 {
9995 "First challenge use is now %" PRIu64 " %s \n",
9996 vs->first_challenge_use.abs_value_us,
9997 GNUNET_sh2s (&vs->challenge.value));
9998 vs->first_challenge_use = now;
9999 }
10000 else
10002 "First challenge use is later %" PRIu64 " %s \n",
10003 vs->first_challenge_use.abs_value_us,
10004 GNUNET_sh2s (&vs->challenge.value));
10005 vs->last_challenge_use =
10006 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10007 update_next_challenge_time (vs, vs->first_challenge_use);
10009 "Validation response %s from %s accepted, address valid until %s\n",
10010 GNUNET_sh2s (&tvr->challenge.value),
10011 GNUNET_i2s (&cmc->im.sender),
10013 /*memcpy (&hkey,
10014 &hc,
10015 sizeof (hkey));*/
10017 "Key %s for address %s map size %u contains %u\n",
10018 GNUNET_h2s (&vs->hc),
10019 vs->address,
10022 &vs->hc));
10026 &vs->hc,
10027 vs,
10031 NULL);
10032 vs->revalidation_task =
10037 "transport",
10038 &cmc->im.sender,
10040 vs->address,
10041 strlen (vs->address) + 1,
10042 vs->valid_until,
10045 vs);
10046 finish_cmc_handling (cmc);
10047
10048 /* Finally, we now possibly have a confirmed (!) working queue,
10049 update queue status (if queue still is around) */
10050 q = find_queue (&vs->pid, vs->address);
10051 if (NULL == q)
10052 {
10054 "# Queues lost at time of successful validation",
10055 1,
10056 GNUNET_NO);
10057 return;
10058 }
10059 q->validated_until = vs->validated_until;
10060 q->pd.aged_rtt = vs->validation_rtt;
10061 n = q->neighbour;
10062 vl = lookup_virtual_link (&vs->pid);
10063 if (NULL == vl)
10064 {
10065 vl = GNUNET_new (struct VirtualLink);
10067 "Creating new virtual link %p to %s using direct neighbour!\n",
10068 vl,
10069 GNUNET_i2s (&vs->pid));
10070 vl->burst_addr = NULL;
10071 vl->confirmed = GNUNET_YES;
10072 vl->message_uuid_ctr =
10074 vl->target = n->pid;
10080 links,
10081 &vl->target,
10082 vl,
10084 vl->n = n;
10085 n->vl = vl;
10086 q->idle = GNUNET_YES;
10087 vl->visibility_task =
10088 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10090 /* We lacked a confirmed connection to the target
10091 before, so tell CORE about it (finally!) */
10094 }
10095 else
10096 {
10097 /* Link was already up, remember n is also now available and we are done */
10098 if (NULL == vl->n)
10099 {
10100 vl->n = n;
10101 n->vl = vl;
10102 if (GNUNET_YES == vl->confirmed)
10104 "Virtual link to %s could now also use direct neighbour!\n",
10105 GNUNET_i2s (&vs->pid));
10106 }
10107 else
10108 {
10109 GNUNET_assert (n == vl->n);
10110 }
10111 if (GNUNET_NO == vl->confirmed)
10112 {
10113 vl->confirmed = GNUNET_YES;
10114 q->idle = GNUNET_YES;
10115 vl->visibility_task =
10116 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10118 /* We lacked a confirmed connection to the target
10119 before, so tell CORE about it (finally!) */
10122 }
10123 }
10124}
10125
10126
10132static void
10134 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10135{
10136 struct TransportClient *tc = cls;
10137 struct CommunicatorMessageContext *cmc =
10139
10140 cmc->tc = tc;
10141 cmc->im = *im;
10143 "Received message with size %u and flow control id %" PRIu64
10144 " via communicator from peer %s\n",
10145 ntohs (im->header.size),
10146 im->fc_id,
10147 GNUNET_i2s (&im->sender));
10148 cmc->im.neighbour_sender = cmc->im.sender;
10149 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10151}
10152
10153
10162static int
10164{
10165 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10166 (void) cls;
10167
10169 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10170 ntohs (fc->header.size),
10171 ntohl (fc->size_of_addresses),
10172 ntohl (fc->number_of_addresses),
10173 sizeof(struct TransportFlowControlMessage),
10174 sizeof (struct TransportGlobalNattedAddress));
10175
10176 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10178 + ntohl (fc->number_of_addresses) * sizeof (struct
10180 + ntohl (fc->size_of_addresses))
10181 return GNUNET_OK;
10182 else
10183 {
10184 GNUNET_break_op (0);
10185 return GNUNET_SYSERR;
10186 }
10187}
10188
10189
10190static struct GNUNET_TIME_Relative
10192{
10194 unsigned int n_hops = 0;
10195
10197 "calculate_rtt\n");
10198 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10199 pos = pos->next_dv)
10200 {
10202 "calculate_rtt %lu\n",
10203 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10204 n_hops++;
10206 aged_rtt, pos
10207 ->distance
10208 + 2), ret);
10209 }
10210
10211 GNUNET_assert (0 != n_hops);
10212
10213 return ret;
10214}
10215
10216
10217static void
10219 const struct GNUNET_PeerIdentity *pid,
10220 const char *uri)
10221{
10222 struct VirtualLink *vl = cls;
10223 const char *slash;
10224 char *address_uri;
10225 char *prefix;
10226 char *uri_without_port;
10227
10228 slash = strrchr (uri, '/');
10229 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10230 GNUNET_assert (NULL != slash);
10231 slash++;
10232 GNUNET_asprintf (&address_uri,
10233 "%s-%s",
10234 prefix,
10235 slash);
10236
10237 uri_without_port = get_address_without_port (address_uri);
10239 "iterate_address_start_burst %s %s %s %s\n",
10240 uri_without_port,
10241 uri,
10242 address_uri,
10243 slash);
10244 if (0 == strcmp (uri_without_port, slash))
10245 {
10246 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10247 );
10248 }
10249 else
10250 vl->burst_addr = NULL;
10251
10253 GNUNET_free (uri_without_port);
10254}
10255
10256
10257static void
10259 const struct GNUNET_PEERSTORE_Record *record,
10260 const char *emsg)
10261{
10262 struct GNUNET_StartBurstCls *sb_cls = cls;
10263 struct VirtualLink *vl = sb_cls->vl;
10264 struct GNUNET_MessageHeader *hello;
10265 struct GNUNET_HELLO_Parser *parser;
10266
10267 if (NULL != emsg)
10268 {
10270 "Got failure from PEERSTORE: %s\n",
10271 emsg);
10272 return;
10273 }
10274 if (NULL == record)
10275 {
10277 "Hello iteration end for %s\n",
10278 GNUNET_i2s (&vl->target));
10279 vl->ic = NULL;
10280 GNUNET_free (sb_cls);
10281 return;
10282 }
10283
10285 "check_for_burst_address\n");
10286 hello = record->value;
10287 parser = GNUNET_HELLO_parser_from_msg (hello);
10290 vl);
10291 GNUNET_HELLO_parser_free (parser);
10292
10294 GNUNET_free (sb_cls);
10295}
10296
10297
10298static void
10299burst_timeout (void *cls)
10300{
10302}
10303
10304
10305static void
10306start_burst (void *cls)
10307{
10308 struct GNUNET_StartBurstCls *sb_cls = cls;
10309 struct VirtualLink *vl = sb_cls->vl;
10310 struct GNUNET_TRANSPORT_StartBurst *sb;
10311 struct GNUNET_MQ_Envelope *env;
10312 char *uri_without_port = vl->burst_addr;
10313
10314 burst_task = NULL;
10315 /*char buf[strlen (uri_without_port) + 1];
10316
10317 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10318 buf[strlen (uri_without_port)] = '\0';*/
10319 env =
10321 strlen (uri_without_port) + 1,
10323 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10324 sb->pid = vl->target;
10325 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10326 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10327 {
10329 "iterate_address_start_burst client tc prefix %s\n",
10330 tc->details.communicator.address_prefix);
10331 if (CT_COMMUNICATOR != tc->type)
10332 continue;
10333 if (GNUNET_YES == tc->details.communicator.can_burst)
10334 {
10336 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10337 uri_without_port,
10338 strlen (uri_without_port),
10339 ntohs (sb->header.size),
10340 (unsigned long) sb_cls->rtt.rel_value_us);
10341 GNUNET_MQ_send (tc->mq, env);
10345 60),
10347 NULL);
10348 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10349 break;
10350 }
10351 }
10352 GNUNET_free (env);
10353 GNUNET_free (sb_cls);
10354}
10355
10356
10357static void
10358queue_burst (void *cls)
10359{
10360 struct GNUNET_StartBurstCls *sb_cls = cls;
10361 struct VirtualLink *vl = sb_cls->vl;
10362
10363 if (GNUNET_YES != use_burst)
10364 return;
10366 "burst_task %p ready %s burst addr %s (%p)\n",
10367 burst_task,
10368 sb_cls->sync_ready ? "yes" : "no",
10369 vl->burst_addr,
10370 vl->burst_addr);
10371 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10372 {
10374 burst_task = NULL;
10376 return;
10377 }
10378 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10379 )
10380 {
10382 &start_burst,
10383 sb_cls);
10384 }
10385 else if (NULL == vl->burst_addr)
10386 {
10388 "peerstore",
10389 &vl->target,
10392 sb_cls);
10393 }
10394}
10395
10396
10405static void
10407{
10408 struct CommunicatorMessageContext *cmc = cls;
10409 struct VirtualLink *vl;
10411 uint32_t seq;
10412 struct GNUNET_TIME_Absolute st;
10413 uint64_t os;
10414 uint64_t wnd;
10415 uint32_t random;
10416
10418 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10419 vl = lookup_virtual_link (&cmc->im.sender);
10420 if (NULL == vl)
10421 {
10422 vl = GNUNET_new (struct VirtualLink);
10424 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10425 vl,
10426 GNUNET_i2s (&cmc->im.sender));
10427 vl->burst_addr = NULL;
10428 vl->confirmed = GNUNET_NO;
10429 vl->message_uuid_ctr =
10431 vl->target = cmc->im.sender;
10437 links,
10438 &vl->target,
10439 vl,
10441 }
10442 if (NULL != vl->n)
10443 {
10444 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10445 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10446 }
10447
10449 "remaining %lu timeout for neighbour %p\n",
10450 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10451 rel_value_us,
10452 vl->n);
10453 if (NULL == vl->n ||
10454 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10455 {
10456 struct GNUNET_TIME_Relative rtt;
10457 struct GNUNET_BurstSync burst_sync;
10458 struct GNUNET_StartBurstCls *bcls;
10459
10460 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10461 bcls->vl = vl;
10462 vl->sb_cls = bcls;
10463 if (NULL != vl->dv)
10464 rtt = calculate_rtt (vl->dv);
10465 else
10467 burst_sync.rtt_average = fc->rtt;
10468 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10469 burst_sync.sync_ready = fc->sync_ready;
10470
10472 &burst_sync,
10473 &queue_burst,
10474 bcls);
10475 }
10476 if (0 != ntohl (fc->number_of_addresses))
10477 {
10478 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10479 const char *tgnas;
10480 unsigned int off = 0;
10481
10482 tgnas = (const char *) &fc[1];
10483
10484 for (int i = 1; i <= number_of_addresses; i++)
10485 {
10486 struct TransportGlobalNattedAddress *tgna;
10487 char *addr;
10488 unsigned int address_length;
10489
10490 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10491 addr = (char *) &tgna[1];
10492 address_length = ntohl (tgna->address_length);
10493 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10494
10496 "received address %s length %u\n",
10497 addr,
10498 ntohl (tgna->address_length));
10499
10500 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10501 }
10502 }
10504 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10505 {
10507 "FC dropped: Message out of order\n");
10508 /* out of order, drop */
10510 "# FC dropped: message out of order",
10511 1,
10512 GNUNET_NO);
10513 finish_cmc_handling (cmc);
10514 return;
10515 }
10516 seq = ntohl (fc->seq);
10517 if (seq < vl->last_fc_seq)
10518 {
10519 /* Wrap-around/reset of other peer; start all counters from zero */
10521 }
10522 vl->last_fc_seq = seq;
10523 vl->last_fc_timestamp = st;
10525 os = GNUNET_ntohll (fc->outbound_sent);
10527 (int64_t) (os - vl->incoming_fc_window_size_used);
10529 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10530 GNUNET_i2s (&vl->target),
10531 (unsigned int) seq,
10532 (unsigned long long) vl->outbound_fc_window_size,
10533 (long long) vl->incoming_fc_window_size_loss);
10536 UINT32_MAX);
10537 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10541 != wnd) ||
10542 (0 == random
10544 {
10546 "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",
10547 (unsigned long long) wnd,
10548 (unsigned long long) vl->incoming_fc_window_size,
10549 (unsigned long long) vl->last_outbound_window_size_received,
10552 }
10553 if ((wnd == vl->incoming_fc_window_size
10557 (NULL != vl->fc_retransmit_task))
10558 {
10560 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10561 GNUNET_i2s (&vl->target),
10562 (unsigned long long) wnd);
10564 vl->fc_retransmit_task = NULL;
10565 vl->fc_retransmit_count = 0;
10566 }
10568 /* FC window likely increased, check transmission possibilities! */
10570 finish_cmc_handling (cmc);
10571}
10572
10573
10581static void
10583{
10585 { GNUNET_MQ_hd_var_size (fragment_box,
10588 cmc),
10589 GNUNET_MQ_hd_var_size (reliability_box,
10592 cmc),
10593 GNUNET_MQ_hd_var_size (reliability_ack,
10596 cmc),
10597 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10600 cmc),
10601 GNUNET_MQ_hd_var_size (dv_learn,
10604 cmc),
10605 GNUNET_MQ_hd_var_size (dv_box,
10607 struct TransportDVBoxMessage,
10608 cmc),
10609 GNUNET_MQ_hd_var_size (flow_control,
10612 cmc),
10614 validation_challenge,
10617 cmc),
10619 validation_response,
10622 cmc),
10624 int ret;
10625 const struct GNUNET_MessageHeader *msg = cmc->mh;
10626
10628 "Handling message of type %u with %u bytes\n",
10629 (unsigned int) ntohs (msg->type),
10630 (unsigned int) ntohs (msg->size));
10632 if (GNUNET_SYSERR == ret)
10633 {
10634 GNUNET_break (0);
10636 GNUNET_free (cmc);
10637 return;
10638 }
10639 if (GNUNET_NO == ret)
10640 {
10641 /* unencapsulated 'raw' message */
10642 handle_raw_message (cmc, msg);
10643 }
10644}
10645
10646
10653static int
10655 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10656{
10657 struct TransportClient *tc = cls;
10658
10659 if (CT_COMMUNICATOR != tc->type)
10660 {
10661 GNUNET_break (0);
10662 return GNUNET_SYSERR;
10663 }
10665 return GNUNET_OK;
10666}
10667
10668
10674static void
10676{
10677 if (pm->msg_uuid_set)
10678 return;
10679 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10680 pm->msg_uuid_set = GNUNET_YES;
10681}
10682
10683
10692static struct PendingAcknowledgement *
10694 struct DistanceVectorHop *dvh,
10695 struct PendingMessage *pm)
10696{
10697 struct PendingAcknowledgement *pa;
10698
10699 pa = GNUNET_new (struct PendingAcknowledgement);
10700 pa->queue = queue;
10701 pa->dvh = dvh;
10702 pa->pm = pm;
10703 do
10704 {
10706 &pa->ack_uuid,
10707 sizeof(pa->ack_uuid));
10708 }
10711 &pa->ack_uuid.value,
10712 pa,
10714 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10715 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10716 if (NULL != dvh)
10719 pa->message_size = pm->bytes_msg;
10721 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10723 pm->logging_uuid);
10724 return pa;
10725}
10726
10727
10739static struct PendingMessage *
10741 struct DistanceVectorHop *dvh,
10742 struct PendingMessage *pm)
10743{
10744 struct PendingAcknowledgement *pa;
10745 struct PendingMessage *ff;
10746 uint16_t mtu;
10747 uint16_t msize;
10748
10749 mtu = (UINT16_MAX == queue->mtu)
10750 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10751 : queue->mtu;
10753 "Fragmenting message <%" PRIu64
10754 "> with size %u to %s for MTU %u\n",
10755 pm->logging_uuid,
10756 pm->bytes_msg,
10757 GNUNET_i2s (&pm->vl->target),
10758 (unsigned int) mtu);
10761 "Fragmenting message %" PRIu64 " <%" PRIu64
10762 "> with size %u to %s for MTU %u\n",
10763 pm->msg_uuid.uuid,
10764 pm->logging_uuid,
10765 pm->bytes_msg,
10766 GNUNET_i2s (&pm->vl->target),
10767 (unsigned int) mtu);
10768
10769 /* This invariant is established in #handle_add_queue_message() */
10770 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10771
10772 /* select fragment for transmission, descending the tree if it has
10773 been expanded until we are at a leaf or at a fragment that is small
10774 enough
10775 */
10776 ff = pm;
10777 msize = ff->bytes_msg;
10778
10779 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10780 (ff->frag_off == msize) && (NULL != ff->head_frag))
10781 {
10782 ff = ff->head_frag; /* descent into fragmented fragments */
10783 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10784 }
10785
10786 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10787 {
10788 /* Did not yet calculate all fragments, calculate next fragment */
10789 struct PendingMessage *frag;
10790 struct TransportFragmentBoxMessage tfb;
10791 const char *orig;
10792 char *msg;
10793 uint16_t fragmax;
10794 uint16_t fragsize;
10795 uint16_t msize_ff;
10796 uint16_t xoff = 0;
10797 pm->frag_count++;
10798
10799 orig = (const char *) &ff[1];
10800 msize_ff = ff->bytes_msg;
10801 if (pm != ff)
10802 {
10803 const struct TransportFragmentBoxMessage *tfbo;
10804
10805 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10806 orig += sizeof(struct TransportFragmentBoxMessage);
10807 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10808 xoff = ntohs (tfbo->frag_off);
10809 }
10810 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10811 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10812 frag =
10813 GNUNET_malloc (sizeof(struct PendingMessage)
10814 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10816 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10817 frag,
10818 ff,
10819 pm->vl,
10820 pm);
10822 frag->vl = pm->vl;
10823 frag->frag_parent = ff;
10824 frag->timeout = pm->timeout;
10825 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10826 frag->pmt = PMT_FRAGMENT_BOX;
10827 msg = (char *) &frag[1];
10829 tfb.header.size =
10830 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10831 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10832 tfb.ack_uuid = pa->ack_uuid;
10833 tfb.msg_uuid = pm->msg_uuid;
10834 tfb.frag_off = htons (ff->frag_off + xoff);
10835 tfb.msg_size = htons (pm->bytes_msg);
10836 memcpy (msg, &tfb, sizeof(tfb));
10837 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10839 ff->tail_frag, frag);
10840 ff->frag_off += fragsize;
10841 ff = frag;
10842 }
10843
10844 /* Move head to the tail and return it */
10848 ff);
10852 ff);
10853
10854 return ff;
10855}
10856
10857
10870static struct PendingMessage *
10872 struct DistanceVectorHop *dvh,
10873 struct PendingMessage *pm)
10874{
10876 struct PendingAcknowledgement *pa;
10877 struct PendingMessage *bpm;
10878 char *msg;
10879
10880 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10881 return pm; /* already fragmented or reliability boxed, or control message:
10882 do nothing */
10883 if (NULL != pm->bpm)
10884 return pm->bpm; /* already computed earlier: do nothing */
10885 // TODO I guess we do not need this assertion. We might have a DLL with
10886 // fragments, because the MTU changed, and we do not need to fragment anymore.
10887 // But we should keep the fragments until message was completed, because
10888 // the MTU might change again.
10889 // GNUNET_assert (NULL == pm->head_frag);
10890 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10891 {
10892 /* failed hard */
10893 GNUNET_break (0);
10895 return NULL;
10896 }
10897
10899
10900 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10901 + pm->bytes_msg);
10903 "4 created pm %p storing vl %p from pm %p\n",
10904 bpm,
10905 pm->vl,
10906 pm);
10908 bpm->vl = pm->vl;
10909 bpm->frag_parent = pm;
10910 // Why was this needed?
10911 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10912 bpm->timeout = pm->timeout;
10914 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10917 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10918 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10919
10920 rbox.ack_uuid = pa->ack_uuid;
10921 msg = (char *) &bpm[1];
10922 memcpy (msg, &rbox, sizeof(rbox));
10923 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10924 pm->bpm = bpm;
10926 "Preparing reliability box for message <%" PRIu64
10927 "> of size %d (%d) to %s on queue %s\n",
10928 pm->logging_uuid,
10929 pm->bytes_msg,
10930 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10931 GNUNET_i2s (&pm->vl->target),
10932 queue->address);
10933 return bpm;
10934}
10935
10936
10937static void
10940{
10941 struct VirtualLink *vl = pm->vl;
10942 struct PendingMessage *pos;
10943
10944 /* re-insert sort in neighbour list */
10948 pm);
10949 pos = vl->pending_msg_tail;
10950 while ((NULL != pos) &&
10952 pos = pos->prev_vl;
10956 pos,
10957 pm);
10958}
10959
10960
10961static unsigned int
10963{
10964 struct PendingMessage *pos;
10966
10967 pos = pm->head_frag;
10968 while (NULL != pos)
10969 {
10970 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10971 GNUNET_NO == check_next_attempt_tree (pos, root))
10973 else
10974 {
10976 break;
10977 }
10978 pos = pos->next_frag;
10979 }
10980
10981 return frags_in_flight;
10982}
10983
10984
10985static void
10987{
10988 struct PendingMessage *pos;
10989
10990 pos = pm->head_frag;
10991 while (NULL != pos)
10992 {
10993 pos->frags_in_flight_round = pm->frags_in_flight_round;
10995 pos = pos->next_frag;
10996 }
10997}
10998
10999
11008static void
11011{
11012 if (NULL == pm->frag_parent)
11013 {
11016 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11017 pm->logging_uuid,
11020 }
11021 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11022 {
11023 struct PendingMessage *root = pm->frag_parent;
11024
11025 while (NULL != root->frag_parent)
11026 root = root->frag_parent;
11028 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11029 root->logging_uuid,
11031 root->next_attempt = next_attempt;
11033 }
11034 else
11035 {
11036 struct PendingMessage *root = pm->frag_parent;
11037
11038 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11039 root = root->frag_parent;
11040
11042 "frag_count next attempt %u\n",
11043 root->frag_count);
11044
11045 if (GNUNET_NO == root->frags_in_flight)
11046 {
11047 root->next_attempt = next_attempt;
11049 root->frags_in_flight_round++;
11051 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11052 ">)set to %" PRIu64 "\n",
11053 pm->logging_uuid,
11054 root->logging_uuid,
11056 }
11057
11058 pm->next_attempt = root->next_attempt;
11059 pm->frags_in_flight_round = root->frags_in_flight_round;
11061
11062 if (root->bytes_msg == root->frag_off)
11063 root->frags_in_flight = check_next_attempt_tree (root, root);
11064 else
11066
11067 if (GNUNET_NO == root->frags_in_flight)
11068 {
11070 "We have no fragments in flight for message %" PRIu64
11071 ", reorder root! Next attempt is %" PRIu64 "\n",
11072 root->logging_uuid,
11074 if (PMT_DV_BOX == root->pmt)
11075 root = root->frag_parent;
11076 reorder_root_pm (root, root->next_attempt);
11077 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11078 }
11079 else
11080 {
11081 double factor = ((double) root->frag_count - 1)
11082 / (double) root->frag_count;
11083 struct GNUNET_TIME_Relative s1;
11084 struct GNUNET_TIME_Relative s2;
11085 struct GNUNET_TIME_Relative plus_mean =
11088 next_attempt);
11089
11091 "frag_count %u after factor\n",
11092 root->frag_count);
11094 factor);
11095 s2 = GNUNET_TIME_relative_divide (plus,
11096 root->frag_count);
11097 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11100 "We have fragments in flight for message %" PRIu64
11101 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11102 root->logging_uuid,
11104 }
11105 }
11106}
11107
11108
11113{
11118
11123
11128
11133
11137 int frag;
11138
11142 int relb;
11143
11148
11152 unsigned int frags_in_flight;
11153
11158};
11159
11160
11172static void
11174 struct Queue *queue,
11175 struct VirtualLink *vl,
11176 struct DistanceVectorHop *dvh,
11177 size_t overhead)
11178{
11179 struct GNUNET_TIME_Absolute now;
11180
11181 now = GNUNET_TIME_absolute_get ();
11182 sc->to_early = GNUNET_NO;
11183 sc->frags_in_flight = GNUNET_NO;
11184 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11185 pos = pos->next_vl)
11186 {
11187 size_t real_overhead = overhead;
11188 int frag;
11189 int relb;
11190
11191 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11192 {
11194 "DV messages must not be DV-routed to next hop!\n");
11195 continue; /* DV messages must not be DV-routed to next hop! */
11196 }
11197 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11198 {
11199 if (GNUNET_YES == pos->frags_in_flight)
11200 {
11201 sc->frags_in_flight = GNUNET_YES;
11203 "Fragments in flight for message %" PRIu64 "\n",
11204 pos->logging_uuid);
11205 }
11206 else
11207 {
11209 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11210 PRIu64 "\n",
11211 pos->logging_uuid);
11212 sc->to_early = GNUNET_YES;
11213 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11214 pos->next_attempt);
11215 continue;
11216 }
11217 // break; /* too early for all messages, they are sorted by next_attempt */
11218 }
11219 if (NULL != pos->qe)
11220 {
11222 "not eligible\n");
11223 continue; /* not eligible */
11224 }
11225 sc->consideration_counter++;
11226 /* determine if we have to fragment, if so add fragmentation
11227 overhead! */
11229 "check %" PRIu64 " for sc->best\n",
11230 pos->logging_uuid);
11231 frag = GNUNET_NO;
11232 if (((0 != queue->mtu) &&
11233 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11234 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11236 ||
11237 (NULL != pos->head_frag /* fragments already exist, should
11238 respect that even if MTU is UINT16_MAX for
11239 this queue */))
11240 {
11242 "fragment msg with size %u, realoverhead is %lu\n",
11243 pos->bytes_msg,
11244 real_overhead);
11245 frag = GNUNET_YES;
11246 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11247 {
11248 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11249 header without the ACK UUID when using a *reliable* channel! */
11250 }
11251 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11252 }
11253 /* determine if we have to reliability-box, if so add reliability box
11254 overhead */
11255 relb = GNUNET_NO;
11256 if ((GNUNET_NO == frag) &&
11257 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11258 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11259 {
11260 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11261
11262 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11263 {
11264 frag = GNUNET_YES;
11265 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11266 }
11267 else
11268 {
11269 relb = GNUNET_YES;
11270 }
11272 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11273 pos->bytes_msg,
11274 real_overhead,
11275 queue->mtu,
11276 frag,
11277 relb);
11278 }
11279
11280 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11281 message would beat it! */
11282 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11283 {
11284 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11285 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11286 experimentally validated. There may be some huge potential for
11287 improvement here. Also, we right now only compare how well the
11288 given message fits _this_ queue, and do not consider how well other
11289 queues might suit the message. Taking other queues into consideration
11290 may further improve the result, but could also be expensive
11291 in terms of CPU time. */
11292 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11293 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11294 long long time_delta =
11295 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11296 / 1000LL;
11297
11298 /* "time_delta" considers which message has been 'ready' for transmission
11299 for longer, if a message has a preference for low latency, increase
11300 the weight of the time_delta by 10x if it is favorable for that message */
11301 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11302 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11303 time_delta *= 10; /* increase weight (always, both are low latency) */
11304 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11305 (time_delta > 0))
11306 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11307 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11308 (time_delta < 0))
11309 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11310 if (0 != queue->mtu)
11311 {
11312 /* Grant bonus if we are below MTU, larger bonus the closer we will
11313 be to the MTU */
11314 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11315 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11316 if (queue->mtu > real_overhead + pos->bytes_msg)
11317 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11318 }
11319 if (sc_score + time_delta > pm_score)
11320 {
11322 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11323 "\n",
11324 pos->logging_uuid,
11325 sc->best->logging_uuid);
11326 continue; /* sc_score larger, keep sc->best */
11327 }
11328 }
11329 sc->best = pos;
11330 sc->dvh = dvh;
11331 sc->frag = frag;
11332 sc->relb = relb;
11333 sc->real_overhead = real_overhead;
11334 }
11335}
11336
11337
11348static void
11350 struct Neighbour *next_hop,
11351 const struct GNUNET_MessageHeader *hdr,
11353{
11354 struct PendingMessageScoreContext *sc = cls;
11355 struct PendingMessage *pm = sc->best;
11356 struct PendingMessage *bpm;
11357 uint16_t bsize = ntohs (hdr->size);
11358
11359 GNUNET_assert (NULL == pm->bpm);
11360 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11362 "5 created pm %p storing vl %p from pm %p\n",
11363 bpm,
11364 pm->vl,
11365 pm);
11367 bpm->pmt = PMT_DV_BOX;
11368 bpm->vl = pm->vl;
11369 bpm->timeout = pm->timeout;
11370 bpm->bytes_msg = bsize;
11371 bpm->frag_parent = pm;
11374 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11375 " (next hop is %s)\n",
11377 pm->logging_uuid,
11378 GNUNET_i2s (&next_hop->pid));
11379 memcpy (&bpm[1], hdr, bsize);
11380 pm->bpm = bpm;
11381}
11382
11383
11399static void
11401{
11402 struct Queue *queue = cls;
11403 struct Neighbour *n = queue->neighbour;
11405 struct PendingMessage *pm;
11406
11407 queue->transmit_task = NULL;
11408 if (NULL == n->vl)
11409 {
11411 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11412 GNUNET_i2s (&n->pid),
11413 queue->address);
11414 queue->idle = GNUNET_YES;
11415 return;
11416 }
11417 memset (&sc, 0, sizeof(sc));
11418 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11419 if (NULL == sc.best)
11420 {
11421 /* Also look at DVH that have the n as first hop! */
11422 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11423 dvh = dvh->next_neighbour)
11424 {
11426 queue,
11427 dvh->dv->vl,
11428 dvh,
11429 sizeof(struct GNUNET_PeerIdentity)
11430 * (1 + dvh->distance)
11431 + sizeof(struct TransportDVBoxMessage)
11432 + sizeof(struct TransportDVBoxPayloadP));
11433 }
11434 }
11435 if (NULL == sc.best)
11436 {
11437 /* no message pending, nothing to do here! */
11439 "No pending messages, queue `%s' to %s now idle\n",
11440 queue->address,
11441 GNUNET_i2s (&n->pid));
11442 if (GNUNET_YES == sc.to_early)
11443 schedule_transmit_on_queue (sc.to_early_retry_delay,
11444 queue,
11446 queue->idle = GNUNET_YES;
11447 return;
11448 }
11449 /* There is a message pending, we are certainly not idle */
11450 queue->idle = GNUNET_NO;
11451
11452 /* Given selection in `sc`, do transmission */
11453 pm = sc.best;
11455 "Selected message <%" PRIu64 ">\n",
11456 pm->logging_uuid);
11457 if (NULL != sc.dvh)
11458 {
11460 "Is this %u a DV box?\n",
11461 pm->pmt);
11462 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11463 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11464 {
11466 "Discard old box, because we have a new DV path.\n");
11467 free_pending_message (sc.best->bpm);
11468 sc.best->bpm = NULL;
11469 }
11470
11471 if (NULL == sc.best->bpm)
11472 {
11474 "encapsulate_for_dv 2\n");
11475 encapsulate_for_dv (sc.dvh->dv,
11476 1,
11477 &sc.dvh,
11478 (const struct GNUNET_MessageHeader *) &sc.best[1],
11480 &sc,
11481 RMO_NONE,
11482 GNUNET_NO);
11483 GNUNET_assert (NULL != sc.best->bpm);
11485 "%lu %lu %lu %lu %u\n",
11486 sizeof(struct GNUNET_PeerIdentity),
11487 sizeof(struct TransportDVBoxMessage),
11488 sizeof(struct TransportDVBoxPayloadP),
11489 sizeof(struct TransportFragmentBoxMessage),
11490 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11491 sc.best->bpm->used_dvh = sc.dvh;
11492 }
11493 pm = sc.best->bpm;
11494 }
11495 if (GNUNET_YES == sc.frag)
11496 {
11497 pm = fragment_message (queue, sc.dvh, pm);
11498 if (NULL == pm)
11499 {
11501 "Fragmentation failed queue %s to %s for <%" PRIu64
11502 ">, trying again\n",
11503 queue->address,
11504 GNUNET_i2s (&n->pid),
11505 sc.best->logging_uuid);
11507 queue,
11509 return;
11510 }
11511 }
11512 else if (GNUNET_YES == sc.relb)
11513 {
11515 if (NULL == pm)
11516 {
11517 /* Reliability boxing failed, try next message... */
11518 GNUNET_log (
11520 "Reliability boxing failed queue %s to %s for <%" PRIu64
11521 ">, trying again\n",
11522 queue->address,
11523 GNUNET_i2s (&n->pid),
11524 sc.best->logging_uuid);
11526 queue,
11528 return;
11529 }
11530 }
11531
11532 /* Pass 'pm' for transission to the communicator */
11533 GNUNET_log (
11535 "Passing message <%" PRIu64
11536 "> to queue %s for peer %s (considered %u others)\n",
11537 pm->logging_uuid,
11538 queue->address,
11539 GNUNET_i2s (&n->pid),
11540 sc.consideration_counter);
11541
11542 /* Flow control: increment amount of traffic sent; if we are routing
11543 via DV (and thus the ultimate target of the pending message is for
11544 a different virtual link than the one of the queue), then we need
11545 to use up not only the window of the direct link but also the
11546 flow control window for the DV link! */
11547 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11548
11549 if (pm->vl != queue->neighbour->vl)
11550 {
11551 /* If the virtual link of the queue differs, this better be distance
11552 vector routing! */
11553 GNUNET_assert (NULL != sc.dvh);
11554 /* If we do distance vector routing, we better not do this for a
11555 message that was itself DV-routed */
11556 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11557 /* We use the size of the unboxed message here, to avoid counting
11558 the DV-Box header which is eaten up on the way by intermediaries */
11559 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11560 }
11561 else
11562 {
11563 GNUNET_assert (NULL == sc.dvh);
11564 }
11565
11566 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11567
11568 /* Check if this transmission somehow conclusively finished handing 'pm'
11569 even without any explicit ACKs */
11570 if ((PMT_CORE == pm->pmt) ||
11571 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11572 {
11574 }
11575 else
11576 {
11577 struct GNUNET_TIME_Relative wait_duration;
11578 unsigned int wait_multiplier;
11579
11580 if (PMT_FRAGMENT_BOX == pm->pmt)
11581 {
11582 struct PendingMessage *root;
11583
11584 root = pm->frag_parent;
11585 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11586 root = root->frag_parent;
11587
11588 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11589 / ((double) root->frag_off
11590 / (double) root->frag_count))
11591 * 4;
11592 }
11593 else
11594 {
11595 // No fragments, we use 4 RTT before retransmitting.
11596 wait_multiplier = 4;
11597 }
11598
11599 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11600 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11601
11603 "Wait multiplier %u\n",
11604 wait_multiplier);
11605
11606 /* Message not finished, waiting for acknowledgement.
11607 Update time by which we might retransmit 's' based on queue
11608 characteristics (i.e. RTT); it takes one RTT for the message to
11609 arrive and the ACK to come back in the best case; but the other
11610 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11611 retransmitting.
11612
11613 OPTIMIZE: Note that in the future this heuristic should likely
11614 be improved further (measure RTT stability, consider message
11615 urgency and size when delaying ACKs, etc.) */
11616
11617 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11618 queue->pd.aged_rtt.rel_value_us)
11619 wait_duration = queue->pd.aged_rtt;
11620 else
11621 {
11622 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11623 wait_multiplier = 4;
11624 }
11625 {
11628 wait_duration, wait_multiplier));
11630 wait_duration, wait_multiplier);
11632 "Waiting %s for ACK until %s\n",
11637 GNUNET_TIME_relative_multiply (wait_duration,
11638 wait_multiplier))
11639 );
11640 }
11641 }
11642 /* finally, re-schedule queue transmission task itself */
11644 queue,
11646}
11647
11648
11655static void
11657 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11658{
11659 struct TransportClient *tc = cls;
11660
11661 if (CT_COMMUNICATOR != tc->type)
11662 {
11663 GNUNET_break (0);
11665 return;
11666 }
11667 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11668 queue = queue->next_client)
11669 {
11670 struct Neighbour *neighbour = queue->neighbour;
11671
11672 if ((ntohl (dqm->qid) != queue->qid) ||
11673 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11674 continue;
11676 "Dropped queue %s to peer %s\n",
11677 queue->address,
11678 GNUNET_i2s (&neighbour->pid));
11679 free_queue (queue);
11681 return;
11682 }
11683 GNUNET_break (0);
11685}
11686
11687
11688static void
11690 struct TransportClient *tc)
11691{
11692 struct PendingMessage *pm;
11693
11694 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11695 qe->queue->queue_tail,
11696 qe);
11697 qe->queue->queue_length--;
11698 tc->details.communicator.total_queue_length--;
11700 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11701 qe->queue->address,
11702 qe->queue->qid,
11703 GNUNET_i2s (&qe->queue->neighbour->pid),
11704 qe->queue->queue_length,
11705 tc->details.communicator.total_queue_length);
11706
11707 /* if applicable, resume transmissions that waited on ACK */
11709 tc->details.communicator.total_queue_length)
11710 {
11711 /* Communicator dropped below threshold, resume all queues
11712 incident with this client! */
11714 GST_stats,
11715 "# Transmission throttled due to communicator queue limit",
11716 -1,
11717 GNUNET_NO);
11718 for (struct Queue *queue = tc->details.communicator.queue_head;
11719 NULL != queue;
11720 queue = queue->next_client)
11721 {
11723 queue,
11725 }
11726 }
11727 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11728 {
11729 /* queue dropped below threshold; only resume this one queue */
11731 "# Transmission throttled due to queue queue limit",
11732 -1,
11733 GNUNET_NO);
11735 qe->queue,
11737 }
11738 else if (1 == qe->queue->q_capacity)
11739 {
11740 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11742 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11743 PRIu64 ".\n",
11744 qe->queue->qid,
11745 qe->queue->q_capacity);
11746 /* message queue has capacity; only resume this one queue */
11747 /* queue dropped below threshold; only resume this one queue */
11749 "# Transmission throttled due to message queue capacity",
11750 -1,
11751 GNUNET_NO);
11753 qe->queue,
11755 }
11756
11757 if (NULL != (pm = qe->pm))
11758 {
11759 struct VirtualLink *vl;
11760
11761 // GNUNET_assert (qe == pm->qe);
11762 pm->qe = NULL;
11763 /* If waiting for this communicator may have blocked transmission
11764 of pm on other queues for this neighbour, force schedule
11765 transmit on queue for queues of the neighbour */
11766 if (NULL == pm->frag_parent)
11767 {
11768 vl = pm->vl;
11769 if ((NULL != vl) &&
11770 (NULL != vl->pending_msg_head) &&
11771 (vl->pending_msg_head == pm))
11773 }
11774 }
11775 GNUNET_free (qe);
11776}
11777
11778
11785static void
11787 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11788{
11789 struct TransportClient *tc = cls;
11790 struct QueueEntry *qe;
11791
11792 if (CT_COMMUNICATOR != tc->type)
11793 {
11794 GNUNET_break (0);
11796 return;
11797 }
11798
11799 /* find our queue entry matching the ACK */
11800 qe = NULL;
11802 "Looking for queue for PID %s\n",
11803 GNUNET_i2s (&sma->receiver));
11804 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11805 queue = queue->next_client)
11806 {
11807 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11808 continue;
11810 "Found PID %s\n",
11811 GNUNET_i2s (&queue->neighbour->pid));
11812
11813
11814 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11815 qep = qep->next)
11816 {
11817 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11818 sma->qid))
11819 continue;
11821 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11822 PRIu64 " Ack QID %u\n",
11823 qep->mid,
11824 queue->qid,
11825 GNUNET_ntohll (sma->mid),
11826 ntohl (sma->qid));
11827 qe = qep;
11828 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11830 "For pending message %" PRIu64 " we had retransmissions.\n",
11831 qe->pm->logging_uuid);
11832 break;
11833 }
11834 }
11835 if (NULL == qe)
11836 {
11838 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11839 GNUNET_ntohll (sma->mid),
11840 ntohl (sma->qid));
11841 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11842 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11843 /* this should never happen */
11844 // GNUNET_break (0);
11845 // GNUNET_SERVICE_client_drop (tc->client);
11847 return;
11848 }
11851}
11852
11853
11859static void
11861 const struct GNUNET_TRANSPORT_BurstFinished *bf)
11862{
11864}
11865
11866
11876static int
11878 const struct GNUNET_PeerIdentity *pid,
11879 void *value)
11880{
11881 struct TransportClient *tc = cls;
11882 struct Neighbour *neighbour = value;
11883
11884 GNUNET_assert (CT_MONITOR == tc->type);
11885 for (struct Queue *q = neighbour->queue_head; NULL != q;
11886 q = q->next_neighbour)
11887 {
11888 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11889 .cs = q->cs,
11890 .num_msg_pending = q->num_msg_pending,
11891 .num_bytes_pending = q->num_bytes_pending };
11892
11893 notify_monitor (tc, pid, q->address, q->nt, &me);
11894 }
11895 return GNUNET_OK;
11896}
11897
11898
11905static void
11908{
11909 struct TransportClient *tc = cls;
11910
11911 if (CT_NONE != tc->type)
11912 {
11913 GNUNET_break (0);
11915 return;
11916 }
11917 tc->type = CT_MONITOR;
11918 tc->details.monitor.peer = start->peer;
11919 tc->details.monitor.one_shot = ntohl (start->one_shot);
11923}
11924
11925
11933static struct TransportClient *
11935{
11936 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11937 {
11938 if (CT_COMMUNICATOR != tc->type)
11939 continue;
11940 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11941 return tc;
11942 }
11943 GNUNET_log (
11945 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11946 prefix);
11947 return NULL;
11948}
11949
11950
11958static void
11960{
11961 static uint32_t idgen = 0;
11962 struct TransportClient *tc;
11963 char *prefix;
11964 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11965 struct GNUNET_MQ_Envelope *env;
11966 size_t alen;
11967
11969 if (NULL == prefix)
11970 {
11971 GNUNET_break (0); /* We got an invalid address!? */
11972 return;
11973 }
11975 if (NULL == tc)
11976 {
11978 "# Suggestions ignored due to missing communicator",
11979 1,
11980 GNUNET_NO);
11982 "Cannot connect to %s at `%s', no matching communicator present\n",
11983 GNUNET_i2s (pid),
11984 address);
11986 return;
11987 }
11988 /* forward suggestion for queue creation to communicator */
11990 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11991 (unsigned int) idgen,
11992 prefix,
11993 GNUNET_i2s (pid),
11994 address);
11996 alen = strlen (address) + 1;
11997 env =
11999 cqm->request_id = htonl (idgen++);
12000 cqm->receiver = *pid;
12001 memcpy (&cqm[1], address, alen);
12002 GNUNET_MQ_send (tc->mq, env);
12003}
12004
12005
12013static void
12015{
12017 struct GNUNET_TIME_Absolute monotonic_time;
12018
12019 if (NULL != vs->revalidation_task)
12020 {
12021 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12022 vs->revalidation_task = NULL;
12023 }
12024 /*memcpy (&hkey,
12025 &hc,
12026 sizeof (hkey));*/
12028 "Remove key %s for address %s map size %u contains %u\n",
12029 GNUNET_h2s (&vs->hc),
12030 vs->address,
12033 &vs->hc));
12035
12037 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12038 vs->last_challenge_use.abs_value_us)
12039 {
12040 vs->first_challenge_use = monotonic_time;
12041 }
12042 vs->last_challenge_use = monotonic_time;
12043 tvc.header.type =
12045 tvc.header.size = htons (sizeof(tvc));
12046 tvc.reserved = htonl (0);
12047 tvc.challenge = vs->challenge;
12048 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12050 "Sending address validation challenge %s to %s\n",
12052 GNUNET_i2s (&q->neighbour->pid));
12053 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12054}
12055
12056
12062static void
12064{
12065 struct ValidationState *vs;
12066 struct Queue *q;
12068 GST_cfg);
12069
12070 (void) cls;
12071 validation_task = NULL;
12073 /* drop validations past their expiration */
12074 while (
12075 (NULL != vs) &&
12077 {
12079 "Validation response %s cleaned up\n",
12080 GNUNET_sh2s (&vs->challenge.value));
12083 }
12084 if (NULL == vs)
12085 {
12087 "Address validation task not scheduled anymore, nothing to do\n");
12088 return; /* woopsie, no more addresses known, should only
12089 happen if we're really a lonely peer */
12090 }
12091 q = find_queue (&vs->pid, vs->address);
12092 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
12093 {
12095 "To early to start next address validation for challenge %s\n",
12096 GNUNET_sh2s (&vs->challenge.value));
12097 return;
12098 }
12099 if (NULL == q)
12100 {
12101 vs->awaiting_queue = GNUNET_YES;
12102 suggest_to_connect (&vs->pid, vs->address);
12103 }
12104 else
12106 /* Finally, reschedule next attempt */
12107 vs->challenge_backoff =
12108 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12111 "Address validation task will run again in %s\n",
12112 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12113 GNUNET_YES));
12116 vs->challenge_backoff));
12117}
12118
12119
12124{
12128 struct Queue *q;
12129
12133 unsigned int quality_count;
12134
12138 unsigned int num_queues;
12139
12144 unsigned int k;
12145};
12146
12147
12159static int
12161 const struct GNUNET_PeerIdentity *pid,
12162 void *value)
12163{
12164 struct QueueQualityContext *ctx = cls;
12165 struct Neighbour *n = value;
12166 int do_inc;
12167
12168 (void) pid;
12169 do_inc = GNUNET_NO;
12170 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12171 {
12172 ctx->num_queues++;
12173 if (0 == ctx->k--)
12174 ctx->q = q;
12175 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12176 statistics and consider those as well here? */
12177 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12178 do_inc = GNUNET_YES;
12179 }
12180 if (GNUNET_YES == do_inc)
12181 ctx->quality_count++;
12182 return GNUNET_OK;
12183}
12184
12185
12197static void
12198start_dv_learn (void *cls);
12199
12200
12208
12209
12210static void
12212 const struct GNUNET_PeerIdentity *pid,
12213 const struct GNUNET_CRYPTO_EddsaSignature *sig)
12214{
12215 struct SignDvInitCls *sign_dv_init_cls = cls;
12216 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12217 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12218 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12219
12220 sign_dv_init_cls->pr->op = NULL;
12223 sign_dv_init_cls->pr);
12224 GNUNET_free (sign_dv_init_cls->pr);
12225
12226 dvl.init_sig = *sig;
12228 dvl.challenge = lle->challenge;
12229
12230 qqc.quality_count = 0;
12232 qqc.num_queues = 0;
12233 qqc.q = NULL;
12236 &qqc);
12237 GNUNET_assert (NULL != qqc.q);
12238
12239 /* Do this as close to transmission time as possible! */
12241
12242 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12243 /* reschedule this job, randomizing the time it runs (but no
12244 actual backoff!) */
12248 NULL);
12249}
12250
12251
12263static void
12265{
12266 struct LearnLaunchEntry *lle;
12267 struct QueueQualityContext qqc;
12268 struct TransportDVLearnMessage dvl;
12269
12270 (void) cls;
12271 dvlearn_task = NULL;
12273 return; /* lost all connectivity, cannot do learning */
12274 qqc.quality_count = 0;
12275 qqc.num_queues = 0;
12279 &qqc);
12281 {
12282 struct GNUNET_TIME_Relative delay;
12283 unsigned int factor;
12284
12285 /* scale our retries by how far we are above the threshold */
12289 "At connection quality %u, will launch DV learn in %s\n",
12290 qqc.quality_count,
12293 return;
12294 }
12295 /* remove old entries in #dvlearn_map if it has grown too big */
12296 while (MAX_DV_LEARN_PENDING <=
12298 {
12299 lle = lle_tail;
12302 &lle->challenge.value,
12303 lle));
12305 GNUNET_free (lle);
12306 }
12307 /* setup data structure for learning */
12308 lle = GNUNET_new (struct LearnLaunchEntry);
12310 &lle->challenge,
12311 sizeof(lle->challenge));
12313 "Starting launch DV learn with challenge %s\n",
12314 GNUNET_sh2s (&lle->challenge.value));
12319 &lle->challenge.value,
12320 lle,
12323 dvl.header.size = htons (sizeof(dvl));
12324 dvl.num_hops = htons (0);
12325 dvl.bidirectional = htons (0);
12327 dvl.monotonic_time =
12329 // We will set the below again later
12330 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12331 dvl.challenge = lle->challenge;
12333 {
12334 struct DvInitPS dvip = {
12335 .purpose.purpose = htonl (
12337 .purpose.size = htonl (sizeof(dvip)),
12338 .monotonic_time = dvl.monotonic_time,
12339 .challenge = lle->challenge
12340 };
12341 struct SignDvInitCls *sign_dv_init_cls;
12342
12343 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12344 sign_dv_init_cls->dvl = dvl;
12345 sign_dv_init_cls->lle = lle;
12346 sign_dv_init_cls->qqc = qqc;
12347 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12350 sign_dv_init_cls->pr);
12351 sign_dv_init_cls->pr->op =
12353 &dvip.purpose,
12355 sign_dv_init_cls);
12356 }
12357}
12358
12359
12367static char *
12369{
12370 const char *colon;
12371 char *colon_rest;
12372 size_t colon_rest_length;
12373 char *address_without_port;
12374
12375 colon = strchr (address,':');
12376 colon_rest = GNUNET_strndup (address, colon - address);
12377 colon_rest_length = strlen (colon_rest);
12378 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12379 GNUNET_free (colon_rest);
12380
12381 return address_without_port;
12382}
12383
12384
12394static int
12396 const struct GNUNET_PeerIdentity *pid,
12397 void *value)
12398{
12399 struct Queue *q = cls;
12400 struct ValidationState *vs = value;
12401 char *address_without_port_vs;
12402 char *address_without_port_q;
12403 int success = GNUNET_YES;
12404
12405 // TODO Check if this is really necessary.
12406 address_without_port_vs = get_address_without_port (vs->address);
12407 address_without_port_q = get_address_without_port (q->address);
12408
12410 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12411 GNUNET_i2s (pid),
12412 address_without_port_vs,
12413 address_without_port_q);
12414 (void) pid;
12415 if ((GNUNET_YES == vs->awaiting_queue) &&
12416 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12417 {
12418
12419 vs->awaiting_queue = GNUNET_NO;
12421 success = GNUNET_NO;
12422 }
12423
12424 GNUNET_free (address_without_port_vs);
12425 GNUNET_free (address_without_port_q);
12426 return success;
12427}
12428
12429
12438static void
12440 const struct GNUNET_PEERSTORE_Record *record,
12441 const char *emsg)
12442{
12443 struct Neighbour *n = cls;
12444 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12445
12446 (void) emsg;
12447 if (NULL == record)
12448 {
12449 /* we're done with #neighbour_dv_monotime_cb() invocations,
12450 continue normal processing */
12451 n->get = NULL;
12453 return;
12454 }
12455 if (0 == record->value_size)
12456 {
12458 GNUNET_break (0);
12459 return;
12460 }
12461 mtbe = record->value;
12466}
12467
12468
12469static void
12471 const struct GNUNET_PeerIdentity *pid,
12472 const char *uri)
12473{
12474 struct Queue *queue = cls;
12475 struct sockaddr_in v4;
12476 const char *slash;
12477 char *address_uri;
12478 char *prefix;
12479 char *uri_without_port;
12480 char *address_uri_without_port;
12481
12482 slash = strrchr (uri, '/');
12483 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12484 GNUNET_assert (NULL != slash);
12485 slash++;
12486 GNUNET_asprintf (&address_uri,
12487 "%s-%s",
12488 prefix,
12489 slash);
12490
12492 "1 not global natted_address %u %s %s %s\n",
12493 queue->is_global_natted,
12494 uri,
12495 queue->address,
12496 slash);
12497
12498 uri_without_port = get_address_without_port (address_uri);
12499 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12500 {
12502 GNUNET_free (address_uri);
12503 GNUNET_free (uri_without_port);
12504 return;
12505 }
12506
12508 "2 not global natted_address %u %s %s\n",
12509 queue->is_global_natted,
12510 uri,
12511 queue->address);
12512
12513 if (GNUNET_NO == queue->is_global_natted)
12514 {
12516 GNUNET_free (address_uri);
12517 GNUNET_free (uri_without_port);
12518 return;
12519 }
12520
12522 "3 not global natted_address %u %s %s\n",
12523 queue->is_global_natted,
12524 uri,
12525 queue->address);
12526
12527 if (0 == strcmp (uri_without_port, address_uri))
12528 {
12530 GNUNET_free (address_uri);
12531 GNUNET_free (uri_without_port);
12532 return;
12533 }
12534
12536 "4 not global natted_address %u %s %s\n",
12537 queue->is_global_natted,
12538 uri,
12539 queue->address);
12540
12541 address_uri_without_port = get_address_without_port (queue->address);
12542 if (0 == strcmp (uri_without_port, address_uri_without_port))
12543 {
12544 queue->is_global_natted = GNUNET_NO;
12545 }
12546
12548 "not global natted_address %u %s %s %s %s %s %u\n",
12549 queue->is_global_natted,
12550 uri,
12551 queue->address,
12552 uri_without_port,
12553 address_uri_without_port,
12554 prefix,
12555 GNUNET_NO);
12557 GNUNET_free (address_uri);
12558 GNUNET_free (address_uri_without_port);
12559 GNUNET_free (uri_without_port);
12560}
12561
12562
12575
12576
12577static enum GNUNET_GenericReturnValue
12579 const struct GNUNET_PeerIdentity *pid,
12580 void *value)
12581{
12582 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12583 struct TransportGlobalNattedAddress *tgna = value;
12584 char *addr = (char *) &tgna[1];
12585
12587 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12588 tgna,
12589 addr,
12590 ntohl (tgna->address_length),
12591 strlen (tgna_cls->addr));
12592 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12593 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12594 {
12595 tgna_cls->tgna = tgna;
12596 return GNUNET_NO;
12597 }
12598 return GNUNET_YES;
12599}
12600
12601
12602static void
12604{
12606 "Error in PEERSTORE monitoring for checking global natted\n");
12607}
12608
12609
12610static void
12612{
12614 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12615}
12616
12617
12618static void
12620 const struct GNUNET_PEERSTORE_Record *record,
12621 const char *emsg)
12622{
12623 struct Queue *queue = cls;
12624 struct Neighbour *neighbour = queue->neighbour;
12625 struct GNUNET_HELLO_Parser *parser;
12626 struct GNUNET_MessageHeader *hello;
12628 size_t address_len_without_port;
12629
12630 if (NULL != emsg)
12631 {
12633 "Got failure from PEERSTORE: %s\n",
12634 emsg);
12635 return;
12636 }
12637 if (0 == record->value_size)
12638 {
12640 GNUNET_break (0);
12641 return;
12642 }
12643 queue->is_global_natted = GNUNET_YES;
12644 hello = record->value;
12645 parser = GNUNET_HELLO_parser_from_msg (hello);
12647 "before not global natted %u\n",
12648 queue->is_global_natted);
12651 queue);
12653 "after not global natted %u\n",
12654 queue->is_global_natted);
12655 GNUNET_HELLO_parser_free (parser);
12656
12657 tgna_cls.addr = get_address_without_port (queue->address);
12658 address_len_without_port = strlen (tgna_cls.addr);
12659 /*{
12660 char buf[address_len_without_port + 1];
12661
12662 GNUNET_memcpy (&buf, addr, address_len_without_port);
12663 buf[address_len_without_port] = '\0';
12664 GNUNET_free (addr);
12665 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12666 }*/
12667 tgna_cls.tgna = NULL;
12669 &neighbour->pid,
12671 &tgna_cls);
12672 if (NULL != tgna_cls.tgna)
12674 " tgna_cls.tgna tgna %p %lu %u %u\n",
12675 tgna_cls.tgna,
12676 neighbour->size_of_global_addresses,
12677 ntohl (tgna_cls.tgna->address_length),
12678 neighbour->number_of_addresses);
12679 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12680 {
12681 struct TransportGlobalNattedAddress *tgna;
12682
12683 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12684 + address_len_without_port);
12685 tgna->address_length = htonl (address_len_without_port);
12686 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12688 &neighbour->pid,
12689 tgna,
12691 neighbour->number_of_addresses++;
12692 neighbour->size_of_global_addresses += address_len_without_port + 1;
12694 "Created tgna %p with address %s and length %lu\n",
12695 tgna,
12696 tgna_cls.addr,
12697 address_len_without_port + 1);
12698 }
12699 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12700 {
12702 &neighbour->pid,
12703 tgna_cls.tgna);
12704 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12706 );
12707 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12708 ;
12709 GNUNET_assert (0 < neighbour->number_of_addresses);
12710 neighbour->number_of_addresses--;
12712 "removed tgna %p\n",
12713 tgna_cls.tgna);
12714 GNUNET_free (tgna_cls.tgna);
12715 }
12717 GNUNET_free (tgna_cls.addr);
12718}
12719
12720
12727static void
12729 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12730{
12731 struct TransportClient *tc = cls;
12732 struct Queue *queue;
12733 struct Neighbour *neighbour;
12734 const char *addr;
12735 uint16_t addr_len;
12736
12737 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12738 {
12739 /* MTU so small as to be useless for transmissions,
12740 required for #fragment_message()! */
12741 GNUNET_break_op (0);
12743 return;
12744 }
12745 /* This may simply be a queue update */
12746 for (queue = tc->details.communicator.queue_head;
12747 NULL != queue;
12748 queue = queue->next_client)
12749 {
12750 if (queue->qid != ntohl (aqm->qid))
12751 continue;
12752 break;
12753 }
12754
12755 if (NULL != queue)
12756 {
12757 neighbour = queue->neighbour;
12758 }
12759 else
12760 {
12761 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12762
12763 neighbour = lookup_neighbour (&aqm->receiver);
12764 if (NULL == neighbour)
12765 {
12766 neighbour = GNUNET_new (struct Neighbour);
12768 GNUNET_YES);
12769 neighbour->pid = aqm->receiver;
12772 neighbours,
12773 &neighbour->pid,
12774 neighbour,
12776 neighbour->get =
12778 "transport",
12779 &neighbour->pid,
12782 neighbour);
12783 }
12784 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12785 addr = (const char *) &aqm[1];
12787 "New queue %s to %s available with QID %u and q_len %" PRIu64
12788 " and mtu %u\n",
12789 addr,
12790 GNUNET_i2s (&aqm->receiver),
12791 ntohl (aqm->qid),
12792 GNUNET_ntohll (aqm->q_len),
12793 ntohl (aqm->mtu));
12794 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12795 queue->tc = tc;
12796 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12797 next_neighbour)
12798 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12799 validated_until);
12800 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12801 {
12803 "New queue with QID %u inherit validated until\n",
12804 ntohl (aqm->qid));
12805 queue->validated_until = validated_until;
12806 }
12807 queue->address = (const char *) &queue[1];
12808 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12809 queue->qid = ntohl (aqm->qid);
12810 queue->neighbour = neighbour;
12812 queue->unlimited_length = GNUNET_YES;
12813 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12814 memcpy (&queue[1], addr, addr_len);
12815 /* notify monitors about new queue */
12816 {
12817 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12818
12819 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12820 }
12822 neighbour->queue_head,
12823 neighbour->queue_tail,
12824 queue);
12826 tc->details.communicator.queue_head,
12827 tc->details.communicator.queue_tail,
12828 queue);
12829
12830 }
12831 queue->mtu = ntohl (aqm->mtu);
12832 queue->nt = ntohl (aqm->nt);
12833 queue->cs = ntohl (aqm->cs);
12834 queue->idle = GNUNET_YES;
12835
12836 {
12837 struct sockaddr_in v4;
12838 char *addr_without = get_address_without_port (queue->address);
12839 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12840 {
12842 "start not global natted\n");
12844 GNUNET_YES,
12845 "peerstore",
12846 &neighbour->pid,
12848 &
12850 NULL,
12851 &
12853 NULL,
12855 queue);
12856 }
12857 GNUNET_free (addr_without);
12858 }
12859 /* check if valdiations are waiting for the queue */
12861 &aqm->receiver))
12862 {
12865 &aqm->
12866 receiver,
12867 &
12869 queue))
12870 start_address_validation (&aqm->receiver, queue->address);
12871 }
12872 else
12873 start_address_validation (&aqm->receiver, queue->address);
12874 /* look for traffic for this queue */
12875 // TODO Check whether this makes any sense at all.
12876 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12877 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12878 /* might be our first queue, try launching DV learning */
12879 if (NULL == dvlearn_task)
12882}
12883
12884
12891static void
12893 const struct
12895{
12896 struct TransportClient *tc = cls;
12897 struct Queue *target_queue = NULL;
12898
12900 "Received queue update message for %u with q_len %llu and mtu %u\n",
12901 ntohl (msg->qid),
12902 (unsigned long long) GNUNET_ntohll (msg->q_len),
12903 ntohl (msg->mtu));
12904 for (target_queue = tc->details.communicator.queue_head;
12905 NULL != target_queue;
12906 target_queue = target_queue->next_client)
12907 {
12908 if (ntohl (msg->qid) == target_queue->qid)
12909 break;
12910 }
12911 if (NULL == target_queue)
12912 {
12914 "Queue to update no longer exists! Discarding update.\n");
12915 return;
12916 }
12917
12918 target_queue->nt = msg->nt;
12919 target_queue->mtu = ntohl (msg->mtu);
12920 target_queue->cs = msg->cs;
12921 target_queue->priority = ntohl (msg->priority);
12922 /* The update message indicates how many messages
12923 * the queue should be able to handle.
12924 */
12926 target_queue->unlimited_length = GNUNET_YES;
12927 else
12928 target_queue->unlimited_length = GNUNET_NO;
12929 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12930 if (0 < target_queue->q_capacity)
12932 target_queue,
12935}
12936
12937
12945static void
12947 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12948{
12949 struct TransportClient *tc = cls;
12950
12951 if (CT_COMMUNICATOR != tc->type)
12952 {
12953 GNUNET_break (0);
12955 return;
12956 }
12958 "# Suggestions succeeded at communicator",
12959 1,
12960 GNUNET_NO);
12962 "Request #%u for communicator to create queue succeeded\n",
12963 (unsigned int) ntohs (cqr->request_id));
12965}
12966
12967
12976static void
12978 void *cls,
12979 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12980{
12981 struct TransportClient *tc = cls;
12982
12983 if (CT_COMMUNICATOR != tc->type)
12984 {
12985 GNUNET_break (0);
12987 return;
12988 }
12990 "Request #%u for communicator to create queue failed\n",
12991 (unsigned int) ntohl (cqr->request_id));
12993 "# Suggestions failed in queue creation at communicator",
12994 1,
12995 GNUNET_NO);
12997}
12998
12999
13007static void
13009{
13010 struct TransportClient *tc = cls;
13011 struct PeerRequest *pr;
13012
13013 if (CT_APPLICATION != tc->type)
13014 {
13015 GNUNET_break (0);
13017 return;
13018 }
13019 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
13020 &msg->peer);
13021 if (NULL == pr)
13022 {
13023 GNUNET_break (0);
13025 return;
13026 }
13027 (void) stop_peer_request (tc, &pr->pid, pr);
13029}
13030
13031
13032static void
13034 const struct GNUNET_PeerIdentity *pid,
13035 const char *uri)
13036{
13037 struct Queue *q;
13038 int pfx_len;
13039 const char *eou;
13040 char *address;
13041 (void) cls;
13042
13043 eou = strstr (uri,
13044 "://");
13045 pfx_len = eou - uri;
13046 eou += 3;
13048 "%.*s-%s",
13049 pfx_len,
13050 uri,
13051 eou);
13052
13054 "hello for client %s\n",
13055 address);
13056
13057 q = find_queue (pid, address);
13058 if (NULL == q)
13059 {
13061 }
13062 else
13065}
13066
13067
13075static void
13077 const struct GNUNET_PEERSTORE_Record *record,
13078 const char *emsg)
13079{
13080 struct PeerRequest *pr = cls;
13081 struct GNUNET_HELLO_Parser *parser;
13082 struct GNUNET_MessageHeader *hello;
13083
13084 if (NULL != emsg)
13085 {
13087 "Got failure from PEERSTORE: %s\n",
13088 emsg);
13089 return;
13090 }
13091 if (NULL == GST_my_identity)
13092 {
13094 "No identity given yet!\n");
13095 return;
13096 }
13097 hello = record->value;
13098 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
13099 {
13101 return;
13102 }
13103 parser = GNUNET_HELLO_parser_from_msg (hello);
13104 if (NULL == parser)
13105 {
13107 "HELLO cannot be parsed!\n");
13108 return;
13109 }
13111 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13115 NULL);
13116 GNUNET_HELLO_parser_free (parser);
13117}
13118
13119
13120static void
13122{
13124 "Error in PEERSTORE monitoring\n");
13125}
13126
13127
13128static void
13130{
13132 "Done with initial PEERSTORE iteration during monitoring\n");
13133}
13134
13135
13143static void
13145{
13146 struct TransportClient *tc = cls;
13147 struct PeerRequest *pr;
13148
13149 if (CT_NONE == tc->type)
13150 {
13151 tc->type = CT_APPLICATION;
13152 tc->details.application.requests =
13154 }
13155 if (CT_APPLICATION != tc->type)
13156 {
13157 GNUNET_break (0);
13159 return;
13160 }
13162 "Client suggested we talk to %s with preference %d at rate %u\n",
13163 GNUNET_i2s (&msg->peer),
13164 (int) ntohl (msg->pk),
13165 (int) ntohl (msg->bw.value__));
13166 if (0 == GNUNET_memcmp (GST_my_identity, &msg->peer))
13167 {
13169 "Client suggested connection to ourselves, ignoring...\n");
13170 return;
13171 }
13172 pr = GNUNET_new (struct PeerRequest);
13173 pr->tc = tc;
13174 pr->pid = msg->peer;
13175 pr->bw = msg->bw;
13176 pr->pk = ntohl (msg->pk);
13178 tc->details.application.requests,
13179 &pr->pid,
13180 pr,
13182 {
13183 GNUNET_break (0);
13184 GNUNET_free (pr);
13186 return;
13187 }
13188 pr->nc =
13190 GNUNET_YES,
13191 "peerstore",
13192 NULL,
13195 NULL,
13197 NULL,
13199 pr);
13201}
13202
13203
13212static int
13214 const struct RequestHelloValidationMessage *m)
13215{
13216 (void) cls;
13218 return GNUNET_OK;
13219}
13220
13221
13229static void
13231 const struct RequestHelloValidationMessage *m)
13232{
13233 struct TransportClient *tc = cls;
13234 struct Queue *q;
13235
13236 q = find_queue (&m->peer, (const char *) &m[1]);
13237 if (NULL == q)
13238 {
13239 suggest_to_connect (&m->peer, (const char *) &m[1]);
13240 }
13241 else
13242 start_address_validation (&m->peer, (const char *) &m[1]);
13244}
13245
13246
13255static int
13257 const struct GNUNET_PeerIdentity *pid,
13258 void *value)
13259{
13260 struct Neighbour *neighbour = value;
13261
13262 (void) cls;
13263 (void) pid;
13264 GNUNET_break (0); // should this ever happen?
13265 free_neighbour (neighbour, GNUNET_YES);
13266
13267 return GNUNET_OK;
13268}
13269
13270
13279static int
13281 const struct GNUNET_PeerIdentity *pid,
13282 void *value)
13283{
13284 struct DistanceVector *dv = value;
13285
13286 (void) cls;
13287 (void) pid;
13288 free_dv_route (dv);
13289
13290 return GNUNET_OK;
13291}
13292
13293
13302static int
13304 const struct GNUNET_PeerIdentity *pid,
13305 void *value)
13306{
13307 struct ValidationState *vs = value;
13308
13309 (void) cls;
13310 (void) pid;
13312 return GNUNET_OK;
13313}
13314
13315
13324static int
13325free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
13326{
13327 struct PendingAcknowledgement *pa = value;
13328
13329 (void) cls;
13330 (void) key;
13332 return GNUNET_OK;
13333}
13334
13335
13344static int
13346 const struct GNUNET_PeerIdentity *pid,
13347 void *value)
13348{
13349 struct AcknowledgementCummulator *ac = value;
13350
13351 (void) cls;
13352 (void) pid;
13354 GNUNET_free (ac);
13355 return GNUNET_OK;
13356}
13357
13358
13365static void
13366do_shutdown (void *cls)
13367{
13368 struct LearnLaunchEntry *lle;
13369 struct PilsRequest *pr;
13370 (void) cls;
13371
13373 "shutdown logic\n");
13376 &free_neighbour_cb, NULL);
13377 if (NULL != validation_task)
13378 {
13380 validation_task = NULL;
13381 }
13382 if (NULL != dvlearn_task)
13383 {
13385 dvlearn_task = NULL;
13386 }
13388 dvlearn_map = NULL;
13391 dv_routes = NULL;
13392 if (NULL != GST_stats)
13393 {
13395 GST_stats = NULL;
13396 }
13397 if (NULL != GST_my_hello)
13398 {
13400 GST_my_hello = NULL;
13401 }
13402 if (NULL != GST_my_identity)
13403 {
13405 GST_my_identity = NULL;
13406 }
13409 NULL);
13411 ack_cummulators = NULL;
13414 NULL);
13416 pending_acks = NULL;
13419 neighbours = NULL;
13422 links = NULL;
13425 NULL);
13427 backtalkers = NULL;
13430 NULL);
13432 validation_map = NULL;
13434 validation_heap = NULL;
13436 revalidation_map = NULL;
13437 while (NULL != ir_head)
13439 GNUNET_assert (0 == ir_total);
13440 while (NULL != (lle = lle_head))
13441 {
13443 GNUNET_free (lle);
13444 }
13445 while (NULL != (pr = pils_requests_head))
13446 {
13449 pr);
13450 if (NULL != pr->op)
13451 GNUNET_PILS_cancel (pr->op);
13452 GNUNET_free (pr);
13453 }
13454 if (NULL != pils_feed_task)
13455 {
13457 pils_feed_task = NULL;
13458 }
13459 if (NULL != pils)
13460 {
13462 pils = NULL;
13463 }
13464 if (NULL != peerstore)
13465 {
13467 "Disconnecting from PEERSTORE service\n");
13469 peerstore = NULL;
13470 }
13472}
13473
13474
13475static void
13476shutdown_task (void *cls)
13477{
13479
13481 "Shutdown task executed\n");
13482 if (NULL != clients_head)
13483 {
13484 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13485 {
13487 "client still connected: %u\n",
13488 tc->type);
13489 }
13490 }
13491 else
13492 do_shutdown (cls);
13493
13494}
13495
13496
13501
13502static void
13503update_hello_from_pid_change_cb (void *cls, int success)
13504{
13505 struct UpdateHelloFromPidCtx *pc = cls;
13506
13507 if (GNUNET_OK != success)
13508 {
13510 "Failed to store our new hello with peerstore\n");
13511 }
13512 GNUNET_free (pc);
13514 "Stored our new hello with peerstore\n");
13515}
13516
13517
13518void
13520 const struct GNUNET_PeerIdentity *pid,
13521 const char *uri)
13522{
13524 "%s\n", uri);
13525}
13526
13527
13537static void
13539 const struct GNUNET_HELLO_Parser *parser,
13540 const struct GNUNET_HashCode *hash)
13541{
13542 struct GNUNET_MQ_Envelope *env;
13543 const struct GNUNET_MessageHeader *msg;
13544 struct UpdateHelloFromPidCtx *sc;
13545 struct GNUNET_HELLO_Builder *nbuilder;
13546 struct GNUNET_PeerIdentity npid;
13547
13548 if (NULL == GST_my_identity)
13550 if (NULL == GST_my_hello)
13553 "My current identity is `%s'\n",
13565 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13566 &npid);
13567 if (GNUNET_NO ==
13569 {
13571 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
13573 "Proposed address list:\n");
13576 "Current address list:\n");
13578 GNUNET_HELLO_builder_free (nbuilder);
13579 return;
13580 }
13582 GST_my_hello = nbuilder;
13583 memcpy (GST_my_identity, &npid, sizeof npid);
13585 "My new identity is `%s'\n",
13591 msg,
13593 sc);
13594 GNUNET_free (env);
13595}
13596
13597
13605static void
13606run (void *cls,
13607 const struct GNUNET_CONFIGURATION_Handle *c,
13609{
13610 (void) cls;
13611 (void) service;
13612 /* setup globals */
13615 GST_cfg = c;
13623 GNUNET_YES);
13628 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13630 "transport",
13631 "USE_BURST_NAT");
13632 if (GNUNET_SYSERR == use_burst)
13634 "Could not configure burst nat use. Default to no.\n");
13640 "transport",
13641 0,
13642 0,
13643 NULL,
13644 0,
13645 NULL,
13646 NULL,
13647 NULL);
13648 if (NULL == peerstore)
13649 {
13650 GNUNET_break (0);
13652 return;
13653 }
13654 GST_my_identity = NULL;
13657 NULL); // FIXME we need to wait for
13658 // our first peer id before
13659 // we can start the service
13660 // completely - PILS in turn
13661 // waits for the first
13662 // addresses from the
13663 // communicators in order to
13664 // be able to generate a
13665 // peer id
13666 if (NULL == pils)
13667 {
13668 GNUNET_break (0);
13670 return;
13671 }
13672}
13673
13674
13680 "transport",
13682 &run,
13685 NULL,
13686 /* communication with applications */
13687 GNUNET_MQ_hd_fixed_size (suggest,
13690 NULL),
13691 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13694 NULL),
13695 GNUNET_MQ_hd_var_size (request_hello_validation,
13698 NULL),
13699 /* communication with core */
13700 GNUNET_MQ_hd_fixed_size (client_start,
13702 struct StartMessage,
13703 NULL),
13704 GNUNET_MQ_hd_var_size (client_send,
13706 struct OutboundMessage,
13707 NULL),
13708 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13710 struct RecvOkMessage,
13711 NULL),
13712 /* communication with communicators */
13713 GNUNET_MQ_hd_var_size (communicator_available,
13716 NULL),
13717 GNUNET_MQ_hd_var_size (communicator_backchannel,
13720 NULL),
13721 GNUNET_MQ_hd_var_size (add_address,
13724 NULL),
13725 GNUNET_MQ_hd_fixed_size (del_address,
13728 NULL),
13729 GNUNET_MQ_hd_var_size (incoming_msg,
13732 NULL),
13733 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13736 NULL),
13737 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13740 NULL),
13741 GNUNET_MQ_hd_var_size (add_queue_message,
13744 NULL),
13745 GNUNET_MQ_hd_fixed_size (update_queue_message,
13748 NULL),
13749 GNUNET_MQ_hd_fixed_size (del_queue_message,
13752 NULL),
13753 GNUNET_MQ_hd_fixed_size (send_message_ack,
13756 NULL),
13757 GNUNET_MQ_hd_fixed_size (burst_finished,
13760 NULL),
13761 /* communication with monitors */
13762 GNUNET_MQ_hd_fixed_size (monitor_start,
13765 NULL),
13767
13768
13769/* 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 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.
static char * data
The data to insert into the dht.
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 OpusEncoder * enc
OPUS encoder.
struct GNUNET_SCHEDULER_Task * shutdown_task
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 size_t data_size
Number of bytes in data.
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 unsigned long long payload
How much data are we currently storing in the database?
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 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 enum GNUNET_GenericReturnValue dv_decrypt(struct DVKeyState *key, void *out, const void *ciph, size_t out_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
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 void pils_sign_addr_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
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 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 void dv_key_clean(struct DVKeyState *key)
Clean up key material in key.
static struct GNUNET_SCHEDULER_Task * dvlearn_task
Task run to initiate DV learning.
static int check_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void handle_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static int check_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment box.
static unsigned int get_age()
Get an offset into the transmission history buffer for struct PerformanceData.
static void free_validation_state(struct ValidationState *vs)
Free validation state.
static struct PendingAcknowledgement * prepare_pending_acknowledgement(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Setup data structure waiting for acknowledgements.
static int check_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
static void hello_for_incoming_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
#define MAX_DV_DISCOVERY_SELECTION
Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiato...
#define QUEUE_ENTRY_TIMEOUT
static struct LearnLaunchEntry * lle_tail
Tail of a DLL sorted by launch time.
static struct GNUNET_CONTAINER_Heap * validation_heap
MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware ...
static void core_send_connect_info(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void send_dv_to_neighbour(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
static void harmonize_flight_round(struct PendingMessage *pm)
#define ACK_CUMMULATOR_TIMEOUT
How long until we forget about historic accumulators and thus reset the ACK counter?...
void pils_sign_address(struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
Build address record by signing raw information with private key of the peer identity.
static 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 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 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.
#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 void burst_timeout(void *cls)
#define BACKCHANNEL_INACTIVITY_TIMEOUT
How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
static struct GNUNET_TIME_Relative get_network_latency(const struct TransportDVLearnMessage *dvl)
static void hello_for_client_error_cb(void *cls)
static void check_for_global_natted(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
#define ADDRESS_VALIDATION_LIFETIME
How long do we consider an address valid if we just checked?
static void free_distance_vector_hop(struct DistanceVectorHop *dvh)
Free a dvh.
#define MAX_FC_RETRANSMIT_COUNT
Maximum number of FC retransmissions for a running retransmission task.
static void sign_ephemeral(struct DistanceVector *dv)
Sign ephemeral keys in our dv are current.
static void handle_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment.
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 cores_send_connect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we gained a connection.
static void cummulative_ack(const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
static void task_consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define DV_LEARN_QUALITY_THRESHOLD
How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiati...
static void free_neighbour(struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
Release memory used by neighbour.
PendingMessageType
Types of different pending messages.
@ PMT_FRAGMENT_BOX
Fragment box.
@ PMT_DV_BOX
Pending message created during forward_dv_box().
@ PMT_CORE
Ordinary message received from the CORE service.
@ PMT_RELIABILITY_BOX
Reliability box.
static struct GNUNET_TIME_Relative calculate_rtt(struct DistanceVector *dv)
static int check_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int stop_peer_request(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Stop the peer request in value.
static void handle_update_queue_message(void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
Handle updates to queues.
static void cores_send_disconnect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void handle_client_start(void *cls, const struct StartMessage *start)
Initialize a "CORE" client.
#define MAX_DV_PATHS_TO_TARGET
Maximum number of DV paths we keep simultaneously to the same target.
static void free_virtual_link(struct VirtualLink *vl)
Free virtual link.
RouteMessageOptions
Which transmission options are allowable for transmission? Interpreted bit-wise!
@ RMO_UNCONFIRMED_ALLOWED
We are allowed to use unconfirmed queues or DV routes for this message.
@ RMO_DV_ALLOWED
We are allowed to use DV routing for this hdr.
@ RMO_REDUNDANT
If we have multiple choices, it is OK to send this message over multiple channels at the same time to...
@ RMO_NONE
Only confirmed, non-DV direct neighbours.
@ RMO_ANYTHING_GOES
Reliable and unreliable, DV and non-DV are all acceptable.
static int notify_client_queues(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new MONITOR client about all existing queues to peers.
static struct AddressListEntry * create_address_entry(struct TransportClient *tc, struct GNUNET_TIME_Relative expiration, enum GNUNET_NetworkType nt, const char *address, uint32_t aid, size_t slen)
static void extract_box_cb(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void backtalker_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a backtalker by PEERSTORE.
static void queue_burst(void *cls)
static void handle_monitor_start(void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
Initialize a monitor client.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static void finish_cmc_handling(struct CommunicatorMessageContext *cmc)
static int learn_dv_path(const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
We have learned a path through the network to some other peer, add it to our DV data structure (retur...
static void store_pi(void *cls)
Ask peerstore to store our address.
#define FC_NO_CHANGE_REPLY_PROBABILITY
What is the 1:n chance that we send a Flow control response when receiving a flow control message tha...
static void notify_monitors(const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Send information in me about a peer's status with respect to some address to all monitors that care.
static struct GNUNET_TIME_Relative route_via_neighbour(const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Pick a queue of n under constraints options and schedule transmission of hdr.
#define RECV_WINDOW_SIZE
Window size.
static int check_known_challenge(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the challenge from cls.
static unsigned int check_for_queue_with_higher_prio(struct Queue *queue, struct Queue *queue_head)
Check if the communicator has another queue with higher prio ready for sending.
#define GOODPUT_AGING_SLOTS
Number of slots we keep of historic data for computation of goodput / message loss ratio.
static int free_validation_state_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free validation state.
static int free_neighbour_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free neighbour entry.
static void handle_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static void sign_dv_init_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
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 void dv_hmac(const struct DVKeyState *key, struct GNUNET_HashCode *hmac, const void *data, size_t data_size)
Do HMAC calculation for backchannel messages over data using key material from key.
static struct PilsRequest * pils_requests_head
PILS Operation DLL.
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT
How many messages can we have pending for a given communicator process before we start to throttle th...
static void free_reassembly_context(struct ReassemblyContext *rc)
Free rc.
static struct VirtualLink * lookup_virtual_link(const struct GNUNET_PeerIdentity *pid)
Lookup virtual link for peer pid.
static int check_connection_quality(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counte...
static void reorder_root_pm(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
static void core_env_sent_cb(void *cls)
Function called when we are done giving a message of a certain size to CORE and should thus decrement...
static unsigned int ir_total
Length of the DLL starting at ir_head.
static int in_shutdown
Indication if we have received a shutdown signal and are in the process of cleaning up.
static void select_best_pending_from_link(struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
Select the best pending message from vl for transmission via queue.
static void suggest_to_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Signature of a function called with a communicator address of a peer pid that an application wants us...
static void free_timedout_queue_entry(void *cls)
static void sign_t_validation_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
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...
#define RING_BUFFER_SIZE
Size of ring buffer to cache CORE and forwarded DVBox messages.
static struct GNUNET_PeerIdentity * GST_my_identity
Our public key.
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.
static void sign_dhp_cp(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void handle_suggest_cancel(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void update_performance_data(struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully tran...
static void forward_dv_box(struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
Create a DV Box message and queue it for transmission to next_hop.
static void handle_validation_response(void *cls, const struct TransportValidationResponseMessage *tvr)
Communicator gave us a transport address validation response.
static void handle_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void send_msg_from_cache(struct VirtualLink *vl)
static void free_address_list_entry(struct AddressListEntry *ale)
Free ale.
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)
static struct PilsRequest * pils_requests_tail
PILS Operation DLL.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Map from PIDs to struct Neighbour entries.
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 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 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 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 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 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 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 struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static struct GNUNET_SCHEDULER_Task * burst_task
The task to start the burst.
void print_address_list(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_TIME_Relative encapsulate_for_dv(struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
Pick a path of dv under constraints options and schedule transmission of hdr.
static void neighbour_store_dvmono_cb(void *cls, int success)
Function called when peerstore is done storing a DV monotonic time.
static void handle_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
A client encountered an address of another peer.
static void free_queue_entry(struct QueueEntry *qe, struct TransportClient *tc)
static void pils_sign_hello_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Get HELLO signature and create message to store in PEERSTORE.
static void check_for_global_natted_sync_cb(void *cls)
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 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 dv_setup_key_state_from_km(const struct GNUNET_ShortHashCode *km, const struct GNUNET_ShortHashCode *iv, struct DVKeyState *key)
Given the key material in km and the initialization vector iv, setup the key material for the backcha...
static void handle_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void handle_hello_for_incoming(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void 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 sign_dv_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void dv_encrypt(struct DVKeyState *key, const void *in, void *dst, size_t in_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
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 int free_dv_routes_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free DV route entry.
static enum GNUNET_GenericReturnValue add_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR
Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope...
static void handle_queue_create_fail(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue failed.
static void check_link_down(void *cls)
Task run to check whether the hops of the cls still are validated, or if we need to core about discon...
static void check_for_global_natted_error_cb(void *cls)
static void finish_cmc_handling_with_continue(struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
Send ACK to communicator (if requested) and free cmc.
static void forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
Build and forward a DV learn message to next_hop.
static void handle_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Incoming message.
static void validation_transmit_on_queue(struct Queue *q, struct ValidationState *vs)
The queue q (which matches the peer and address in vs) is ready for queueing.
static int free_ack_cummulator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free acknowledgement cummulator.
static void update_pm_next_attempt(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission ...
#define PILS_FEED_ADDRESSES_DELAY
Delay between added/removed addresses and PILS feed call.
static int check_known_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the address from cls.
enum GNUNET_GenericReturnValue use_burst
static struct GNUNET_CONTAINER_MultiPeerMap * dv_routes
Map from PIDs to struct DistanceVector entries describing known paths to the peer.
static struct GNUNET_TIME_Relative route_control_message_without_fc(struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
We need to transmit hdr to target.
static void free_incoming_request(struct IncomingRequest *ir)
Release ir data structure.
#define MAX_INCOMING_REQUEST
For how many incoming connections do we try to create a virtual link for (at the same time!...
static void neighbour_dv_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a DV initiator by PEERSTORE.
static struct GNUNET_PILS_Handle * pils
Service that manages our peer id.
void(* DVMessageHandler)(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void decaps_dv_box_cb(void *cls, const struct GNUNET_ShortHashCode *km)
static char * get_address_without_port(const char *address)
Get the IP address without 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.
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.
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.
static unsigned int bsize
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
static struct GNUNET_OS_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
Helper library for handling HELLO URIs.
API to the peerstore service.
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:367
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:390
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:575
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:495
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_by_peer_identity(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_SignaturePurpose *purpose, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Sign data with the peer id.
Definition pils_api.c:428
struct GNUNET_PILS_Operation * GNUNET_PILS_kem_decaps(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, GNUNET_PILS_DecapsResultCallback cb, void *cb_cls)
Decaps an encapsulated key with our private key.
Definition pils_api.c:468
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:541
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_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".
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
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.
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#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:41
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
#define GNUNET_CRYPTO_hkdf_expand(result, out_len, prk,...)
HKDF-Expand using SHA256.
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.
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:379
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg)
Parse msg.
Definition hello-uri.c:415
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:397
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:343
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:956
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:360
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:975
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:903
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:1330
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:932
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:353
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
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:624
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:1062
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:1142
#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)
#define GNUNET_CRYPTO_kdf_arg_string(d)
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.
#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_CRYPTO_kdf_arg_auto(d)
#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.
#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:305
#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 ...
#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)
enum GNUNET_GenericReturnValue GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition mq.c:205
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition mq.c:655
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:896
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
@ 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).
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_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_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_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_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2527
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2462
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2433
@ 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:1623
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
#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:604
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
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:665
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition peer.c:68
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
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition socks.c:330
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.
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.
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.
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().
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.
unsigned int continue_send
Did we already call GNUNET_SERVICE_client_continue and send ACK to communicator?
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
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:89
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition transport.h:112
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.
Structure of the key material used to encrypt backchannel messages.
struct DVKeyState::@70 material
Actual key material.
struct GNUNET_CRYPTO_AuthKey hmac_key
Key used for HMAC calculations (via GNUNET_CRYPTO_hmac()).
gcry_cipher_hd_t cipher
State of our block cipher.
char aes_key[256/8]
Symmetric key to use for encryption.
char aes_ctr[128/8]
Counter value to use during setup.
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.
const struct TransportDVBoxMessage * dvb
struct PilsRequest * pr
struct CommunicatorMessageContext * cmc
Message from the transport service to the library informing about disconnects.
Definition transport.h:121
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:807
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 (message) authentication keys
Type of a nonce used for challenges.
struct GNUNET_ShortHashCode value
The value of the nonce.
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:184
Context for parsing HELLOs.
Definition hello-uri.c:232
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:82
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:288
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
Definition transport.h:292
struct GNUNET_TIME_RelativeNBO expiration
When does the address expire?
Definition transport.h:302
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:307
uint32_t aid
Address identifier (used during deletion).
Definition transport.h:297
Add queue to the transport.
Definition transport.h:402
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:421
uint32_t mtu
Maximum transmission unit, in NBO.
Definition transport.h:426
uint64_t q_len
Queue length, in NBO.
Definition transport.h:432
uint32_t qid
Queue identifier (used to identify the queue).
Definition transport.h:411
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:416
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
Definition transport.h:406
uint32_t cs
An enum GNUNET_TRANSPORT_ConnectionStatus in NBO.
Definition transport.h:442
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
Definition transport.h:268
uint32_t cc
NBO encoding of enum GNUNET_TRANSPORT_CommunicatorCharacteristics
Definition transport.h:273
uint32_t can_burst
The communicator can do burst msgs.
Definition transport.h:278
Message from transport to communicator passing along a backchannel message from the given peer pid.
Definition transport.h:656
struct GNUNET_PeerIdentity pid
Origin peer.
Definition transport.h:671
Message from communicator to transport service asking for transmission of a backchannel message with ...
Definition transport.h:627
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL.
Definition transport.h:631
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:641
Communicator tells transport how queue creation went down.
Definition transport.h:546
uint32_t request_id
Unique ID for the request.
Definition transport.h:556
Transport tells communicator that it wants a new queue.
Definition transport.h:522
uint32_t request_id
Unique ID for the request.
Definition transport.h:531
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:536
Remove address from the list.
Definition transport.h:317
uint32_t aid
Address identifier.
Definition transport.h:326
Remove queue, it is no longer available.
Definition transport.h:500
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:514
uint32_t qid
Address identifier.
Definition transport.h:509
Transport informs us about being done with an incoming message.
Definition transport.h:375
struct GNUNET_PeerIdentity sender
Sender identifier of the original message.
Definition transport.h:394
uint64_t fc_id
Which message is being ACKed?
Definition transport.h:389
uint32_t reserved
Reserved (0)
Definition transport.h:384
Inform transport about an incoming message.
Definition transport.h:334
struct GNUNET_PeerIdentity neighbour_sender
Direct neighbour sender identifier.
Definition transport.h:364
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:354
struct GNUNET_PeerIdentity sender
Sender identifier.
Definition transport.h:359
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
Definition transport.h:338
uint32_t fc_on
Do we use flow control or not?
Definition transport.h:343
uint64_t fc_id
64-bit number to identify the matching ACK.
Definition transport.h:348
uint32_t num_msg_pending
Messages pending (in NBO).
Definition transport.h:767
struct GNUNET_PeerIdentity peer
Target identifier.
Definition transport.h:745
struct GNUNET_TIME_AbsoluteNBO valid_until
Definition transport.h:751
struct GNUNET_TIME_AbsoluteNBO last_validation
Definition transport.h:750
uint32_t num_bytes_pending
Bytes pending (in NBO).
Definition transport.h:772
struct GNUNET_TIME_AbsoluteNBO next_validation
Definition transport.h:752
uint32_t nt
Network type (an enum GNUNET_NetworkType in NBO).
Definition transport.h:740
struct GNUNET_TIME_RelativeNBO rtt
Current round-trip time estimate.
Definition transport.h:757
uint32_t cs
Connection status (in NBO).
Definition transport.h:762
Request to start monitoring.
Definition transport.h:709
Inform transport that message was sent.
Definition transport.h:593
uint64_t mid
Message ID of the original message.
Definition transport.h:607
uint32_t qid
Queue ID for the queue which was used to send the message.
Definition transport.h:612
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:617
Inform communicator about transport's desire to send a message.
Definition transport.h:564
uint32_t qid
Which queue should we use?
Definition transport.h:573
uint64_t mid
Message ID, used for flow control.
Definition transport.h:578
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
Definition transport.h:568
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:583
Message from transport to communicator to start a burst.
Definition transport.h:681
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST.
Definition transport.h:685
struct GNUNET_TIME_RelativeNBO rtt
Definition transport.h:692
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:690
A UUID, a 128 bit "random" value.
Message used to notify the transport API about a message received from the network.
Definition transport.h:144
struct GNUNET_PeerIdentity peer
Which peer sent the message?
Definition transport.h:153
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...
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_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:230
uint32_t priority
An enum GNUNET_MQ_PriorityPreferences in NBO.
Definition transport.h:239
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND.
Definition transport.h:234
struct GNUNET_PeerIdentity peer
Which peer should receive the message?
Definition transport.h:253
Information per peer and request.
struct GNUNET_BANDWIDTH_Value32NBO bw
How much bandwidth would this tc like to see?
struct TransportClient * tc
Client responsible for the request.
enum GNUNET_MQ_PriorityPreferences pk
What kind of performance preference does this tc have?
struct GSF_PendingRequest * pr
Handle to generic request (generic: from peer or local client).
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
Data structure kept when we are waiting for an acknowledgement.
struct AcknowledgementUUIDP ack_uuid
Unique identifier for this transmission operation.
unsigned int num_send
How often the PendingMessage was send via the Queue of this PendingAcknowledgement.
struct PendingAcknowledgement * next_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingMessage * pm
Message that was transmitted, may be NULL if the message was ACKed via another channel.
struct PendingAcknowledgement * next_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
struct PendingAcknowledgement * next_pa
Pointers for the DLL of all pending acknowledgements.
struct PendingAcknowledgement * next_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct GNUNET_TIME_Absolute transmission_time
Time of the transmission, for RTT calculation.
struct Queue * queue
Queue used for transmission, NULL if the queue has been destroyed (which may happen before we get an ...
struct DistanceVectorHop * dvh
Distance vector path chosen for this transmission, NULL if transmission was to a direct neighbour OR ...
uint16_t message_size
Number of bytes of the original message (to calculate bandwidth).
struct PendingAcknowledgement * prev_pa
Pointers for the DLL of all pending acknowledgements.
struct PendingAcknowledgement * prev_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct PendingAcknowledgement * prev_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingAcknowledgement * prev_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
Context for select_best_pending_from_link().
struct GNUNET_TIME_Relative to_early_retry_delay
When will we try to transmit the message again for which it was to early to retry.
struct PendingMessage * best
Set to the best message that was found, NULL for none.
int to_early
There are pending messages, but it was to early to send one of them.
unsigned int consideration_counter
Number of pending messages we seriously considered this time.
struct DistanceVectorHop * dvh
DVH that best should take, or NULL for direct transmission.
size_t real_overhead
What is the estimated total overhead for this message?
unsigned int frags_in_flight
There is a pending messages we are sending fragments at the moment.
int frag
Did we have to fragment?
int relb
Did we have to reliability box?
List containing all messages that are yet to be send.
struct PendingMessage * tail_frag
Tail of a MDLL of fragments created for this core message.
struct PendingMessage * frag_parent
Our parent in the fragmentation tree.
enum GNUNET_MQ_PriorityPreferences prefs
Preferences for this message.
struct TransportClient * client
Client that issued the transmission request, if pmt is PMT_CORE.
struct QueueEntry * qe
Set to non-NULL value if this message is currently being given to a communicator and we are awaiting ...
struct MessageUUIDP msg_uuid
UUID to use for this message (used for reassembly of fragments, only initialized if msg_uuid_set is G...
struct PendingMessage * head_frag
Head of a MDLL of fragments created for this core message.
uint16_t bytes_msg
Size of the original message.
enum PendingMessageType pmt
Type of the pending message.
struct PendingMessage * prev_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
struct PendingMessage * prev_vl
Kept in a MDLL of messages for this vl.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs for this pending message.
struct PendingMessage * next_vl
Kept in a MDLL of messages for this vl.
struct VirtualLink * vl
Target of the request (always the ultimate destination!).
struct PendingAcknowledgement * pa_head
Head of DLL of PAs for this pending message.
struct DistanceVectorHop * used_dvh
If pmt is of type PMT_DV_BOX we store the used path here.
int16_t msg_uuid_set
GNUNET_YES once msg_uuid was initialized
uint32_t frags_in_flight_round
The round we are (re)-sending fragments.
struct PendingMessage * next_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
uint32_t frags_in_flight
Are we sending fragments at the moment?
uint16_t frag_off
Offset at which we should generate the next fragment.
struct PendingMessage * next_frag
Kept in a MDLL of messages from this cpm (if pmt is #PMT_FRAGMENT_BOx)
uint64_t logging_uuid
UUID we use to identify this message in our logs.
uint16_t frag_count
How many fragments do we have?
struct PendingMessage * prev_frag
Kept in a MDLL of messages from this cpm (if pmt is PMT_FRAGMENT_BOX)
struct PendingMessage * bpm
This message, reliability or DV-boxed.
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:206
struct GNUNET_PeerIdentity peer
Which peer can CORE handle more from now?
Definition transport.h:221
uint32_t increase_window_delta
Number of messages by which to increase the window, greater or equal to one.
Definition transport.h:216
We got an address of another peer, TRANSPORT service should validate it.
Definition transport.h:838
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:162
struct GNUNET_PeerIdentity peer
Which peer can send more now?
Definition transport.h:196
struct DVPathEntryP * dhops
struct PilsRequest * pr
struct TransportDVLearnMessage * fwd
const struct GNUNET_PeerIdentity * next_hop
struct PilsRequest * req
struct DistanceVector * dv
struct PilsRequest * pr
struct QueueQualityContext qqc
struct TransportDVLearnMessage dvl
struct LearnLaunchEntry * lle
struct TransportValidationResponseMessage tvr
struct CommunicatorMessageContext * cmc
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:62
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.
struct TransportClient::@65::@69 application
Information for type CT_APPLICATION.
struct TransportClient * next
Kept in a DLL.
struct TransportClient::@65::@67 monitor
Information for type CT_MONITOR.
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 Queue * queue_head
Head of DLL of queues offered by this communicator.
struct TransportClient::@65::@68 communicator
Information for type CT_COMMUNICATOR.
union TransportClient::@65 details
struct AddressListEntry * addr_head
Head of list of the addresses of this peer offered by this communicator.
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.
char * address_prefix
If type is CT_COMMUNICATOR, this communicator supports communicating using these addresses.
struct TransportClient::@65::@66 core
Information for type CT_CORE.
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_HashCode hmac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
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.
unsigned int without_fc
Flag if the payload is a control message.
struct GNUNET_ShortHashCode iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
uint16_t total_hops
Number of total hops this messages travelled.
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.
unsigned int number_of_addresses
Number of TransportGlobalNattedAddress following the struct.
size_t size_of_addresses
Size of all the addresses attached to all TransportGlobalNattedAddress.
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.
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.
unsigned int 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.
unsigned int 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