GNUnet 0.21.2
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"
80#include "gnunet_nat_service.h"
82#include "gnunet_signatures.h"
83#include "transport.h"
84
88#define RING_BUFFER_SIZE 16
89
93#define MAX_FC_RETRANSMIT_COUNT 1000
94
99#define MAX_CUMMULATIVE_ACKS 64
100
113#define FC_NO_CHANGE_REPLY_PROBABILITY 8
114
119#define IN_PACKET_SIZE_WITHOUT_MTU 128
120
125#define GOODPUT_AGING_SLOTS 4
126
131#define DEFAULT_WINDOW_SIZE (128 * 1024)
132
141#define MAX_INCOMING_REQUEST 16
142
147#define MAX_DV_DISCOVERY_SELECTION 16
148
157#define RECV_WINDOW_SIZE 4
158
166#define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
167
171#define MAX_DV_HOPS_ALLOWED 16
172
177#define MAX_DV_LEARN_PENDING 64
178
182#define MAX_DV_PATHS_TO_TARGET 3
183
189#define DELAY_WARN_THRESHOLD \
190 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
191
196#define DV_FORWARD_TIMEOUT \
197 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
198
202#define DEFAULT_ACK_WAIT_DURATION \
203 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
204
210#define DV_QUALITY_RTT_THRESHOLD \
211 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
212
217#define DV_PATH_VALIDITY_TIMEOUT \
218 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
219
224#define BACKCHANNEL_INACTIVITY_TIMEOUT \
225 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
226
231#define DV_PATH_DISCOVERY_FREQUENCY \
232 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
233
237#define EPHEMERAL_VALIDITY \
238 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
239
243#define REASSEMBLY_EXPIRATION \
244 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
245
250#define FAST_VALIDATION_CHALLENGE_FREQ \
251 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
252
256#define MAX_VALIDATION_CHALLENGE_FREQ \
257 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
258
264#define ACK_CUMMULATOR_TIMEOUT \
265 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
266
271#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
272
277#define DV_LEARN_QUALITY_THRESHOLD 100
278
282#define MAX_ADDRESS_VALID_UNTIL \
283 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
284
288#define ADDRESS_VALIDATION_LIFETIME \
289 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
290
297#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
298
305#define VALIDATION_RTT_BUFFER_FACTOR 3
306
313#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
314
320#define QUEUE_LENGTH_LIMIT 32
321
325#define QUEUE_ENTRY_TIMEOUT \
326 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
327
328
330
335{
341};
342
343
348{
353};
354
359{
364
365 /* Followed by *another* message header which is the message to
366 the communicator */
367
368 /* Followed by a 0-terminated name of the communicator */
369};
370
371
376{
381
397
402
408};
409
410
416{
421
427
439
440 /* Followed by a `struct GNUNET_MessageHeader` with a message
441 for the target peer */
442};
443
444
450{
455
463
470};
471
472
477{
485
490};
491
492
501{
506
512
513 /* followed by any number of `struct TransportCummulativeAckPayloadP`
514 messages providing ACKs */
515};
516
517
522{
527
532
537
546
552};
553
554
573{
578
592
597};
598
599
617{
622
627
632
637};
638
639
645{
650
656};
657
658
673{
678
684
694
701
715
721
726
731
732 /* Followed by @e num_hops `struct DVPathEntryP` values,
733 excluding the initiator of the DV trace; the last entry is the
734 current sender; the current peer must not be included. */
735};
736
737
761{
766
770 unsigned int without_fc;
771
779
786
792
799
806
813
814 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
815 excluding the @e origin and the current peer, the last must be
816 the ultimate target; if @e num_hops is zero, the receiver of this
817 message is the ultimate target. */
818
819 /* Followed by encrypted, variable-size payload, which
820 must begin with a `struct TransportDVBoxPayloadP` */
821
822 /* Followed by the actual message, which itself must not be a
823 a DV_LEARN or DV_BOX message! */
824};
825
826
832{
837
842
847
853};
854
855
861{
866
872
877};
878
879
885{
890
895
901
906
911 struct GNUNET_TIME_AbsoluteNBO origin_time;
912
917 struct GNUNET_TIME_RelativeNBO validity_duration;
918};
919
921{
925 unsigned int address_length;
926
927 /* Followed by @e address_length bytes of the address. */
928};
929
939{
944
953
959
966
976
986
987
992
997
998 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
999};
1000
1002
1003
1008{
1013
1018
1023
1028
1032 CT_APPLICATION = 4
1034
1035
1041{
1046
1051
1056
1061
1067 RMO_REDUNDANT = 4
1069
1070
1075{
1080
1085
1090
1096};
1097
1098
1104{
1108 uint64_t bytes_sent;
1109
1115};
1116
1117
1122{
1127
1133
1138 unsigned int last_age;
1139};
1140
1141
1145struct TransportClient;
1146
1150struct Neighbour;
1151
1156struct DistanceVector;
1157
1162struct Queue;
1163
1167struct PendingMessage;
1168
1172struct DistanceVectorHop;
1173
1182struct VirtualLink;
1183
1184
1190{
1196
1202
1207
1212
1217
1222 uint16_t total_hops;
1223
1227 unsigned int continue_send;
1228};
1229
1230
1235{
1240
1245};
1246
1247
1252{
1257
1262
1267
1271 uint16_t size;
1272
1279 uint16_t isize;
1280};
1281
1282
1287{
1293
1298
1303
1311 uint8_t *bitfield;
1312
1317
1323
1327 uint16_t msg_size;
1328
1333 uint16_t msg_missing;
1334
1335 /* Followed by @e msg_size bytes of the (partially) defragmented original
1336 * message */
1337
1338 /* Followed by @e bitfield data */
1339};
1340
1341
1351{
1356
1363
1370
1375
1381
1387
1392
1397
1402
1407
1415
1421
1426
1431 unsigned int confirmed;
1432
1436 struct Neighbour *n;
1437
1442
1449
1456
1465
1471
1477
1486
1494
1501
1510
1523
1529
1536
1547
1552 uint32_t fc_seq_gen;
1553
1559 uint32_t last_fc_seq;
1560
1573};
1574
1575
1580{
1586
1592
1599
1606
1613
1620
1627
1634
1639
1645
1651
1656 struct Queue *queue;
1657
1662
1667
1671 unsigned int num_send;
1672};
1673
1674
1679{
1684
1689
1694
1699
1704
1709
1714
1719
1726
1732
1741
1746
1752 unsigned int distance;
1753};
1754
1755
1761{
1766
1771
1776
1781
1787
1793
1798
1803
1808
1813};
1814
1815
1826{
1831
1836
1840 struct Queue *queue;
1841
1846
1850 uint64_t mid;
1851
1856};
1857
1858
1863struct Queue
1864{
1869
1874
1879
1884
1889
1894
1899
1904
1909
1914
1918 const char *address;
1919
1923 unsigned int unlimited_length;
1924
1930
1939
1944
1950
1955 uint64_t mid_gen;
1956
1960 uint32_t qid;
1961
1965 uint32_t mtu;
1966
1971
1976
1980 unsigned int queue_length;
1981
1985 uint64_t q_capacity;
1986
1990 uint32_t priority;
1991
1996
2001
2006 int idle;
2007
2012};
2013
2014
2019{
2024
2030
2036
2041
2046
2052
2058
2064
2070
2076
2081
2086
2091
2096};
2097
2098
2104{
2109
2114
2119
2124};
2125
2126
2130struct PeerRequest
2131{
2136
2141
2146
2153
2158};
2159
2160
2165{
2170
2175
2180
2184 PMT_DV_BOX = 3
2186
2187
2214struct PendingMessage
2215{
2220
2225
2230
2235
2241
2247
2252
2257
2263
2269
2274
2284
2289
2294
2299
2304
2309
2314
2320
2326
2331
2337
2342
2346 uint16_t bytes_msg;
2347
2351 uint16_t frag_off;
2352
2357
2362
2366 uint16_t frag_count;
2367
2372
2373 /* Followed by @e bytes_msg to transmit */
2374};
2375
2376
2381{
2387
2392};
2393
2394
2400{
2405
2410
2417
2422
2428 uint32_t ack_counter;
2429
2433 unsigned int num_acks;
2434};
2435
2436
2441{
2446
2451
2456
2461
2465 const char *address;
2466
2471
2476
2481
2486
2492
2496 uint32_t aid;
2497
2502};
2503
2504
2509{
2514
2519
2524
2529
2534
2535 union
2536 {
2540 struct
2541 {
2547
2553
2557 struct
2558 {
2565
2571
2572
2576 struct
2577 {
2583
2588
2593
2599
2605
2612
2617
2623
2627 struct
2628 {
2636};
2637
2638
2644{
2650
2658
2664
2671 struct GNUNET_TIME_Absolute first_challenge_use;
2672
2679 struct GNUNET_TIME_Absolute last_challenge_use;
2680
2688 struct GNUNET_TIME_Absolute next_challenge;
2689
2698 struct GNUNET_TIME_Relative challenge_backoff;
2699
2704 struct GNUNET_TIME_Relative validation_rtt;
2705
2713 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2714
2718 struct GNUNET_HashCode hc;
2719
2723 struct GNUNET_SCHEDULER_Task *revalidation_task;
2724
2728 char *address;
2729
2735 struct GNUNET_CONTAINER_HeapNode *hn;
2736
2742
2748 uint32_t last_window_consum_limit;
2749
2754 int awaiting_queue;
2755};
2756
2757
2765{
2770
2775
2780
2785
2791
2796
2802
2808
2814};
2815
2820
2824static unsigned int ring_buffer_head;
2825
2829static unsigned int is_ring_buffer_full;
2830
2835
2839static unsigned int ring_buffer_dv_head;
2840
2844static unsigned int is_ring_buffer_dv_full;
2845
2850
2855
2860
2865
2870
2875
2880
2886
2892
2898
2904
2910
2916
2922
2928
2933
2937static struct LearnLaunchEntry *lle_head = NULL;
2938
2942static struct LearnLaunchEntry *lle_tail = NULL;
2943
2950
2955
2960
2965
2970
2977
2982
2986static unsigned int ir_total;
2987
2991static unsigned long long logging_uuid_gen;
2992
3002
3007static int in_shutdown;
3008
3019static unsigned int
3021{
3022 struct GNUNET_TIME_Absolute now;
3023
3024 now = GNUNET_TIME_absolute_get ();
3025 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3026}
3027
3028
3034static void
3036{
3038 GNUNET_assert (ir_total > 0);
3039 ir_total--;
3040 if (NULL != ir->nc)
3042 ir->nc = NULL;
3043 GNUNET_free (ir);
3044}
3045
3046
3052static void
3054{
3055 struct Queue *q = pa->queue;
3056 struct PendingMessage *pm = pa->pm;
3057 struct DistanceVectorHop *dvh = pa->dvh;
3058
3060 "free_pending_acknowledgement\n");
3061 if (NULL != q)
3062 {
3063 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3064 pa->queue = NULL;
3065 }
3066 if (NULL != pm)
3067 {
3069 "remove pa from message\n");
3071 "remove pa from message %" PRIu64 "\n",
3072 pm->logging_uuid);
3074 "remove pa from message %u\n",
3075 pm->pmt);
3077 "remove pa from message %s\n",
3079 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3080 pa->pm = NULL;
3081 }
3082 if (NULL != dvh)
3083 {
3084 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3085 pa->queue = NULL;
3086 }
3089 &pa->ack_uuid.value,
3090 pa));
3091 GNUNET_free (pa);
3092}
3093
3094
3103static void
3105{
3106 struct PendingMessage *frag;
3107
3108 while (NULL != (frag = root->head_frag))
3109 {
3110 struct PendingAcknowledgement *pa;
3111
3112 free_fragment_tree (frag);
3113 while (NULL != (pa = frag->pa_head))
3114 {
3115 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3116 pa->pm = NULL;
3117 }
3118 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3119 if (NULL != frag->qe)
3120 {
3121 GNUNET_assert (frag == frag->qe->pm);
3122 frag->qe->pm = NULL;
3123 }
3125 "Free frag %p\n",
3126 frag);
3127 GNUNET_free (frag);
3128 }
3129}
3130
3131
3139static void
3141{
3142 struct TransportClient *tc = pm->client;
3143 struct VirtualLink *vl = pm->vl;
3144 struct PendingAcknowledgement *pa;
3145
3147 "Freeing pm %p\n",
3148 pm);
3149 if (NULL != tc)
3150 {
3152 tc->details.core.pending_msg_head,
3153 tc->details.core.pending_msg_tail,
3154 pm);
3155 }
3156 if ((NULL != vl) && (NULL == pm->frag_parent))
3157 {
3159 "Removing pm %" PRIu64 "\n",
3160 pm->logging_uuid);
3162 vl->pending_msg_head,
3163 vl->pending_msg_tail,
3164 pm);
3165 }
3166 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3167 {
3168 struct PendingMessage *root = pm->frag_parent;
3169
3170 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3171 root = root->frag_parent;
3172
3173 root->frag_count--;
3174 }
3175 while (NULL != (pa = pm->pa_head))
3176 {
3177 if (NULL == pa)
3179 "free pending pa null\n");
3180 if (NULL == pm->pa_tail)
3182 "free pending pa_tail null\n");
3183 if (NULL == pa->prev_pa)
3185 "free pending pa prev null\n");
3186 if (NULL == pa->next_pa)
3188 "free pending pa next null\n");
3189 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3190 pa->pm = NULL;
3191 }
3192
3194 if (NULL != pm->qe)
3195 {
3196 GNUNET_assert (pm == pm->qe->pm);
3197 pm->qe->pm = NULL;
3198 }
3199 if (NULL != pm->bpm)
3200 {
3201 free_fragment_tree (pm->bpm);
3202 if (NULL != pm->bpm->qe)
3203 {
3204 struct QueueEntry *qe = pm->bpm->qe;
3205
3206 qe->pm = NULL;
3207 }
3208 GNUNET_free (pm->bpm);
3209 }
3210
3211 GNUNET_free (pm);
3213 "Freeing pm done\n");
3214}
3215
3216
3222static void
3224{
3225 struct VirtualLink *vl = rc->virtual_link;
3226
3230 rc->msg_uuid.uuid,
3231 rc));
3232 GNUNET_free (rc);
3233}
3234
3235
3241static void
3243{
3244 struct VirtualLink *vl = cls;
3245 struct ReassemblyContext *rc;
3246
3247 vl->reassembly_timeout_task = NULL;
3248 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3249 {
3251 .rel_value_us)
3252 {
3254 continue;
3255 }
3260 vl);
3261 return;
3262 }
3263}
3264
3265
3274static int
3275free_reassembly_cb (void *cls, uint32_t key, void *value)
3276{
3277 struct ReassemblyContext *rc = value;
3278
3279 (void) cls;
3280 (void) key;
3282 return GNUNET_OK;
3283}
3284
3285
3291static void
3293{
3294 struct PendingMessage *pm;
3295 struct CoreSentContext *csc;
3296
3298 "free virtual link %p\n",
3299 vl);
3300
3301 if (NULL != vl->reassembly_map)
3302 {
3305 NULL);
3307 vl->reassembly_map = NULL;
3309 vl->reassembly_heap = NULL;
3310 }
3311 if (NULL != vl->reassembly_timeout_task)
3312 {
3315 }
3316 while (NULL != (pm = vl->pending_msg_head))
3320 if (NULL != vl->visibility_task)
3321 {
3323 vl->visibility_task = NULL;
3324 }
3325 if (NULL != vl->fc_retransmit_task)
3326 {
3328 vl->fc_retransmit_task = NULL;
3329 }
3330 while (NULL != (csc = vl->csc_head))
3331 {
3333 GNUNET_assert (vl == csc->vl);
3334 csc->vl = NULL;
3335 }
3336 GNUNET_break (NULL == vl->n);
3337 GNUNET_break (NULL == vl->dv);
3338 GNUNET_free (vl);
3339}
3340
3341
3347static void
3349{
3350 if (NULL != vs->revalidation_task)
3351 {
3352 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3353 vs->revalidation_task = NULL;
3354 }
3355 /*memcpy (&hkey,
3356 &hc,
3357 sizeof (hkey));*/
3359 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3360 GNUNET_h2s (&vs->hc),
3361 vs->address,
3364 &vs->hc));
3367 GNUNET_YES ==
3370 vs->hn = NULL;
3371 if (NULL != vs->sc)
3372 {
3374 "store cancel\n");
3376 vs->sc = NULL;
3377 }
3378 GNUNET_free (vs->address);
3379 GNUNET_free (vs);
3380}
3381
3382
3389static struct Neighbour *
3391{
3393}
3394
3395
3402static struct VirtualLink *
3404{
3406}
3407
3408
3413{
3420
3425
3430
3435
3440};
3441
3442
3451static void
3453{
3454 struct Neighbour *n = dvh->next_hop;
3455 struct DistanceVector *dv = dvh->dv;
3456 struct PendingAcknowledgement *pa;
3457
3458 while (NULL != (pa = dvh->pa_head))
3459 {
3461 pa->dvh = NULL;
3462 }
3463 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3465 GNUNET_free (dvh);
3466}
3467
3468
3475static void
3476check_link_down (void *cls);
3477
3478
3484static void
3486{
3488 "Informing CORE clients about disconnect from %s\n",
3489 GNUNET_i2s (pid));
3490 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3491 {
3492 struct GNUNET_MQ_Envelope *env;
3493 struct DisconnectInfoMessage *dim;
3494
3495 if (CT_CORE != tc->type)
3496 continue;
3498 dim->peer = *pid;
3499 GNUNET_MQ_send (tc->mq, env);
3500 }
3501}
3502
3503
3510static void
3512{
3513 struct DistanceVectorHop *dvh;
3514
3515 while (NULL != (dvh = dv->dv_head))
3517 if (NULL == dv->dv_head)
3518 {
3519 struct VirtualLink *vl;
3520
3522 GNUNET_YES ==
3524 if (NULL != (vl = dv->vl))
3525 {
3526 GNUNET_assert (dv == vl->dv);
3527 vl->dv = NULL;
3528 if (NULL == vl->n)
3529 {
3531 free_virtual_link (vl);
3532 }
3533 else
3534 {
3537 }
3538 dv->vl = NULL;
3539 }
3540
3541 if (NULL != dv->timeout_task)
3542 {
3544 dv->timeout_task = NULL;
3545 }
3546 GNUNET_free (dv->km);
3547 GNUNET_free (dv);
3548 }
3549}
3550
3551
3565static void
3567 const struct GNUNET_PeerIdentity *peer,
3568 const char *address,
3570 const struct MonitorEvent *me)
3571{
3572 struct GNUNET_MQ_Envelope *env;
3574 size_t addr_len = strlen (address) + 1;
3575
3577 addr_len,
3579 md->nt = htonl ((uint32_t) nt);
3580 md->peer = *peer;
3581 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3582 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3583 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3584 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3585 md->cs = htonl ((uint32_t) me->cs);
3586 md->num_msg_pending = htonl (me->num_msg_pending);
3587 md->num_bytes_pending = htonl (me->num_bytes_pending);
3588 memcpy (&md[1], address, addr_len);
3589 GNUNET_MQ_send (tc->mq, env);
3590}
3591
3592
3602static void
3604 const char *address,
3606 const struct MonitorEvent *me)
3607{
3608 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3609 {
3610 if (CT_MONITOR != tc->type)
3611 continue;
3612 if (tc->details.monitor.one_shot)
3613 continue;
3614 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3615 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3616 continue;
3618 }
3619}
3620
3621
3631static void *
3633 struct GNUNET_SERVICE_Client *client,
3634 struct GNUNET_MQ_Handle *mq)
3635{
3636 struct TransportClient *tc;
3637
3638 (void) cls;
3639 tc = GNUNET_new (struct TransportClient);
3640 tc->client = client;
3641 tc->mq = mq;
3644 "Client %p of type %u connected\n",
3645 tc,
3646 tc->type);
3647 return tc;
3648}
3649
3650
3651static enum GNUNET_GenericReturnValue
3653 const struct GNUNET_PeerIdentity *pid,
3654 void *value)
3655{
3656 (void) cls;
3657 struct TransportGlobalNattedAddress *tgna = value;
3658
3659 GNUNET_free (tgna);
3660
3661 return GNUNET_OK;
3662}
3663
3664
3670static void
3671free_neighbour (struct Neighbour *neighbour)
3672{
3673 struct DistanceVectorHop *dvh;
3674 struct VirtualLink *vl;
3675
3676 GNUNET_assert (NULL == neighbour->queue_head);
3679 &neighbour->pid,
3680 neighbour));
3682 "Freeing neighbour\n");
3685 NULL);
3687 while (NULL != (dvh = neighbour->dv_head))
3688 {
3689 struct DistanceVector *dv = dvh->dv;
3690
3692 if (NULL == dv->dv_head)
3693 free_dv_route (dv);
3694 }
3695 if (NULL != neighbour->get)
3696 {
3698 neighbour->get = NULL;
3699 }
3700 if (NULL != neighbour->sc)
3701 {
3703 "store cancel\n");
3704 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3705 neighbour->sc = NULL;
3706 }
3707 if (NULL != (vl = neighbour->vl))
3708 {
3709 GNUNET_assert (neighbour == vl->n);
3710 vl->n = NULL;
3711 if (NULL == vl->dv)
3712 {
3715 }
3716 else
3717 {
3720 }
3721 neighbour->vl = NULL;
3722 }
3723 GNUNET_free (neighbour);
3724}
3725
3726
3733static void
3735 const struct GNUNET_PeerIdentity *pid)
3736{
3737 struct GNUNET_MQ_Envelope *env;
3738 struct ConnectInfoMessage *cim;
3739
3740 GNUNET_assert (CT_CORE == tc->type);
3742 cim->id = *pid;
3743 GNUNET_MQ_send (tc->mq, env);
3744}
3745
3746
3752static void
3754{
3756 "Informing CORE clients about connection to %s\n",
3757 GNUNET_i2s (pid));
3758 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3759 {
3760 if (CT_CORE != tc->type)
3761 continue;
3763 }
3764}
3765
3766
3774static void
3775transmit_on_queue (void *cls);
3776
3777
3781static unsigned int
3783{
3784 for (struct Queue *s = queue_head; NULL != s;
3785 s = s->next_client)
3786 {
3787 if (s->tc->details.communicator.address_prefix !=
3788 queue->tc->details.communicator.address_prefix)
3789 {
3791 "queue address %s qid %u compare with queue: address %s qid %u\n",
3792 queue->address,
3793 queue->qid,
3794 s->address,
3795 s->qid);
3796 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3797 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3798 return GNUNET_YES;
3800 "Lower prio\n");
3801 }
3802 }
3803 return GNUNET_NO;
3804}
3805
3806
3814static void
3816 struct Queue *queue,
3818{
3820
3821 if (queue->validated_until.abs_value_us < now.abs_value_us)
3822 return;
3824 queue->tc->details.communicator.
3825 queue_head))
3826 return;
3827
3828 if (queue->tc->details.communicator.total_queue_length >=
3830 {
3832 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3833 queue->address,
3834 queue->qid);
3836 GST_stats,
3837 "# Transmission throttled due to communicator queue limit",
3838 1,
3839 GNUNET_NO);
3840 queue->idle = GNUNET_NO;
3841 return;
3842 }
3843 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3844 {
3846 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3847 queue->address,
3848 queue->qid);
3850 "# Transmission throttled due to queue queue limit",
3851 1,
3852 GNUNET_NO);
3853 queue->idle = GNUNET_NO;
3854 return;
3855 }
3856 if (0 == queue->q_capacity)
3857 {
3859 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3860 PRIu64 ".\n",
3861 queue->address,
3862 queue->qid,
3863 queue->q_capacity);
3865 "# Transmission throttled due to message queue capacity",
3866 1,
3867 GNUNET_NO);
3868 queue->idle = GNUNET_NO;
3869 return;
3870 }
3871 /* queue might indeed be ready, schedule it */
3872 if (NULL != queue->transmit_task)
3873 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3874 queue->transmit_task =
3876 queue);
3878 "Considering transmission on queue `%s' QID %llu to %s\n",
3879 queue->address,
3880 (unsigned long long) queue->qid,
3881 GNUNET_i2s (&queue->neighbour->pid));
3882}
3883
3884
3891static void
3893{
3894 struct VirtualLink *vl = cls;
3895 struct DistanceVector *dv = vl->dv;
3896 struct Neighbour *n = vl->n;
3897 struct GNUNET_TIME_Absolute dvh_timeout;
3898 struct GNUNET_TIME_Absolute q_timeout;
3899
3901 "Checking if link is down\n");
3902 vl->visibility_task = NULL;
3903 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3904 if (NULL != dv)
3905 {
3906 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3907 pos = pos->next_dv)
3908 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
3909 pos->path_valid_until);
3910 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3911 {
3912 vl->dv->vl = NULL;
3913 vl->dv = NULL;
3914 }
3915 }
3916 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3917 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3918 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3919 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3920 {
3921 vl->n->vl = NULL;
3922 vl->n = NULL;
3923 }
3924 if ((NULL == vl->n) && (NULL == vl->dv))
3925 {
3927 free_virtual_link (vl);
3928 return;
3929 }
3930 vl->visibility_task =
3931 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3933 vl);
3934}
3935
3936
3942static void
3944{
3945 struct Neighbour *neighbour = queue->neighbour;
3946 struct TransportClient *tc = queue->tc;
3947 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
3949 struct QueueEntry *qe;
3950 int maxxed;
3951 struct PendingAcknowledgement *pa;
3952 struct VirtualLink *vl;
3953
3955 "Cleaning up queue %u\n", queue->qid);
3956 if (NULL != queue->mo)
3957 {
3959 queue->mo = NULL;
3960 }
3961 if (NULL != queue->transmit_task)
3962 {
3963 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3964 queue->transmit_task = NULL;
3965 }
3966 while (NULL != (pa = queue->pa_head))
3967 {
3968 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
3969 pa->queue = NULL;
3970 }
3971
3973 neighbour->queue_head,
3974 neighbour->queue_tail,
3975 queue);
3977 tc->details.communicator.queue_head,
3978 tc->details.communicator.queue_tail,
3979 queue);
3981 tc->details.communicator.total_queue_length);
3983 "Cleaning up queue with length %u\n",
3984 queue->queue_length);
3985 while (NULL != (qe = queue->queue_head))
3986 {
3987 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
3988 queue->queue_length--;
3989 tc->details.communicator.total_queue_length--;
3990 if (NULL != qe->pm)
3991 {
3992 GNUNET_assert (qe == qe->pm->qe);
3993 qe->pm->qe = NULL;
3994 }
3995 GNUNET_free (qe);
3996 }
3997 GNUNET_assert (0 == queue->queue_length);
3998 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
3999 tc->details.communicator.total_queue_length))
4000 {
4001 /* Communicator dropped below threshold, resume all _other_ queues */
4003 GST_stats,
4004 "# Transmission throttled due to communicator queue limit",
4005 -1,
4006 GNUNET_NO);
4007 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4008 s = s->next_client)
4010 s,
4012 }
4013 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4015
4016 vl = lookup_virtual_link (&neighbour->pid);
4017 if ((NULL != vl) && (neighbour == vl->n))
4018 {
4020 check_link_down (vl);
4021 }
4022 if (NULL == neighbour->queue_head)
4023 {
4024 free_neighbour (neighbour);
4025 }
4026}
4027
4028
4034static void
4036{
4037 struct TransportClient *tc = ale->tc;
4038
4039 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4040 tc->details.communicator.addr_tail,
4041 ale);
4042 if (NULL != ale->sc)
4043 {
4045 "store cancel\n");
4047 ale->sc = NULL;
4048 }
4049 if (NULL != ale->st)
4050 {
4052 ale->st = NULL;
4053 }
4054 if (NULL != ale->signed_address)
4056 GNUNET_free (ale);
4057}
4058
4059
4068static int
4070 const struct GNUNET_PeerIdentity *pid,
4071 void *value)
4072{
4073 struct TransportClient *tc = cls;
4074 struct PeerRequest *pr = value;
4075
4076 if (NULL != pr->nc)
4078 pr->nc = NULL;
4080 GNUNET_YES ==
4081 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4082 pid,
4083 pr));
4084 GNUNET_free (pr);
4085
4086 return GNUNET_OK;
4087}
4088
4089
4090static void
4091do_shutdown (void *cls);
4092
4101static void
4103 struct GNUNET_SERVICE_Client *client,
4104 void *app_ctx)
4105{
4106 struct TransportClient *tc = app_ctx;
4107
4108 (void) cls;
4109 (void) client;
4111 switch (tc->type)
4112 {
4113 case CT_NONE:
4115 "Unknown Client %p disconnected, cleaning up.\n",
4116 tc);
4117 break;
4118
4119 case CT_CORE: {
4121 "CORE Client %p disconnected, cleaning up.\n",
4122 tc);
4123
4124 struct PendingMessage *pm;
4125
4126 while (NULL != (pm = tc->details.core.pending_msg_head))
4127 {
4129 tc->details.core.pending_msg_head,
4130 tc->details.core.pending_msg_tail,
4131 pm);
4132 pm->client = NULL;
4133 }
4134 }
4135 break;
4136
4137 case CT_MONITOR:
4139 "MONITOR Client %p disconnected, cleaning up.\n",
4140 tc);
4141
4142 break;
4143
4144 case CT_COMMUNICATOR: {
4146 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4147 tc);
4148
4149 struct Queue *q;
4150 struct AddressListEntry *ale;
4151
4152 if (NULL != tc->details.communicator.free_queue_entry_task)
4154 tc->details.communicator.free_queue_entry_task);
4155 while (NULL != (q = tc->details.communicator.queue_head))
4156 free_queue (q);
4157 while (NULL != (ale = tc->details.communicator.addr_head))
4159 GNUNET_free (tc->details.communicator.address_prefix);
4160 }
4161 break;
4162
4163 case CT_APPLICATION:
4165 "APPLICATION Client %p disconnected, cleaning up.\n",
4166 tc);
4167
4168 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4170 tc);
4171 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4172 break;
4173 }
4174 GNUNET_free (tc);
4175 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4176 {
4178 "Our last client disconnected\n");
4179 do_shutdown (cls);
4180 }
4181}
4182
4183
4193static int
4195 const struct GNUNET_PeerIdentity *pid,
4196 void *value)
4197{
4198 struct TransportClient *tc = cls;
4199 struct VirtualLink *vl = value;
4200
4201 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4202 return GNUNET_OK;
4203
4205 "Telling new CORE client about existing connection to %s\n",
4206 GNUNET_i2s (pid));
4208 return GNUNET_OK;
4209}
4210
4211
4217static void
4219 unsigned
4220 int free_cmc);
4221
4222static enum GNUNET_GenericReturnValue
4224 const struct GNUNET_PeerIdentity *pid,
4225 void *value)
4226{
4227 struct VirtualLink *vl = value;
4228 struct CommunicatorMessageContext *cmc;
4229
4230 /* resume communicators */
4231 while (NULL != (cmc = vl->cmc_tail))
4232 {
4234 if (GNUNET_NO == cmc->continue_send)
4236 }
4237 return GNUNET_OK;
4238}
4239
4240
4249static void
4250handle_client_start (void *cls, const struct StartMessage *start)
4251{
4252 struct TransportClient *tc = cls;
4253 uint32_t options;
4254
4255 options = ntohl (start->options);
4256 if ((0 != (1 & options)) &&
4257 (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4258 {
4259 /* client thinks this is a different peer, reject */
4260 GNUNET_break (0);
4262 return;
4263 }
4264 if (CT_NONE != tc->type)
4265 {
4266 GNUNET_break (0);
4268 return;
4269 }
4270 tc->type = CT_CORE;
4272 "New CORE client with PID %s registered\n",
4273 GNUNET_i2s (&start->self));
4276 tc);
4279 NULL);
4281}
4282
4283
4290static int
4291check_client_send (void *cls, const struct OutboundMessage *obm)
4292{
4293 struct TransportClient *tc = cls;
4294 uint16_t size;
4295 const struct GNUNET_MessageHeader *obmm;
4296
4297 if (CT_CORE != tc->type)
4298 {
4299 GNUNET_break (0);
4300 return GNUNET_SYSERR;
4301 }
4302 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4303 if (size < sizeof(struct GNUNET_MessageHeader))
4304 {
4305 GNUNET_break (0);
4306 return GNUNET_SYSERR;
4307 }
4308 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4309 if (size != ntohs (obmm->size))
4310 {
4311 GNUNET_break (0);
4312 return GNUNET_SYSERR;
4313 }
4314 return GNUNET_OK;
4315}
4316
4317
4325static void
4327{
4328 struct TransportClient *tc = pm->client;
4329 struct VirtualLink *vl = pm->vl;
4330
4332 "client send response\n");
4333 if (NULL != tc)
4334 {
4335 struct GNUNET_MQ_Envelope *env;
4336 struct SendOkMessage *so_msg;
4337
4339 so_msg->peer = vl->target;
4341 "Confirming transmission of <%" PRIu64 "> to %s\n",
4342 pm->logging_uuid,
4343 GNUNET_i2s (&vl->target));
4344 GNUNET_MQ_send (tc->mq, env);
4345 }
4347}
4348
4349
4359static unsigned int
4362 struct DistanceVectorHop **hops_array,
4363 unsigned int hops_array_length)
4364{
4365 uint64_t choices[hops_array_length];
4366 uint64_t num_dv;
4367 unsigned int dv_count;
4368
4369 /* Pick random vectors, but weighted by distance, giving more weight
4370 to shorter vectors */
4371 num_dv = 0;
4372 dv_count = 0;
4373 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4374 pos = pos->next_dv)
4375 {
4376 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4377 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4378 .rel_value_us == 0))
4379 continue; /* pos unconfirmed and confirmed required */
4380 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4381 dv_count++;
4382 }
4383 if (0 == dv_count)
4384 return 0;
4385 if (dv_count <= hops_array_length)
4386 {
4387 dv_count = 0;
4388 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4389 pos = pos->next_dv)
4390 hops_array[dv_count++] = pos;
4391 return dv_count;
4392 }
4393 for (unsigned int i = 0; i < hops_array_length; i++)
4394 {
4395 int ok = GNUNET_NO;
4396 while (GNUNET_NO == ok)
4397 {
4398 choices[i] =
4400 ok = GNUNET_YES;
4401 for (unsigned int j = 0; j < i; j++)
4402 if (choices[i] == choices[j])
4403 {
4404 ok = GNUNET_NO;
4405 break;
4406 }
4407 }
4408 }
4409 dv_count = 0;
4410 num_dv = 0;
4411 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4412 pos = pos->next_dv)
4413 {
4414 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4415
4416 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4417 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4418 .rel_value_us == 0))
4419 continue; /* pos unconfirmed and confirmed required */
4420 for (unsigned int i = 0; i < hops_array_length; i++)
4421 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4422 hops_array[dv_count++] = pos;
4423 num_dv += delta;
4424 }
4425 return dv_count;
4426}
4427
4428
4435static int
4437 void *cls,
4439{
4440 struct TransportClient *tc = cls;
4441 uint16_t size;
4442
4443 if (CT_NONE != tc->type)
4444 {
4445 GNUNET_break (0);
4446 return GNUNET_SYSERR;
4447 }
4448 tc->type = CT_COMMUNICATOR;
4449 size = ntohs (cam->header.size) - sizeof(*cam);
4450 if (0 == size)
4451 return GNUNET_OK; /* receive-only communicator */
4453 return GNUNET_OK;
4454}
4455
4456
4462static void
4464 unsigned
4465 int free_cmc)
4466{
4467 if (0 != ntohl (cmc->im.fc_on))
4468 {
4469 /* send ACK when done to communicator for flow control! */
4470 struct GNUNET_MQ_Envelope *env;
4472
4474 "Acknowledge message with flow control id %" PRIu64 "\n",
4475 cmc->im.fc_id);
4477 ack->reserved = htonl (0);
4478 ack->fc_id = cmc->im.fc_id;
4479 ack->sender = cmc->im.neighbour_sender;
4480 GNUNET_MQ_send (cmc->tc->mq, env);
4481 }
4482
4484
4485 if (GNUNET_YES == free_cmc)
4486 {
4487 GNUNET_free (cmc);
4488 }
4489}
4490
4491
4492static void
4494{
4496}
4497
4498
4508static void
4509handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4510{
4511 struct TransportClient *tc = cls;
4512 struct VirtualLink *vl;
4513 uint32_t delta;
4514 struct CommunicatorMessageContext *cmc;
4515
4516 if (CT_CORE != tc->type)
4517 {
4518 GNUNET_break (0);
4520 return;
4521 }
4522 vl = lookup_virtual_link (&rom->peer);
4523 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4524 {
4526 "# RECV_OK dropped: virtual link unknown",
4527 1,
4528 GNUNET_NO);
4530 return;
4531 }
4532 delta = ntohl (rom->increase_window_delta);
4533 vl->core_recv_window += delta;
4535 "CORE ack receiving message, increased CORE recv window to %d\n",
4536 vl->core_recv_window);
4538 if (vl->core_recv_window <= 0)
4539 return;
4540 /* resume communicators */
4541 while (NULL != (cmc = vl->cmc_tail))
4542 {
4544 if (GNUNET_NO == cmc->continue_send)
4546 }
4547}
4548
4549
4556static void
4558 void *cls,
4560{
4561 struct TransportClient *tc = cls;
4562 uint16_t size;
4563
4564 size = ntohs (cam->header.size) - sizeof(*cam);
4565 if (0 == size)
4566 {
4568 "Receive-only communicator connected\n");
4569 return; /* receive-only communicator */
4570 }
4571 tc->details.communicator.address_prefix =
4572 GNUNET_strdup ((const char *) &cam[1]);
4573 tc->details.communicator.cc =
4576 "Communicator with prefix `%s' connected\n",
4577 tc->details.communicator.address_prefix);
4579}
4580
4581
4589static int
4591 void *cls,
4593{
4594 const struct GNUNET_MessageHeader *inbox;
4595 const char *is;
4596 uint16_t msize;
4597 uint16_t isize;
4598
4599 (void) cls;
4600 msize = ntohs (cb->header.size) - sizeof(*cb);
4601 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4602 isize = ntohs (inbox->size);
4603 if (isize >= msize)
4604 {
4605 GNUNET_break (0);
4606 return GNUNET_SYSERR;
4607 }
4608 is = (const char *) inbox;
4609 is += isize;
4610 msize -= isize;
4611 GNUNET_assert (0 < msize);
4612 if ('\0' != is[msize - 1])
4613 {
4614 GNUNET_break (0);
4615 return GNUNET_SYSERR;
4616 }
4617 return GNUNET_OK;
4618}
4619
4620
4626static void
4628{
4629 struct EphemeralConfirmationPS ec;
4630
4632 dv->ephemeral_validity =
4635 ec.target = dv->target;
4638 ec.purpose.size = htonl (sizeof(ec));
4640 &ec,
4641 &dv->sender_sig);
4642}
4643
4644
4645static void
4647 struct TransportClient *tc);
4648
4649
4650static void
4652{
4653 struct TransportClient *tc = cls;
4655
4657 "freeing timedout queue entries\n");
4658
4659 tc->details.communicator.free_queue_entry_task = NULL;
4660 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4661 queue = queue->next_client)
4662 {
4663 struct QueueEntry *qep = queue->queue_head;
4664
4666 "checking QID %u for timedout queue entries\n",
4667 queue->qid);
4668 while (NULL != qep)
4669 {
4670 struct QueueEntry *pos = qep;
4671
4672 qep = qep->next;
4674 pos->creation_timestamp, now);
4675
4677 "diff to now %s \n",
4680 {
4682 "Freeing timed out QueueEntry with MID %" PRIu64
4683 " and QID %u\n",
4684 pos->mid,
4685 queue->qid);
4686 free_queue_entry (pos, tc);
4687 }
4688 }
4689 }
4690}
4691
4692
4702static void
4704 struct PendingMessage *pm,
4705 const void *payload,
4706 size_t payload_size)
4707{
4708 struct Neighbour *n = queue->neighbour;
4710 struct GNUNET_MQ_Envelope *env;
4711 struct PendingAcknowledgement *pa;
4712
4713 GNUNET_log (
4715 "Queueing %u bytes of payload for transmission <%" PRIu64
4716 "> on queue %llu to %s\n",
4717 (unsigned int) payload_size,
4718 (NULL == pm) ? 0 : pm->logging_uuid,
4719 (unsigned long long) queue->qid,
4720 GNUNET_i2s (&queue->neighbour->pid));
4721 env = GNUNET_MQ_msg_extra (smt,
4722 payload_size,
4724 smt->qid = htonl (queue->qid);
4725 smt->mid = GNUNET_htonll (queue->mid_gen);
4726 smt->receiver = n->pid;
4727 memcpy (&smt[1], payload, payload_size);
4728 {
4729 /* Pass the env to the communicator of queue for transmission. */
4730 struct QueueEntry *qe;
4731
4732 qe = GNUNET_new (struct QueueEntry);
4733 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4734 qe->mid = queue->mid_gen;
4736 "Create QueueEntry with MID %" PRIu64
4737 " and QID %u and prefix %s\n",
4738 qe->mid,
4739 queue->qid,
4740 queue->tc->details.communicator.address_prefix);
4741 queue->mid_gen++;
4742 qe->queue = queue;
4743 if (NULL != pm)
4744 {
4745 qe->pm = pm;
4746 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4747 // GNUNET_assert (NULL == pm->qe);
4748 if (NULL != pm->qe)
4749 {
4751 "Retransmitting message <%" PRIu64
4752 "> remove pm from qe with MID: %llu \n",
4753 pm->logging_uuid,
4754 (unsigned long long) pm->qe->mid);
4755 pm->qe->pm = NULL;
4756 }
4757 pm->qe = qe;
4758 }
4759 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4760 if (0 == queue->q_capacity)
4761 {
4762 // Messages without FC or fragments can get here.
4763 if (NULL != pm)
4764 {
4766 "Message %" PRIu64
4767 " (pm type %u) was not send because queue has no capacity.\n",
4768 pm->logging_uuid,
4769 pm->pmt);
4770 pm->qe = NULL;
4771 }
4772 GNUNET_free (env);
4773 GNUNET_free (qe);
4774 return;
4775 }
4776 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4777 queue->queue_length++;
4778 queue->tc->details.communicator.total_queue_length++;
4779 if (GNUNET_NO == queue->unlimited_length)
4780 queue->q_capacity--;
4782 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4783 queue->address,
4784 queue->qid,
4785 queue->q_capacity);
4787 queue->tc->details.communicator.total_queue_length)
4788 queue->idle = GNUNET_NO;
4789 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4790 queue->idle = GNUNET_NO;
4791 if (0 == queue->q_capacity)
4792 queue->idle = GNUNET_NO;
4793
4794 if (GNUNET_NO == queue->idle)
4795 {
4796 struct TransportClient *tc = queue->tc;
4797
4798 if (NULL == tc->details.communicator.free_queue_entry_task)
4799 tc->details.communicator.free_queue_entry_task =
4801 &
4803 tc);
4804 }
4805 if (NULL != pm && NULL != (pa = pm->pa_head))
4806 {
4807 while (pm != pa->pm)
4808 pa = pa->next_pa;
4809 pa->num_send++;
4810 }
4811 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4813 "Sending message MID %" PRIu64
4814 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4815 PRIu64 "\n",
4816 GNUNET_ntohll (smt->mid),
4817 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4818 ntohs (smt->header.size),
4819 (unsigned long) payload_size,
4820 queue->tc->mq,
4821 queue->address,
4822 queue->qid,
4823 (NULL == pm) ? 0 : pm->logging_uuid);
4824 GNUNET_MQ_send (queue->tc->mq, env);
4825 }
4826}
4827
4828
4839static struct GNUNET_TIME_Relative
4841 const struct GNUNET_MessageHeader *hdr,
4843{
4844 struct GNUNET_TIME_Absolute now;
4845 unsigned int candidates;
4846 unsigned int sel1;
4847 unsigned int sel2;
4848 struct GNUNET_TIME_Relative rtt;
4849
4850 /* Pick one or two 'random' queues from n (under constraints of options) */
4851 now = GNUNET_TIME_absolute_get ();
4852 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4853 weight in the future; weight could be assigned by observed
4854 bandwidth (note: not sure if we should do this for this type
4855 of control traffic though). */
4856 candidates = 0;
4857 for (struct Queue *pos = n->queue_head; NULL != pos;
4858 pos = pos->next_neighbour)
4859 {
4860 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4861 (pos->validated_until.abs_value_us > now.abs_value_us))
4862 candidates++;
4863 }
4864 if (0 == candidates)
4865 {
4866 /* This can happen rarely if the last confirmed queue timed
4867 out just as we were beginning to process this message. */
4869 "Could not route message of type %u to %s: no valid queue\n",
4870 ntohs (hdr->type),
4871 GNUNET_i2s (&n->pid));
4873 "# route selection failed (all no valid queue)",
4874 1,
4875 GNUNET_NO);
4877 }
4878
4881 if (0 == (options & RMO_REDUNDANT))
4882 sel2 = candidates; /* picks none! */
4883 else
4885 candidates = 0;
4886 for (struct Queue *pos = n->queue_head; NULL != pos;
4887 pos = pos->next_neighbour)
4888 {
4889 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4890 (pos->validated_until.abs_value_us > now.abs_value_us))
4891 {
4892 if ((sel1 == candidates) || (sel2 == candidates))
4893 {
4895 "Routing message of type %u to %s using %s (#%u)\n",
4896 ntohs (hdr->type),
4897 GNUNET_i2s (&n->pid),
4898 pos->address,
4899 (sel1 == candidates) ? 1 : 2);
4900 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4901 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4902 }
4903 candidates++;
4904 }
4905 }
4906 return rtt;
4907}
4908
4909
4914{
4918 gcry_cipher_hd_t cipher;
4919
4923 struct
4924 {
4929
4933 char aes_key[256 / 8];
4934
4938 char aes_ctr[128 / 8];
4940};
4941
4942
4951static void
4953 const struct GNUNET_ShortHashCode *iv,
4954 struct DVKeyState *key)
4955{
4956 /* must match what we defive from decapsulated key */
4958 GNUNET_CRYPTO_hkdf_expand (&key->material,
4959 sizeof(key->material),
4960 km,
4961 "gnunet-transport-dv-key",
4962 strlen ("gnunet-transport-dv-key")
4963 ,
4964 km,
4965 sizeof(*km),
4966 iv,
4967 sizeof(*iv),
4968 NULL));
4970 "Deriving backchannel key based on KM %s and IV %s\n",
4971 GNUNET_sh2s (km),
4972 GNUNET_sh2s (iv));
4973 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
4974 GCRY_CIPHER_AES256 /* low level: go for speed */
4975 ,
4976 GCRY_CIPHER_MODE_CTR,
4977 0 /* flags */));
4978 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
4979 &key->material.aes_key,
4980 sizeof(key->material.aes_key)));
4981 gcry_cipher_setctr (key->cipher,
4982 &key->material.aes_ctr,
4983 sizeof(key->material.aes_ctr));
4984}
4985
4986
4996static void
4997dv_hmac (const struct DVKeyState *key,
4998 struct GNUNET_HashCode *hmac,
4999 const void *data,
5000 size_t data_size)
5001{
5002 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5003}
5004
5005
5015static void
5016dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5017{
5018 GNUNET_assert (0 ==
5019 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5020}
5021
5022
5033static enum GNUNET_GenericReturnValue
5035 void *out,
5036 const void *ciph,
5037 size_t out_size)
5038{
5039 return (0 ==
5040 gcry_cipher_decrypt (key->cipher,
5041 out, out_size,
5042 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5043}
5044
5045
5051static void
5053{
5054 gcry_cipher_close (key->cipher);
5055 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5056}
5057
5058
5069typedef void (*DVMessageHandler) (void *cls,
5070 struct Neighbour *next_hop,
5071 const struct GNUNET_MessageHeader *hdr,
5073
5088static struct GNUNET_TIME_Relative
5090 unsigned int num_dvhs,
5091 struct DistanceVectorHop **dvhs,
5092 const struct GNUNET_MessageHeader *hdr,
5093 DVMessageHandler use,
5094 void *use_cls,
5096 enum GNUNET_GenericReturnValue without_fc)
5097{
5098 struct TransportDVBoxMessage box_hdr;
5099 struct TransportDVBoxPayloadP payload_hdr;
5100 uint16_t enc_body_size = ntohs (hdr->size);
5101 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5102 struct DVKeyState *key;
5103 struct GNUNET_TIME_Relative rtt;
5104 struct GNUNET_ShortHashCode km;
5105
5106 key = GNUNET_new (struct DVKeyState);
5107 /* Encrypt payload */
5109 box_hdr.total_hops = htons (0);
5110 box_hdr.without_fc = htons (without_fc);
5111 // update_ephemeral (dv);
5112 if (0 ==
5113 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5114 {
5115 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5116 &dv->ephemeral_key,
5117 &km);
5118 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5119 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5120 sign_ephemeral (dv);
5121 }
5122 box_hdr.ephemeral_key = dv->ephemeral_key;
5123 payload_hdr.sender_sig = dv->sender_sig;
5124
5126 &box_hdr.iv,
5127 sizeof(box_hdr.iv));
5128 // We are creating this key, so this must work.
5129 // FIXME: Possibly also add return values here. We are processing
5130 // Input from other peers...
5131 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5132 payload_hdr.sender = GST_my_identity;
5133 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5134 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5135 dv_encrypt (key,
5136 hdr,
5137 &enc[sizeof(struct TransportDVBoxPayloadP)],
5138 enc_body_size);
5139 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5140 dv_key_clean (key);
5142 /* For each selected path, take the pre-computed header and body
5143 and add the path in the middle of the message; then send it. */
5144 for (unsigned int i = 0; i < num_dvhs; i++)
5145 {
5146 struct DistanceVectorHop *dvh = dvhs[i];
5147 unsigned int num_hops = dvh->distance + 1;
5148 char buf[sizeof(struct TransportDVBoxMessage)
5149 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5150 + sizeof(struct TransportDVBoxPayloadP)
5151 + enc_body_size] GNUNET_ALIGN;
5152 struct GNUNET_PeerIdentity *dhops;
5153
5154 box_hdr.header.size = htons (sizeof(buf));
5155 box_hdr.orig_size = htons (sizeof(buf));
5156 box_hdr.num_hops = htons (num_hops);
5157 memcpy (buf, &box_hdr, sizeof(box_hdr));
5158 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5159 memcpy (dhops,
5160 dvh->path,
5161 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5162 dhops[dvh->distance] = dv->target;
5163 if (GNUNET_EXTRA_LOGGING > 0)
5164 {
5165 char *path;
5166
5168 for (unsigned int j = 0; j < num_hops; j++)
5169 {
5170 char *tmp;
5171
5172 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5173 GNUNET_free (path);
5174 path = tmp;
5175 }
5177 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5178 ntohs (hdr->type),
5179 GNUNET_i2s (&dv->target),
5180 i + 1,
5181 num_dvhs,
5182 path);
5183 GNUNET_free (path);
5184 }
5185 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5186 memcpy (&dhops[num_hops], enc, sizeof(enc));
5187 use (use_cls,
5188 dvh->next_hop,
5189 (const struct GNUNET_MessageHeader *) buf,
5190 options);
5191 GNUNET_free (key);
5192 }
5193 return rtt;
5194}
5195
5196
5206static void
5208 struct Neighbour *next_hop,
5209 const struct GNUNET_MessageHeader *hdr,
5211{
5212 (void) cls;
5213 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5214}
5215
5216
5228static struct GNUNET_TIME_Relative
5230// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5231 const struct GNUNET_MessageHeader *hdr,
5233{
5234 // struct VirtualLink *vl;
5235 struct Neighbour *n;
5236 struct DistanceVector *dv;
5237 struct GNUNET_TIME_Relative rtt1;
5238 struct GNUNET_TIME_Relative rtt2;
5239 const struct GNUNET_PeerIdentity *target = &vl->target;
5240
5242 "Trying to route message of type %u to %s without fc\n",
5243 ntohs (hdr->type),
5244 GNUNET_i2s (target));
5245
5246 // TODO Do this elsewhere. vl should be given as parameter to method.
5247 // vl = lookup_virtual_link (target);
5248 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5249 if (NULL == vl)
5251 n = vl->n;
5252 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5253 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5254 {
5255 /* if confirmed is required, and we do not have anything
5256 confirmed, drop respective options */
5257 if (NULL == n)
5258 n = lookup_neighbour (target);
5259 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5261 }
5262 if ((NULL == n) && (NULL == dv))
5263 {
5265 "Cannot route message of type %u to %s: no route\n",
5266 ntohs (hdr->type),
5267 GNUNET_i2s (target));
5269 "# Messages dropped in routing: no acceptable method",
5270 1,
5271 GNUNET_NO);
5273 }
5275 "Routing message of type %u to %s with options %X\n",
5276 ntohs (hdr->type),
5277 GNUNET_i2s (target),
5278 (unsigned int) options);
5279 /* If both dv and n are possible and we must choose:
5280 flip a coin for the choice between the two; for now 50/50 */
5281 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5282 {
5284 n = NULL;
5285 else
5286 dv = NULL;
5287 }
5288 if ((NULL != n) && (NULL != dv))
5289 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5290 enough for redundancy, so clear the flag. */
5293 if (NULL != n)
5294 {
5296 "Try to route message of type %u to %s without fc via neighbour\n",
5297 ntohs (hdr->type),
5298 GNUNET_i2s (target));
5299 rtt1 = route_via_neighbour (n, hdr, options);
5300 }
5301 if (NULL != dv)
5302 {
5303 struct DistanceVectorHop *hops[2];
5304 unsigned int res;
5305
5307 options,
5308 hops,
5309 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5310 if (0 == res)
5311 {
5313 "Failed to route message, could not determine DV path\n");
5314 return rtt1;
5315 }
5317 "encapsulate_for_dv 1\n");
5318 rtt2 = encapsulate_for_dv (dv,
5319 res,
5320 hops,
5321 hdr,
5323 NULL,
5325 GNUNET_YES);
5326 }
5327 return GNUNET_TIME_relative_min (rtt1, rtt2);
5328}
5329
5330
5331static void
5332consider_sending_fc (void *cls);
5333
5340static void
5342{
5343 struct VirtualLink *vl = cls;
5344 vl->fc_retransmit_task = NULL;
5345 consider_sending_fc (cls);
5346}
5347
5348
5349static char *
5350get_address_without_port (const char *address);
5351
5352
5354{
5355 size_t off;
5356 char *tgnas;
5357};
5358
5359
5360static enum GNUNET_GenericReturnValue
5362 const struct GNUNET_PeerIdentity *pid,
5363 void *value)
5364{
5365 struct AddGlobalAddressesContext *ctx = cls;
5366 struct TransportGlobalNattedAddress *tgna = value;
5367 char *addr = (char *) &tgna[1];
5368 size_t address_len = strlen (addr);
5369
5371 "sending address %s length %lu\n",
5372 addr,
5373 address_len);
5374 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
5375 + address_len);
5376 tgna->address_length = htonl (address_len);
5377 GNUNET_memcpy (&tgna[1], addr, address_len);
5378 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5380 + address_len);
5381 GNUNET_free (tgna);
5382 ctx->off += sizeof(struct TransportGlobalNattedAddress) + address_len;
5383
5384 return GNUNET_OK;
5385}
5386
5387
5394static void
5396{
5397 struct VirtualLink *vl = cls;
5398 struct GNUNET_TIME_Absolute monotime;
5399 struct TransportFlowControlMessage *fc;
5401 struct GNUNET_TIME_Relative rtt;
5402 struct Neighbour *n = vl->n;
5403
5404 if (0 < n->number_of_addresses)
5405 {
5406 size_t addresses_size =
5407 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5408 ->size_of_global_addresses;
5409 char *tgnas = GNUNET_malloc (addresses_size);
5411 ctx.off = 0;
5412 ctx.tgnas = tgnas;
5413
5414 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage)
5415 + addresses_size);
5416 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5417 + addresses_size);
5418 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5419 fc->number_of_addresses = htonl (n->number_of_addresses);
5420 GNUNET_CONTAINER_multipeermap_iterate (n->natted_addresses,
5422 &ctx);
5423 GNUNET_memcpy (&fc[1], tgnas, addresses_size);
5425 }
5426 else
5427 {
5428 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5429 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5430 }
5431
5433 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5434 it always! */
5435 /* For example, we should probably ONLY do this if a bit more than
5436 an RTT has passed, or if the window changed "significantly" since
5437 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5438 need an estimate for the bandwidth-delay-product for the entire
5439 VL, as that determines "significantly". We have the delay, but
5440 the bandwidth statistics need to be added for the VL!*/(void) duration;
5441
5443 "Sending FC seq %u to %s with new window %llu\n",
5444 (unsigned int) vl->fc_seq_gen,
5445 GNUNET_i2s (&vl->target),
5446 (unsigned long long) vl->incoming_fc_window_size);
5448 vl->last_fc_transmission = monotime;
5450 fc->seq = htonl (vl->fc_seq_gen++);
5456 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5458 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5459 {
5462 "FC retransmission to %s failed, will retry in %s\n",
5463 GNUNET_i2s (&vl->target),
5466 }
5467 else
5468 {
5469 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5470 vl->last_fc_rtt = rtt;
5471 }
5472 if (NULL != vl->fc_retransmit_task)
5475 {
5477 vl->fc_retransmit_count = 0;
5478 }
5479 vl->fc_retransmit_task =
5481 vl->fc_retransmit_count++;
5482 GNUNET_free (fc);
5483}
5484
5485
5502static void
5504{
5505 struct Neighbour *n = vl->n;
5506 struct DistanceVector *dv = vl->dv;
5507 struct GNUNET_TIME_Absolute now;
5508 struct VirtualLink *vl_next_hop;
5509 int elig;
5510
5512 "check_vl_transmission to target %s\n",
5513 GNUNET_i2s (&vl->target));
5514 /* Check that we have an eligible pending message!
5515 (cheaper than having #transmit_on_queue() find out!) */
5516 elig = GNUNET_NO;
5517 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5518 pm = pm->next_vl)
5519 {
5521 "check_vl_transmission loop\n");
5522 if (NULL != pm->qe)
5523 continue; /* not eligible, is in a queue! */
5524 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5526 {
5528 "Stalled message %" PRIu64
5529 " transmission on VL %s due to flow control: %llu < %llu\n",
5530 pm->logging_uuid,
5531 GNUNET_i2s (&vl->target),
5532 (unsigned long long) vl->outbound_fc_window_size,
5533 (unsigned long long) (pm->bytes_msg
5536 return; /* We have a message, but flow control says "nope" */
5537 }
5539 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5540 GNUNET_i2s (&vl->target));
5541 /* Notify queues at direct neighbours that we are interested */
5542 now = GNUNET_TIME_absolute_get ();
5543 if (NULL != n)
5544 {
5545 for (struct Queue *queue = n->queue_head; NULL != queue;
5546 queue = queue->next_neighbour)
5547 {
5548 if ((GNUNET_YES == queue->idle) &&
5549 (queue->validated_until.abs_value_us > now.abs_value_us))
5550 {
5552 "Direct neighbour %s not stalled\n",
5553 GNUNET_i2s (&n->pid));
5555 queue,
5557 elig = GNUNET_YES;
5558 }
5559 else
5561 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5562 queue->qid,
5563 queue->idle);
5564 }
5565 }
5566 /* Notify queues via DV that we are interested */
5567 if (NULL != dv)
5568 {
5569 /* Do DV with lower scheduler priority, which effectively means that
5570 IF a neighbour exists and is available, we prefer it. */
5571 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5572 pos = pos->next_dv)
5573 {
5574 struct Neighbour *nh = pos->next_hop;
5575
5576
5577 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5578 continue; /* skip this one: path not validated */
5579 else
5580 {
5581 vl_next_hop = lookup_virtual_link (&nh->pid);
5582 GNUNET_assert (NULL != vl_next_hop);
5583 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5584 vl_next_hop->outbound_fc_window_size)
5585 {
5587 "Stalled message %" PRIu64
5588 " transmission on next hop %s due to flow control: %llu < %llu\n",
5589 pm->logging_uuid,
5590 GNUNET_i2s (&vl_next_hop->target),
5591 (unsigned long
5592 long) vl_next_hop->outbound_fc_window_size,
5593 (unsigned long long) (pm->bytes_msg
5594 + vl_next_hop->
5595 outbound_fc_window_size_used));
5596 consider_sending_fc (vl_next_hop);
5597 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5598 }
5599 for (struct Queue *queue = nh->queue_head; NULL != queue;
5600 queue = queue->next_neighbour)
5601 if ((GNUNET_YES == queue->idle) &&
5602 (queue->validated_until.abs_value_us > now.abs_value_us))
5603 {
5605 "Next hop neighbour %s not stalled\n",
5606 GNUNET_i2s (&nh->pid));
5608 queue,
5610 elig = GNUNET_YES;
5611 }
5612 else
5614 "DV Queue QID: %u (%u) busy or invalid\n",
5615 queue->qid,
5616 queue->idle);
5617 }
5618 }
5619 }
5620 if (GNUNET_YES == elig)
5622 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5623 pm->logging_uuid,
5624 pm->bytes_msg,
5625 GNUNET_i2s (&vl->target),
5626 (unsigned long long) vl->outbound_fc_window_size,
5627 (unsigned long long) (pm->bytes_msg
5629 break;
5630 }
5631}
5632
5633
5640static void
5641handle_client_send (void *cls, const struct OutboundMessage *obm)
5642{
5643 struct TransportClient *tc = cls;
5644 struct PendingMessage *pm;
5645 const struct GNUNET_MessageHeader *obmm;
5646 uint32_t bytes_msg;
5647 struct VirtualLink *vl;
5649
5650 GNUNET_assert (CT_CORE == tc->type);
5651 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5652 bytes_msg = ntohs (obmm->size);
5653 pp = (enum GNUNET_MQ_PriorityPreferences) ntohl (obm->priority);
5654 vl = lookup_virtual_link (&obm->peer);
5655 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5656 {
5658 "Don't have %s as a neighbour (anymore).\n",
5659 GNUNET_i2s (&obm->peer));
5660 /* Failure: don't have this peer as a neighbour (anymore).
5661 Might have gone down asynchronously, so this is NOT
5662 a protocol violation by CORE. Still count the event,
5663 as this should be rare. */
5666 "# messages dropped (neighbour unknown)",
5667 1,
5668 GNUNET_NO);
5669 return;
5670 }
5671
5672 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5674 "1 created pm %p storing vl %p\n",
5675 pm,
5676 vl);
5677 pm->logging_uuid = logging_uuid_gen++;
5678 pm->prefs = pp;
5679 pm->client = tc;
5680 pm->vl = vl;
5681 pm->bytes_msg = bytes_msg;
5682 memcpy (&pm[1], obmm, bytes_msg);
5684 "Sending message of type %u with %u bytes as <%" PRIu64
5685 "> to %s\n",
5686 ntohs (obmm->type),
5687 bytes_msg,
5688 pm->logging_uuid,
5689 GNUNET_i2s (&obm->peer));
5691 tc->details.core.pending_msg_head,
5692 tc->details.core.pending_msg_tail,
5693 pm);
5695 vl->pending_msg_head,
5696 vl->pending_msg_tail,
5697 pm);
5700}
5701
5702
5712static void
5714 void *cls,
5716{
5717 struct Neighbour *n;
5718 struct VirtualLink *vl;
5719 struct TransportClient *tc = cls;
5720 const struct GNUNET_MessageHeader *inbox =
5721 (const struct GNUNET_MessageHeader *) &cb[1];
5722 uint16_t isize = ntohs (inbox->size);
5723 const char *is = ((const char *) &cb[1]) + isize;
5724 size_t slen = strlen (is) + 1;
5725 char
5726 mbuf[slen + isize
5727 + sizeof(struct
5731
5732 /* 0-termination of 'is' was checked already in
5733 #check_communicator_backchannel() */
5735 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5736 GNUNET_i2s (&cb->pid),
5737 is,
5738 ntohs (inbox->type),
5739 ntohs (inbox->size));
5740 /* encapsulate and encrypt message */
5741 be->header.type =
5743 be->header.size = htons (sizeof(mbuf));
5744 memcpy (&be[1], inbox, isize);
5745 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5746 + isize],
5747 is,
5748 strlen (is) + 1);
5749 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5750 vl = lookup_virtual_link (&cb->pid);
5751 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5752 {
5754 }
5755 else
5756 {
5757 /* Use route via neighbour */
5758 n = lookup_neighbour (&cb->pid);
5759 if (NULL != n)
5761 n,
5762 &be->header,
5763 RMO_NONE);
5764 }
5766}
5767
5768
5776static int
5778 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5779{
5780 struct TransportClient *tc = cls;
5781
5782 if (CT_COMMUNICATOR != tc->type)
5783 {
5784 GNUNET_break (0);
5785 return GNUNET_SYSERR;
5786 }
5788 return GNUNET_OK;
5789}
5790
5791
5797static void
5798store_pi (void *cls);
5799
5800
5807static void
5808peerstore_store_own_cb (void *cls, int success)
5809{
5810 struct AddressListEntry *ale = cls;
5811
5812 ale->sc = NULL;
5813 if (GNUNET_YES != success)
5815 "Failed to store our own address `%s' in peerstore!\n",
5816 ale->address);
5817 else
5819 "Successfully stored our own address `%s' in peerstore!\n",
5820 ale->address);
5821 /* refresh period is 1/4 of expiration time, that should be plenty
5822 without being excessive. */
5823 ale->st =
5825 4ULL),
5826 &store_pi,
5827 ale);
5828}
5829
5830
5831static void
5832shc_cont (void *cls, int success)
5833{
5834 struct AddressListEntry *ale = cls;
5836
5839 "transport",
5842 ale->signed_address,
5843 ale->signed_address_len,
5844 expiration,
5847 ale);
5848 if (NULL == ale->sc)
5849 {
5851 "Failed to store our address `%s' with peerstore\n",
5852 ale->address);
5854 &store_pi,
5855 ale);
5856 }
5857}
5858
5859
5865static void
5866store_pi (void *cls)
5867{
5868 struct AddressListEntry *ale = cls;
5869 struct GNUNET_MQ_Envelope *env;
5870 const struct GNUNET_MessageHeader *msg;
5871 const char *dash;
5872 char *address_uri;
5874 unsigned int add_success;
5875
5876 dash = strchr (ale->address, '-');
5877 GNUNET_assert (NULL != dash);
5878 dash++;
5879 GNUNET_asprintf (&address_uri,
5880 "%s://%s",
5881 prefix,
5882 dash);
5884 ale->st = NULL;
5886 "Storing our address `%s' in peerstore until %s!\n",
5887 ale->address,
5890 address_uri);
5891 if (GNUNET_OK != add_success)
5892 {
5894 "Storing our address `%s' %s\n",
5895 address_uri,
5896 GNUNET_NO == add_success ? "not done" : "failed");
5897 GNUNET_free (address_uri);
5898 return;
5899 }
5900 else
5901 {
5902
5904 "Storing our address `%s'\n",
5905 address_uri);
5906 }
5907 // FIXME hello_mono_time used here?? What about expiration in ale?
5909 ale->nt,
5912 &ale->signed_address,
5913 &ale->signed_address_len);
5914 GNUNET_free (address_uri);
5920 "store_pi 1\n");
5922 msg,
5923 shc_cont,
5924 ale);
5925 GNUNET_free (env);
5926}
5927
5928
5929static struct AddressListEntry *
5933 const char *address,
5934 uint32_t aid,
5935 size_t slen)
5936{
5937 struct AddressListEntry *ale;
5938
5939 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
5940 ale->tc = tc;
5941 ale->address = (const char *) &ale[1];
5942 ale->expiration = expiration;
5943 ale->aid = aid;
5944 ale->nt = nt;
5945 memcpy (&ale[1], address, slen);
5946 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
5947
5948 return ale;
5949}
5950
5951
5958static void
5960 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5961{
5962 struct TransportClient *tc = cls;
5963 struct AddressListEntry *ale;
5964 size_t slen;
5965
5966 /* 0-termination of &aam[1] was checked in #check_add_address */
5968 "Communicator added address `%s'!\n",
5969 (const char *) &aam[1]);
5970 slen = ntohs (aam->header.size) - sizeof(*aam);
5971 ale = create_address_entry (tc,
5973 (enum GNUNET_NetworkType) ntohl (aam->nt),
5974 (const char *) &aam[1],
5975 aam->aid,
5976 slen);
5977 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
5978 tc->details.communicator.addr_tail,
5979 ale);
5981}
5982
5983
5990static void
5992 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5993{
5994 struct TransportClient *tc = cls;
5995 struct AddressListEntry *alen;
5996
5997 if (CT_COMMUNICATOR != tc->type)
5998 {
5999 GNUNET_break (0);
6001 return;
6002 }
6003 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6004 NULL != ale;
6005 ale = alen)
6006 {
6007 alen = ale->next;
6008 if (dam->aid != ale->aid)
6009 continue;
6010 GNUNET_assert (ale->tc == tc);
6012 "Communicator deleted address `%s'!\n",
6013 ale->address);
6016 return;
6017 }
6019 "Communicator removed address we did not even have.\n");
6021 // GNUNET_SERVICE_client_drop (tc->client);
6022}
6023
6024
6032static void
6034
6035
6043static void
6045{
6046 struct CoreSentContext *ctx = cls;
6047 struct VirtualLink *vl = ctx->vl;
6048
6049 if (NULL == vl)
6050 {
6051 /* lost the link in the meantime, ignore */
6052 GNUNET_free (ctx);
6053 return;
6054 }
6057 vl->incoming_fc_window_size_ram -= ctx->size;
6058 vl->incoming_fc_window_size_used += ctx->isize;
6060 GNUNET_free (ctx);
6061}
6062
6063
6064static void
6066 const struct GNUNET_MessageHeader *mh,
6067 struct CommunicatorMessageContext *cmc,
6068 unsigned int free_cmc)
6069{
6070 uint16_t size = ntohs (mh->size);
6071 int have_core;
6072
6073 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6074 {
6076 "# CORE messages dropped (FC arithmetic overflow)",
6077 1,
6078 GNUNET_NO);
6080 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6081 (unsigned int) ntohs (mh->type),
6082 (unsigned int) ntohs (mh->size));
6083 if (GNUNET_YES == free_cmc)
6085 return;
6086 }
6088 {
6090 "# CORE messages dropped (FC window overflow)",
6091 1,
6092 GNUNET_NO);
6094 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6095 (unsigned int) ntohs (mh->type),
6096 (unsigned int) ntohs (mh->size));
6097 if (GNUNET_YES == free_cmc)
6099 return;
6100 }
6101
6102 /* Forward to all CORE clients */
6103 have_core = GNUNET_NO;
6104 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6105 {
6106 struct GNUNET_MQ_Envelope *env;
6107 struct InboundMessage *im;
6108 struct CoreSentContext *ctx;
6109
6110 if (CT_CORE != tc->type)
6111 continue;
6114 ctx = GNUNET_new (struct CoreSentContext);
6115 ctx->vl = vl;
6116 ctx->size = size;
6117 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6118 have_core = GNUNET_YES;
6121 im->peer = cmc->im.sender;
6122 memcpy (&im[1], mh, size);
6123 GNUNET_MQ_send (tc->mq, env);
6125 }
6126 if (GNUNET_NO == have_core)
6127 {
6129 "Dropped message to CORE: no CORE client connected!\n");
6130 /* Nevertheless, count window as used, as it is from the
6131 perspective of the other peer! */
6133 /* TODO-M1 */
6135 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6136 (unsigned int) ntohs (mh->type),
6137 (unsigned int) ntohs (mh->size));
6138 if (GNUNET_YES == free_cmc)
6140 return;
6141 }
6143 "Delivered message from %s of type %u to CORE recv window %d\n",
6144 GNUNET_i2s (&cmc->im.sender),
6145 ntohs (mh->type),
6147 if (vl->core_recv_window > 0)
6148 {
6149 if (GNUNET_YES == free_cmc)
6151 return;
6152 }
6153 /* Wait with calling #finish_cmc_handling(cmc) until the message
6154 was processed by CORE MQs (for CORE flow control)! */
6155 if (GNUNET_YES == free_cmc)
6157}
6158
6159
6168static void
6170{
6171 struct CommunicatorMessageContext *cmc = cls;
6172 // struct CommunicatorMessageContext *cmc_copy =
6173 // GNUNET_new (struct CommunicatorMessageContext);
6174 struct GNUNET_MessageHeader *mh_copy;
6175 struct RingBufferEntry *rbe;
6176 struct VirtualLink *vl;
6177 uint16_t size = ntohs (mh->size);
6178
6180 "Handling raw message of type %u with %u bytes\n",
6181 (unsigned int) ntohs (mh->type),
6182 (unsigned int) ntohs (mh->size));
6183
6184 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6185 (size < sizeof(struct GNUNET_MessageHeader)))
6186 {
6187 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6188
6189 GNUNET_break (0);
6190 finish_cmc_handling (cmc);
6192 return;
6193 }
6194 vl = lookup_virtual_link (&cmc->im.sender);
6195 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6196 {
6197 /* FIXME: sender is giving us messages for CORE but we don't have
6198 the link up yet! I *suspect* this can happen right now (i.e.
6199 sender has verified us, but we didn't verify sender), but if
6200 we pass this on, CORE would be confused (link down, messages
6201 arrive). We should investigate more if this happens often,
6202 or in a persistent manner, and possibly do "something" about
6203 it. Thus logging as error for now. */
6204
6205 mh_copy = GNUNET_malloc (size);
6206 rbe = GNUNET_new (struct RingBufferEntry);
6207 rbe->cmc = cmc;
6208 /*cmc_copy->tc = cmc->tc;
6209 cmc_copy->im = cmc->im;*/
6210 GNUNET_memcpy (mh_copy, mh, size);
6211
6212 rbe->mh = mh_copy;
6213
6215 {
6216 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6217 GNUNET_free (rbe_old->cmc);
6218 GNUNET_free (rbe_old->mh);
6219 GNUNET_free (rbe_old);
6220 }
6221 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6222 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6223 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6225 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6226 GNUNET_i2s (&cmc->im.sender),
6227 (unsigned int) ntohs (mh->type),
6228 (unsigned int) ntohs (mh_copy->type),
6232 {
6233 ring_buffer_head = 0;
6235 }
6236 else
6238
6240 "%u items stored in ring buffer\n",
6243
6244 /*GNUNET_break_op (0);
6245 GNUNET_STATISTICS_update (GST_stats,
6246 "# CORE messages dropped (virtual link still down)",
6247 1,
6248 GNUNET_NO);
6249
6250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6251 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6252 (unsigned int) ntohs (mh->type),
6253 (unsigned int) ntohs (mh->size));
6254 finish_cmc_handling (cmc);*/
6257 // GNUNET_free (cmc);
6258 return;
6259 }
6261}
6262
6263
6271static int
6273{
6274 uint16_t size = ntohs (fb->header.size);
6275 uint16_t bsize = size - sizeof(*fb);
6276
6277 (void) cls;
6278 if (0 == bsize)
6279 {
6280 GNUNET_break_op (0);
6281 return GNUNET_SYSERR;
6282 }
6283 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6284 {
6285 GNUNET_break_op (0);
6286 return GNUNET_SYSERR;
6287 }
6288 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6289 {
6290 GNUNET_break_op (0);
6291 return GNUNET_SYSERR;
6292 }
6293 return GNUNET_YES;
6294}
6295
6296
6302static void
6304{
6305 struct AcknowledgementCummulator *ac = cls;
6306
6307 ac->task = NULL;
6308 GNUNET_assert (0 == ac->num_acks);
6310 GNUNET_YES ==
6312 GNUNET_free (ac);
6313}
6314
6315
6321static void
6323{
6324 struct Neighbour *n;
6325 struct VirtualLink *vl;
6326 struct AcknowledgementCummulator *ac = cls;
6327 char buf[sizeof(struct TransportReliabilityAckMessage)
6328 + ac->num_acks
6330 struct TransportReliabilityAckMessage *ack =
6331 (struct TransportReliabilityAckMessage *) buf;
6333
6334 ac->task = NULL;
6336 "Sending ACK with %u components to %s\n",
6337 ac->num_acks,
6338 GNUNET_i2s (&ac->target));
6339 GNUNET_assert (0 < ac->num_acks);
6341 ack->header.size =
6342 htons (sizeof(*ack)
6343 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6344 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6345 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6346 for (unsigned int i = 0; i < ac->num_acks; i++)
6347 {
6348 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6351 }
6352 /*route_control_message_without_fc (
6353 &ac->target,
6354 &ack->header,
6355 RMO_DV_ALLOWED);*/
6356 vl = lookup_virtual_link (&ac->target);
6357 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6358 {
6360 vl,
6361 &ack->header,
6363 }
6364 else
6365 {
6366 /* Use route via neighbour */
6367 n = lookup_neighbour (&ac->target);
6368 if (NULL != n)
6370 n,
6371 &ack->header,
6372 RMO_NONE);
6373 }
6374 ac->num_acks = 0;
6377 ac);
6378}
6379
6380
6389static void
6391 const struct AcknowledgementUUIDP *ack_uuid,
6392 struct GNUNET_TIME_Absolute max_delay)
6393{
6394 struct AcknowledgementCummulator *ac;
6395
6397 "Scheduling ACK %s for transmission to %s\n",
6398 GNUNET_uuid2s (&ack_uuid->value),
6399 GNUNET_i2s (pid));
6401 if (NULL == ac)
6402 {
6404 ac->target = *pid;
6405 ac->min_transmission_time = max_delay;
6409 &ac->target,
6410 ac,
6412 }
6413 else
6414 {
6415 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6416 {
6417 /* must run immediately, ack buffer full! */
6419 }
6423 }
6426 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6427 ac->num_acks++;
6430 ac);
6431}
6432
6433
6438{
6443
6448};
6449
6450
6460static int
6461find_by_message_uuid (void *cls, uint32_t key, void *value)
6462{
6463 struct FindByMessageUuidContext *fc = cls;
6464 struct ReassemblyContext *rc = value;
6465
6466 (void) key;
6467 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6468 {
6469 fc->rc = rc;
6470 return GNUNET_NO;
6471 }
6472 return GNUNET_YES;
6473}
6474
6475
6483static void
6485{
6486 struct CommunicatorMessageContext *cmc = cls;
6487 struct VirtualLink *vl;
6488 struct ReassemblyContext *rc;
6489 const struct GNUNET_MessageHeader *msg;
6490 uint16_t msize;
6491 uint16_t fsize;
6492 uint16_t frag_off;
6493 char *target;
6494 struct GNUNET_TIME_Relative cdelay;
6495 struct FindByMessageUuidContext fc;
6496
6497 vl = lookup_virtual_link (&cmc->im.sender);
6498 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6499 {
6500 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6501
6503 "No virtual link for %s to handle fragment\n",
6504 GNUNET_i2s (&cmc->im.sender));
6505 GNUNET_break (0);
6506 finish_cmc_handling (cmc);
6508 return;
6509 }
6510 if (NULL == vl->reassembly_map)
6511 {
6513 vl->reassembly_heap =
6518 vl);
6519 }
6520 msize = ntohs (fb->msg_size);
6521 fc.message_uuid = fb->msg_uuid;
6522 fc.rc = NULL;
6524 fb->msg_uuid.uuid,
6526 &fc);
6527 fsize = ntohs (fb->header.size) - sizeof(*fb);
6528 if (NULL == (rc = fc.rc))
6529 {
6530 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6531 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6532 rc->msg_uuid = fb->msg_uuid;
6533 rc->virtual_link = vl;
6534 rc->msg_size = msize;
6535 rc->reassembly_timeout =
6539 rc,
6543 vl->reassembly_map,
6544 rc->msg_uuid.uuid,
6545 rc,
6547 target = (char *) &rc[1];
6548 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6549 if (fsize != rc->msg_size)
6550 rc->msg_missing = rc->msg_size;
6551 else
6552 rc->msg_missing = 0;
6554 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6555 PRIu64 "\n",
6556 fsize,
6557 ntohs (fb->frag_off),
6558 msize,
6559 rc->msg_missing,
6560 GNUNET_i2s (&cmc->im.sender),
6561 fb->msg_uuid.uuid);
6562 }
6563 else
6564 {
6565 target = (char *) &rc[1];
6567 "Received fragment at offset %u/%u from %s for message %u\n",
6568 ntohs (fb->frag_off),
6569 msize,
6570 GNUNET_i2s (&cmc->im.sender),
6571 (unsigned int) fb->msg_uuid.uuid);
6572 }
6573 if (msize != rc->msg_size)
6574 {
6575 GNUNET_break (0);
6576 finish_cmc_handling (cmc);
6577 return;
6578 }
6579
6580 /* reassemble */
6581 if (0 == fsize)
6582 {
6583 GNUNET_break (0);
6584 finish_cmc_handling (cmc);
6585 return;
6586 }
6587 frag_off = ntohs (fb->frag_off);
6588 if (frag_off + fsize > msize)
6589 {
6590 /* Fragment (plus fragment size) exceeds message size! */
6591 GNUNET_break_op (0);
6592 finish_cmc_handling (cmc);
6593 return;
6594 }
6595 memcpy (&target[frag_off], &fb[1], fsize);
6596 /* update bitfield and msg_missing */
6597 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6598 {
6599 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6600 {
6601 rc->bitfield[i / 8] |= (1 << (i % 8));
6602 rc->msg_missing--;
6603 }
6604 }
6605
6606 /* Compute cumulative ACK */
6608 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6609 if (0 == rc->msg_missing)
6610 cdelay = GNUNET_TIME_UNIT_ZERO;
6611 cummulative_ack (&cmc->im.sender,
6612 &fb->ack_uuid,
6615 /* is reassembly complete? */
6616 if (0 != rc->msg_missing)
6617 {
6618 finish_cmc_handling (cmc);
6619 return;
6620 }
6621 /* reassembly is complete, verify result */
6622 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6623 if (ntohs (msg->size) != rc->msg_size)
6624 {
6625 GNUNET_break (0);
6627 finish_cmc_handling (cmc);
6628 return;
6629 }
6630 /* successful reassembly */
6632 "Fragment reassembly complete for message %u\n",
6633 (unsigned int) fb->msg_uuid.uuid);
6634 /* FIXME: check that the resulting msg is NOT a
6635 DV Box or Reliability Box, as that is NOT allowed! */
6636 cmc->mh = msg;
6638 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6639 en-route and we forget that we finished this reassembly immediately!
6640 -> keep around until timeout?
6641 -> shorten timeout based on ACK? */
6643}
6644
6645
6653static int
6655 const struct TransportReliabilityBoxMessage *rb)
6656{
6657 (void) cls;
6658 const struct GNUNET_MessageHeader *inbox = (const struct
6659 GNUNET_MessageHeader *) &rb[1];
6660
6662 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6663 ntohs (rb->header.size),
6664 ntohs (inbox->type),
6665 ntohs (inbox->size),
6666 sizeof (struct TransportReliabilityBoxMessage),
6667 sizeof (struct GNUNET_MessageHeader));
6669 return GNUNET_YES;
6670}
6671
6672
6680static void
6682 const struct TransportReliabilityBoxMessage *rb)
6683{
6684 struct CommunicatorMessageContext *cmc = cls;
6685 const struct GNUNET_MessageHeader *inbox =
6686 (const struct GNUNET_MessageHeader *) &rb[1];
6687 struct GNUNET_TIME_Relative rtt;
6688
6690 "Received reliability box from %s with UUID %s of type %u\n",
6691 GNUNET_i2s (&cmc->im.sender),
6693 (unsigned int) ntohs (inbox->type));
6694 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6695 do not really have an RTT for the
6696 * incoming* queue (should we have
6697 the sender add it to the rb message?) */
6699 &cmc->im.sender,
6700 &rb->ack_uuid,
6701 (0 == ntohl (rb->ack_countdown))
6704 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6705 /* continue with inner message */
6706 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6707 reliability box (not allowed!) */
6708 cmc->mh = inbox;
6710}
6711
6712
6721static void
6722update_pd_age (struct PerformanceData *pd, unsigned int age)
6723{
6724 unsigned int sage;
6725
6726 if (age == pd->last_age)
6727 return; /* nothing to do */
6728 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6729 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6730 {
6731 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6732
6733 the->bytes_sent = 0;
6734 the->bytes_received = 0;
6735 }
6736 pd->last_age = age;
6737}
6738
6739
6748static void
6750 struct GNUNET_TIME_Relative rtt,
6751 uint16_t bytes_transmitted_ok)
6752{
6753 uint64_t nval = rtt.rel_value_us;
6754 uint64_t oval = pd->aged_rtt.rel_value_us;
6755 unsigned int age = get_age ();
6756 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
6757
6758 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
6759 pd->aged_rtt = rtt;
6760 else
6761 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
6762 update_pd_age (pd, age);
6763 the->bytes_received += bytes_transmitted_ok;
6764}
6765
6766
6774static void
6776 struct GNUNET_TIME_Relative rtt,
6777 uint16_t bytes_transmitted_ok)
6778{
6779 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
6780}
6781
6782
6790static void
6792 struct GNUNET_TIME_Relative rtt,
6793 uint16_t bytes_transmitted_ok)
6794{
6795 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
6796}
6797
6798
6806static void
6808{
6809 struct PendingMessage *pos;
6810
6812 "Complete transmission of message %" PRIu64 " %u\n",
6813 pm->logging_uuid,
6814 pm->pmt);
6815 switch (pm->pmt)
6816 {
6817 case PMT_CORE:
6819 /* Full message sent, we are done */
6821 return;
6822
6823 case PMT_FRAGMENT_BOX:
6824 /* Fragment sent over reliable channel */
6825 pos = pm->frag_parent;
6829 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
6830 (unsigned long) pos->frag_off,
6831 (unsigned long) pos->bytes_msg,
6832 pos->pmt,
6833 NULL == pos->frag_parent ? 1 : 0);
6834 /* check if subtree is done */
6835 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
6836 - sizeof(struct
6838 &&
6839 (NULL != pos->frag_parent))
6840 {
6841 pm = pos;
6842 pos = pm->frag_parent;
6843 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
6844 {
6846 return;
6847 }
6848 else if (PMT_DV_BOX == pm->pmt)
6849 {
6851 return;
6852 }
6855 }
6856
6857 /* Was this the last applicable fragment? */
6858 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
6859 pos->pmt) &&
6860 (pos->frag_off == pos->bytes_msg))
6862 return;
6863
6864 case PMT_DV_BOX:
6866 "Completed transmission of message %" PRIu64 " (DV Box)\n",
6867 pm->logging_uuid);
6868 if (NULL != pm->frag_parent)
6869 {
6870 pos = pm->frag_parent;
6872 pos->bpm = NULL;
6874 }
6875 else
6877 return;
6878 }
6879}
6880
6881
6889static void
6891 struct GNUNET_TIME_Relative ack_delay)
6892{
6893 struct GNUNET_TIME_Relative delay;
6894
6896 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
6897 if (NULL != pa->queue && 1 == pa->num_send)
6899 if (NULL != pa->dvh && 1 == pa->num_send)
6900 update_dvh_performance (pa->dvh, delay, pa->message_size);
6901 if (NULL != pa->pm)
6904}
6905
6906
6914static int
6916 const struct TransportReliabilityAckMessage *ra)
6917{
6918 unsigned int n_acks;
6919
6920 (void) cls;
6921 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
6922 / sizeof(struct TransportCummulativeAckPayloadP);
6923 if (0 == n_acks)
6924 {
6925 GNUNET_break_op (0);
6926 return GNUNET_SYSERR;
6927 }
6928 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
6929 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
6930 {
6931 GNUNET_break_op (0);
6932 return GNUNET_SYSERR;
6933 }
6934 return GNUNET_OK;
6935}
6936
6937
6945static void
6947 const struct TransportReliabilityAckMessage *ra)
6948{
6949 struct CommunicatorMessageContext *cmc = cls;
6950 const struct TransportCummulativeAckPayloadP *ack;
6951 unsigned int n_acks;
6952 uint32_t ack_counter;
6953
6954 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
6955 / sizeof(struct TransportCummulativeAckPayloadP);
6956 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
6957 for (unsigned int i = 0; i < n_acks; i++)
6958 {
6959 struct PendingAcknowledgement *pa =
6961 if (NULL == pa)
6962 {
6964 "Received ACK from %s with UUID %s which is unknown to us!\n",
6965 GNUNET_i2s (&cmc->im.sender),
6966 GNUNET_uuid2s (&ack[i].ack_uuid.value));
6968 GST_stats,
6969 "# FRAGMENT_ACKS dropped, no matching pending message",
6970 1,
6971 GNUNET_NO);
6972 continue;
6973 }
6975 "Received ACK from %s with UUID %s\n",
6976 GNUNET_i2s (&cmc->im.sender),
6977 GNUNET_uuid2s (&ack[i].ack_uuid.value));
6978 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
6979 }
6980
6981 ack_counter = htonl (ra->ack_counter);
6982 (void) ack_counter; /* silence compiler warning for now */
6983 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
6984 // (DV and/or Neighbour?)
6985 finish_cmc_handling (cmc);
6986}
6987
6988
6996static int
6998 void *cls,
7000{
7001 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7002 const struct GNUNET_MessageHeader *inbox =
7003 (const struct GNUNET_MessageHeader *) &be[1];
7004 const char *is;
7005 uint16_t isize;
7006
7007 (void) cls;
7008 if (ntohs (inbox->size) >= size)
7009 {
7010 GNUNET_break_op (0);
7011 return GNUNET_SYSERR;
7012 }
7013 isize = ntohs (inbox->size);
7014 is = ((const char *) inbox) + isize;
7015 size -= isize;
7016 if ('\0' != is[size - 1])
7017 {
7018 GNUNET_break_op (0);
7019 return GNUNET_SYSERR;
7020 }
7021 return GNUNET_YES;
7022}
7023
7024
7033static void
7035 void *cls,
7037{
7038 struct CommunicatorMessageContext *cmc = cls;
7040 struct GNUNET_MQ_Envelope *env;
7041 struct TransportClient *tc;
7042 const struct GNUNET_MessageHeader *inbox =
7043 (const struct GNUNET_MessageHeader *) &be[1];
7044 uint16_t isize = ntohs (inbox->size);
7045 const char *target_communicator = ((const char *) inbox) + isize;
7046 char *sender;
7047 char *self;
7048
7049 GNUNET_asprintf (&sender,
7050 "%s",
7051 GNUNET_i2s (&cmc->im.sender));
7052 GNUNET_asprintf (&self,
7053 "%s",
7055
7056 /* Find client providing this communicator */
7057 for (tc = clients_head; NULL != tc; tc = tc->next)
7058 if ((CT_COMMUNICATOR == tc->type) &&
7059 (0 ==
7060 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7061 break;
7062 if (NULL == tc)
7063 {
7064 char *stastr;
7065
7067 &stastr,
7068 "# Backchannel message dropped: target communicator `%s' unknown",
7069 target_communicator);
7071 GNUNET_free (stastr);
7072 finish_cmc_handling (cmc);
7073 return;
7074 }
7075 /* Finally, deliver backchannel message to communicator */
7077 "Delivering backchannel message from %s to %s of type %u to %s\n",
7078 sender,
7079 self,
7080 ntohs (inbox->type),
7081 target_communicator);
7083 cbi,
7084 isize,
7086 cbi->pid = cmc->im.sender;
7087 memcpy (&cbi[1], inbox, isize);
7088 GNUNET_MQ_send (tc->mq, env);
7089 finish_cmc_handling (cmc);
7090}
7091
7092
7102static void
7104{
7105 struct DistanceVector *dv = cls;
7106 struct DistanceVectorHop *pos;
7107
7108 dv->timeout_task = NULL;
7109 while (NULL != (pos = dv->dv_head))
7110 {
7111 GNUNET_assert (dv == pos->dv);
7113 break;
7115 }
7116 if (NULL == pos)
7117 {
7118 free_dv_route (dv);
7119 return;
7120 }
7121 dv->timeout_task =
7123}
7124
7125
7126static void
7128{
7129
7130 const struct GNUNET_PeerIdentity target = vl->target;
7131
7132
7134 {
7135 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7136 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7137 0;
7138 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7141 struct CommunicatorMessageContext *cmc;
7142 struct RingBufferEntry *rbe;
7143 struct GNUNET_MessageHeader *mh;
7144
7146 "Sending from ring buffer, which has %u items\n",
7147 head);
7148
7149 ring_buffer_head = 0;
7150 for (unsigned int i = 0; i < head; i++)
7151 {
7152 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7153 cmc = rbe->cmc;
7154 mh = rbe->mh;
7155
7156 im = cmc->im;
7157 // mh = cmc->mh;
7159 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7160 mh->type,
7161 GNUNET_i2s (&im.sender),
7162 GNUNET_i2s2 (&target),
7163 (i + tail) % RING_BUFFER_SIZE);
7164 if (0 == GNUNET_memcmp (&target, &im.sender))
7165 {
7167 "Finish handling message of type %u and size %u\n",
7168 (unsigned int) ntohs (mh->type),
7169 (unsigned int) ntohs (mh->size));
7171 GNUNET_free (mh);
7172 GNUNET_free (rbe->cmc);
7173 GNUNET_free (rbe);
7174 }
7175 else
7176 {
7177 ring_buffer_copy[ring_buffer_head] = rbe;
7179 }
7180 }
7181
7184 {
7186 }
7187
7188 for (unsigned int i = 0; i < ring_buffer_head; i++)
7189 {
7190 ring_buffer[i] = ring_buffer_copy[i];
7192 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7193 i,
7194 ring_buffer_copy[i]->mh->type);
7196 "ring_buffer[i]->mh->type for i %u %u\n",
7197 i,
7198 ring_buffer[i]->mh->type);
7199 }
7200
7202 "%u items still in ring buffer\n",
7204 }
7205
7207 {
7208 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7209 struct PendingMessage *pm;
7210 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7212 0;
7213 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7216
7218 "Sending from ring buffer dv, which has %u items\n",
7219 head);
7220
7222 for (unsigned int i = 0; i < head; i++)
7223 {
7224 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7225
7227 "Sending to ring buffer target %s using vl target %s\n",
7228 GNUNET_i2s (&pm->target),
7229 GNUNET_i2s2 (&target));
7230 if (0 == GNUNET_memcmp (&target, &pm->target))
7231 {
7233 "Adding PendingMessage to vl, checking transmission.\n");
7234 pm->vl = vl;
7238 pm);
7239
7241 }
7242 else
7243 {
7244 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7246 }
7247 }
7248
7250 {
7252 }
7253
7254 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7255 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7256
7258 "%u items still in ring buffer dv.\n",
7260
7261 }
7262}
7263
7264
7272static void
7274{
7275 struct DistanceVector *dv = hop->dv;
7276 struct VirtualLink *vl;
7277
7278 vl = lookup_virtual_link (&dv->target);
7279 if (NULL == vl)
7280 {
7281
7282 vl = GNUNET_new (struct VirtualLink);
7284 "Creating new virtual link %p to %s using DV!\n",
7285 vl,
7286 GNUNET_i2s (&dv->target));
7287 vl->confirmed = GNUNET_YES;
7288 vl->message_uuid_ctr =
7290 vl->target = dv->target;
7296 links,
7297 &vl->target,
7298 vl,
7300 vl->dv = dv;
7301 dv->vl = vl;
7302 vl->visibility_task =
7305 /* We lacked a confirmed connection to the target
7306 before, so tell CORE about it (finally!) */
7309 }
7310 else
7311 {
7312 /* Link was already up, remember dv is also now available and we are done */
7313 vl->dv = dv;
7314 dv->vl = vl;
7315 if (GNUNET_NO == vl->confirmed)
7316 {
7317 vl->confirmed = GNUNET_YES;
7318 vl->visibility_task =
7321 /* We lacked a confirmed connection to the target
7322 before, so tell CORE about it (finally!) */
7325 }
7326 else
7328 "Virtual link to %s could now also use DV!\n",
7329 GNUNET_i2s (&dv->target));
7330 }
7331}
7332
7333
7359static int
7361 unsigned int path_len,
7362 struct GNUNET_TIME_Relative network_latency,
7363 struct GNUNET_TIME_Absolute path_valid_until)
7364{
7365 struct DistanceVectorHop *hop;
7366 struct DistanceVector *dv;
7367 struct Neighbour *next_hop;
7368 unsigned int shorter_distance;
7369
7370 if (path_len < 3)
7371 {
7372 /* what a boring path! not allowed! */
7373 GNUNET_break (0);
7374 return GNUNET_SYSERR;
7375 }
7376 GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
7377 next_hop = lookup_neighbour (&path[1]);
7378 if (NULL == next_hop)
7379 {
7380 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7381 GNUNET_break (0);
7382 return GNUNET_SYSERR;
7383 }
7384 for (unsigned int i = 2; i < path_len; i++)
7385 if (NULL != lookup_neighbour (&path[i]))
7386 {
7387 /* Useless path: we have a direct connection to some hop
7388 in the middle of the path, so this one is not even
7389 terribly useful for redundancy */
7391 "Path of %u hops useless: directly link to hop %u (%s)\n",
7392 path_len,
7393 i,
7394 GNUNET_i2s (&path[i]));
7396 "# Useless DV path ignored: hop is neighbour",
7397 1,
7398 GNUNET_NO);
7399 return GNUNET_SYSERR;
7400 }
7401 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7402 if (NULL == dv)
7403 {
7404 dv = GNUNET_new (struct DistanceVector);
7405 dv->target = path[path_len - 1];
7408 dv);
7411 dv_routes,
7412 &dv->target,
7413 dv,
7415 }
7416 /* Check if we have this path already! */
7417 shorter_distance = 0;
7418 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7419 pos = pos->next_dv)
7420 {
7421 if (pos->distance < path_len - 3)
7422 shorter_distance++;
7423 /* Note that the distances in 'pos' excludes us (path[0]),
7424 the next_hop (path[1]) and the target so we need to subtract three
7425 and check next_hop explicitly */
7426 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7427 {
7428 int match = GNUNET_YES;
7429
7430 for (unsigned int i = 0; i < pos->distance; i++)
7431 {
7432 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7433 {
7434 match = GNUNET_NO;
7435 break;
7436 }
7437 }
7438 if (GNUNET_YES == match)
7439 {
7440 struct GNUNET_TIME_Relative last_timeout;
7441
7442 /* Re-discovered known path, update timeout */
7444 "# Known DV path refreshed",
7445 1,
7446 GNUNET_NO);
7447 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7448 pos->timeout =
7450 pos->path_valid_until =
7451 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7452 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7453 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7454 if (0 <
7457 if (last_timeout.rel_value_us <
7460 .rel_value_us)
7461 {
7462 /* Some peer send DV learn messages too often, we are learning
7463 the same path faster than it would be useful; do not forward! */
7465 "Rediscovered path too quickly, not forwarding further\n")
7466 ;
7467 return GNUNET_NO;
7468 }
7470 "Refreshed known path to %s valid until %s, forwarding further\n",
7471 GNUNET_i2s (&dv->target),
7473 pos->path_valid_until));
7474 return GNUNET_YES;
7475 }
7476 }
7477 }
7478 /* Count how many shorter paths we have (incl. direct
7479 neighbours) before simply giving up on this one! */
7480 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7481 {
7482 /* We have a shorter path already! */
7484 "Have many shorter DV paths %s, not forwarding further\n",
7485 GNUNET_i2s (&dv->target));
7486 return GNUNET_NO;
7487 }
7488 /* create new DV path entry */
7490 "Discovered new DV path to %s valid until %s\n",
7491 GNUNET_i2s (&dv->target),
7492 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7493 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7494 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7495 hop->next_hop = next_hop;
7496 hop->dv = dv;
7497 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7498 memcpy (&hop[1],
7499 &path[2],
7500 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7502 hop->path_valid_until = path_valid_until;
7503 hop->distance = path_len - 3;
7504 hop->pd.aged_rtt = network_latency;
7505 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7507 next_hop->dv_head,
7508 next_hop->dv_tail,
7509 hop);
7510 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7512 return GNUNET_YES;
7513}
7514
7515
7523static int
7524check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7525{
7526 uint16_t size = ntohs (dvl->header.size);
7527 uint16_t num_hops = ntohs (dvl->num_hops);
7528 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7529
7530 (void) cls;
7531 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7532 {
7533 GNUNET_break_op (0);
7534 return GNUNET_SYSERR;
7535 }
7536 if (num_hops > MAX_DV_HOPS_ALLOWED)
7537 {
7538 GNUNET_break_op (0);
7539 return GNUNET_SYSERR;
7540 }
7541 for (unsigned int i = 0; i < num_hops; i++)
7542 {
7543 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7544 {
7545 GNUNET_break_op (0);
7546 return GNUNET_SYSERR;
7547 }
7548 if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
7549 {
7550 GNUNET_break_op (0);
7551 return GNUNET_SYSERR;
7552 }
7553 }
7554 return GNUNET_YES;
7555}
7556
7557
7569static void
7571 const struct TransportDVLearnMessage *msg,
7572 uint16_t bi_history,
7573 uint16_t nhops,
7574 const struct DVPathEntryP *hops,
7575 struct GNUNET_TIME_Absolute in_time)
7576{
7577 struct Neighbour *n;
7578 struct VirtualLink *vl;
7579 struct DVPathEntryP *dhops;
7580 char buf[sizeof(struct TransportDVLearnMessage)
7581 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7582 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7583 struct GNUNET_TIME_Relative nnd;
7584
7585 /* compute message for forwarding */
7587 "Forwarding DV learn message originating from %s to %s\n",
7588 GNUNET_i2s (&msg->initiator),
7589 GNUNET_i2s2 (next_hop));
7592 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7593 + (nhops + 1) * sizeof(struct DVPathEntryP));
7594 fwd->num_hops = htons (nhops + 1);
7595 fwd->bidirectional = htons (bi_history);
7598 msg->non_network_delay));
7600 fwd->init_sig = msg->init_sig;
7601 fwd->initiator = msg->initiator;
7602 fwd->challenge = msg->challenge;
7603 fwd->monotonic_time = msg->monotonic_time;
7604 dhops = (struct DVPathEntryP *) &fwd[1];
7605 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7606 dhops[nhops].hop = GST_my_identity;
7607 {
7608 struct DvHopPS dhp = {
7610 .purpose.size = htonl (sizeof(dhp)),
7611 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7612 .succ = *next_hop,
7613 .challenge = msg->challenge
7614 };
7616 &dhp,
7617 &dhops[nhops].hop_sig);
7618 }
7619 /*route_control_message_without_fc (next_hop,
7620 &fwd->header,
7621 RMO_UNCONFIRMED_ALLOWED);*/
7622 vl = lookup_virtual_link (next_hop);
7623 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7624 {
7626 &fwd->header,
7628 }
7629 else
7630 {
7631 /* Use route via neighbour */
7632 n = lookup_neighbour (next_hop);
7633 if (NULL != n)
7635 n,
7636 &fwd->header,
7638 }
7639}
7640
7641
7651static int
7653 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
7654 const struct GNUNET_PeerIdentity *init,
7656 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
7657{
7658 struct DvInitPS ip = { .purpose.purpose = htonl (
7660 .purpose.size = htonl (sizeof(ip)),
7661 .monotonic_time = sender_monotonic_time,
7662 .challenge = *challenge };
7663
7664 if (
7665 GNUNET_OK !=
7667 &ip,
7668 init_sig,
7669 &init->public_key))
7670 {
7671 GNUNET_break_op (0);
7672 return GNUNET_SYSERR;
7673 }
7674 return GNUNET_OK;
7675}
7676
7677
7682{
7687
7691 const struct DVPathEntryP *hops;
7692
7697
7702
7706 unsigned int num_eligible;
7707
7711 unsigned int num_selections;
7712
7716 uint16_t nhops;
7717
7721 uint16_t bi_history;
7722};
7723
7724
7733static int
7735 const struct GNUNET_PeerIdentity *pid,
7736 void *value)
7737{
7738 struct NeighbourSelectionContext *nsc = cls;
7739
7740 (void) value;
7741 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7742 return GNUNET_YES; /* skip initiator */
7743 for (unsigned int i = 0; i < nsc->nhops; i++)
7744 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7745 return GNUNET_YES;
7746 /* skip peers on path */
7747 nsc->num_eligible++;
7748 return GNUNET_YES;
7749}
7750
7751
7762static int
7764 const struct GNUNET_PeerIdentity *pid,
7765 void *value)
7766{
7767 struct NeighbourSelectionContext *nsc = cls;
7768
7770 "transmission %s\n",
7771 GNUNET_i2s (pid));
7772 (void) value;
7773 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7774 return GNUNET_YES; /* skip initiator */
7775 for (unsigned int i = 0; i < nsc->nhops; i++)
7776 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7777 return GNUNET_YES;
7778 /* skip peers on path */
7779 for (unsigned int i = 0; i < nsc->num_selections; i++)
7780 {
7781 if (nsc->selections[i] == nsc->num_eligible)
7782 {
7784 nsc->dvl,
7785 nsc->bi_history,
7786 nsc->nhops,
7787 nsc->hops,
7788 nsc->in_time);
7789 break;
7790 }
7791 }
7792 nsc->num_eligible++;
7793 return GNUNET_YES;
7794}
7795
7796
7840static unsigned int
7841calculate_fork_degree (unsigned int hops_taken,
7842 unsigned int neighbour_count,
7843 unsigned int eligible_count)
7844{
7845 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
7846 double eligible_ratio =
7847 ((double) eligible_count) / ((double) neighbour_count);
7848 double boost_factor = eligible_ratio * eligible_ratio;
7849 unsigned int rnd;
7850 double left;
7851
7852 if (hops_taken >= 64)
7853 {
7854 GNUNET_break (0);
7855 return 0; /* precaution given bitshift below */
7856 }
7857 for (unsigned int i = 1; i < hops_taken; i++)
7858 {
7859 /* For each hop, subtract the expected number of targets
7860 reached at distance d (so what remains divided by 2^d) */
7861 target_total -= (target_total * boost_factor / (1LLU << i));
7862 }
7863 rnd =
7864 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
7865 /* round up or down probabilistically depending on how close we were
7866 when floor()ing to rnd */
7867 left = target_total - (double) rnd;
7868 if (UINT32_MAX * left >
7870 rnd++; /* round up */
7872 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
7873 hops_taken,
7874 rnd,
7875 eligible_count,
7876 neighbour_count);
7877 return rnd;
7878}
7879
7880
7887static void
7888neighbour_store_dvmono_cb (void *cls, int success)
7889{
7890 struct Neighbour *n = cls;
7891
7892 n->sc = NULL;
7893 if (GNUNET_YES != success)
7895 "Failed to store other peer's monotonic time in peerstore!\n");
7896}
7897
7898
7906static void
7907handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7908{
7909 struct CommunicatorMessageContext *cmc = cls;
7911 int bi_hop;
7912 uint16_t nhops;
7913 uint16_t bi_history;
7914 const struct DVPathEntryP *hops;
7915 int do_fwd;
7916 int did_initiator;
7917 struct GNUNET_TIME_Absolute in_time;
7918 struct Neighbour *n;
7919
7920 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
7921 bi_history = ntohs (dvl->bidirectional);
7922 hops = (const struct DVPathEntryP *) &dvl[1];
7923 if (0 == nhops)
7924 {
7925 /* sanity check */
7926 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
7927 {
7928 GNUNET_break (0);
7929 finish_cmc_handling (cmc);
7930 return;
7931 }
7932 }
7933 else
7934 {
7936 "handle dv learn message last hop %s\n",
7937 GNUNET_i2s (&hops[nhops - 1].hop));
7938 /* sanity check */
7939 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
7940 {
7941 GNUNET_break (0);
7942 finish_cmc_handling (cmc);
7943 return;
7944 }
7945 }
7946
7948 cc = cmc->tc->details.communicator.cc;
7949 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
7950 cc); // FIXME: add bi-directional flag to cc?
7951 in_time = GNUNET_TIME_absolute_get ();
7952
7953 /* continue communicator here, everything else can happen asynchronous! */
7954 finish_cmc_handling (cmc);
7955
7956 n = lookup_neighbour (&dvl->initiator);
7957 if (NULL != n)
7958 {
7959 if ((n->dv_monotime_available == GNUNET_YES) &&
7962 {
7964 "DV learn from %s discarded due to time travel",
7965 GNUNET_i2s (&dvl->initiator));
7967 "# DV learn discarded due to time travel",
7968 1,
7969 GNUNET_NO);
7970 return;
7971 }
7973 &dvl->initiator,
7974 &dvl->challenge,
7975 &dvl->init_sig))
7976 {
7978 "DV learn signature from %s invalid\n",
7979 GNUNET_i2s (&dvl->initiator));
7980 GNUNET_break_op (0);
7981 return;
7982 }
7985 {
7986 if (NULL != n->sc)
7987 {
7989 "store cancel\n");
7991 }
7992 n->sc =
7994 "transport",
7995 &dvl->initiator,
7997 &dvl->monotonic_time,
7998 sizeof(dvl->monotonic_time),
8002 n);
8003 }
8004 }
8005 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8006 If signature verification load too high, implement random drop strategy */
8007 for (unsigned int i = 0; i < nhops; i++)
8008 {
8009 struct DvHopPS dhp = { .purpose.purpose =
8011 .purpose.size = htonl (sizeof(dhp)),
8012 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8013 .succ = (nhops == i + 1) ? GST_my_identity
8014 : hops[i + 1].hop,
8015 .challenge = dvl->challenge };
8016
8017 if (GNUNET_OK !=
8019 &dhp,
8020 &hops[i].hop_sig,
8021 &hops[i].hop.public_key))
8022 {
8024 "DV learn from %s signature of hop %u invalid\n",
8025 GNUNET_i2s (&dvl->initiator),
8026 i);
8028 "signature of hop %s invalid\n",
8029 GNUNET_i2s (&hops[i].hop));
8031 "pred %s\n",
8032 GNUNET_i2s (&dhp.pred));
8034 "succ %s\n",
8035 GNUNET_i2s (&dhp.succ));
8037 "hash %s\n",
8038 GNUNET_sh2s (&dhp.challenge.value));
8039 GNUNET_break_op (0);
8040 return;
8041 }
8042 }
8043 if (GNUNET_EXTRA_LOGGING > 0)
8044 {
8045 char *path;
8046
8047 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8048 for (unsigned int i = 0; i < nhops; i++)
8049 {
8050 char *tmp;
8051
8052 GNUNET_asprintf (&tmp,
8053 "%s%s%s",
8054 path,
8055 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8056 GNUNET_i2s (&hops[i].hop));
8057 GNUNET_free (path);
8058 path = tmp;
8059 }
8061 "Received DVInit via %s%s%s\n",
8062 path,
8063 bi_hop ? "<->" : "-->",
8065 GNUNET_free (path);
8066 }
8067 do_fwd = GNUNET_YES;
8068 if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
8069 {
8070 struct GNUNET_PeerIdentity path[nhops + 1];
8071 struct GNUNET_TIME_Relative host_latency_sum;
8072 struct GNUNET_TIME_Relative latency;
8073 struct GNUNET_TIME_Relative network_latency;
8074
8075 /* We initiated this, learn the forward path! */
8076 path[0] = GST_my_identity;
8077 path[1] = hops[0].hop;
8078 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8079
8080 // Need also something to lookup initiation time
8081 // to compute RTT! -> add RTT argument here?
8083 dvl->monotonic_time));
8084 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8085 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8086 // (based on dvl->challenge, we can identify time of origin!)
8087
8088 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8089 /* assumption: latency on all links is the same */
8090 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8091
8092 for (unsigned int i = 2; i <= nhops; i++)
8093 {
8094 struct GNUNET_TIME_Relative ilat;
8095
8096 /* assumption: linear latency increase per hop */
8097 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8098 path[i] = hops[i - 1].hop;
8100 "Learned path with %u hops to %s with latency %s\n",
8101 i,
8102 GNUNET_i2s (&path[i]),
8104 learn_dv_path (path,
8105 i + 1,
8106 ilat,
8109 }
8110 /* as we initiated, do not forward again (would be circular!) */
8111 do_fwd = GNUNET_NO;
8112 return;
8113 }
8114 if (bi_hop)
8115 {
8116 /* last hop was bi-directional, we could learn something here! */
8117 struct GNUNET_PeerIdentity path[nhops + 2];
8118
8119 path[0] = GST_my_identity;
8120 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8121 for (unsigned int i = 0; i < nhops; i++)
8122 {
8123 int iret;
8124
8125 if (0 == (bi_history & (1 << i)))
8126 break; /* i-th hop not bi-directional, stop learning! */
8127 if (i == nhops - 1)
8128 {
8129 path[i + 2] = dvl->initiator;
8130 }
8131 else
8132 {
8133 path[i + 2] = hops[nhops - i - 2].hop;
8134 }
8135
8137 "Learned inverse path with %u hops to %s\n",
8138 i + 2,
8139 GNUNET_i2s (&path[i + 2]));
8140 iret = learn_dv_path (path,
8141 i + 3,
8145 if (GNUNET_SYSERR == iret)
8146 {
8147 /* path invalid or too long to be interesting for US, thus should also
8148 not be interesting to our neighbours, cut path when forwarding to
8149 'i' hops, except of course for the one that goes back to the
8150 initiator */
8152 "# DV learn not forwarded due invalidity of path",
8153 1,
8154 GNUNET_NO);
8155 do_fwd = GNUNET_NO;
8156 break;
8157 }
8158 if ((GNUNET_NO == iret) && (nhops == i + 1))
8159 {
8160 /* we have better paths, and this is the longest target,
8161 so there cannot be anything interesting later */
8163 "# DV learn not forwarded, got better paths",
8164 1,
8165 GNUNET_NO);
8166 do_fwd = GNUNET_NO;
8167 break;
8168 }
8169 }
8170 }
8171 if (MAX_DV_HOPS_ALLOWED == nhops)
8172 {
8173 /* At limit, we're out of here! */
8174 return;
8175 }
8176
8177 /* Forward to initiator, if path non-trivial and possible */
8178 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8179 did_initiator = GNUNET_NO;
8180 if ((1 <= nhops) &&
8181 (GNUNET_YES ==
8183 {
8184 /* send back to origin! */
8186 "Sending DVL back to initiator %s\n",
8187 GNUNET_i2s (&dvl->initiator));
8188 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8189 did_initiator = GNUNET_YES;
8190 }
8191 /* We forward under two conditions: either we still learned something
8192 ourselves (do_fwd), or the path was darn short and thus the initiator is
8193 likely to still be very interested in this (and we did NOT already
8194 send it back to the initiator) */
8195 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8196 (GNUNET_NO == did_initiator)))
8197 {
8198 /* Pick random neighbours that are not yet on the path */
8199 struct NeighbourSelectionContext nsc;
8200 unsigned int n_cnt;
8201
8203 nsc.nhops = nhops;
8204 nsc.dvl = dvl;
8205 nsc.bi_history = bi_history;
8206 nsc.hops = hops;
8207 nsc.in_time = in_time;
8208 nsc.num_eligible = 0;
8211 &nsc);
8212 if (0 == nsc.num_eligible)
8213 return; /* done here, cannot forward to anyone else */
8215 nsc.num_selections =
8218 "Forwarding DVL to %u other peers\n",
8219 nsc.num_selections);
8220 for (unsigned int i = 0; i < nsc.num_selections; i++)
8221 nsc.selections[i] =
8222 (nsc.num_selections == n_cnt)
8223 ? i /* all were selected, avoid collisions by chance */
8225 nsc.num_eligible = 0;
8228 &nsc);
8229 }
8230}
8231
8232
8240static int
8241check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8242{
8243 uint16_t size = ntohs (dvb->header.size);
8244 uint16_t num_hops = ntohs (dvb->num_hops);
8245 const struct GNUNET_PeerIdentity *hops =
8246 (const struct GNUNET_PeerIdentity *) &dvb[1];
8247
8248 (void) cls;
8249 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8250 + sizeof(struct GNUNET_MessageHeader))
8251 {
8252 GNUNET_break_op (0);
8253 return GNUNET_SYSERR;
8254 }
8255 /* This peer must not be on the path */
8256 for (unsigned int i = 0; i < num_hops; i++)
8257 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8258 {
8259 GNUNET_break_op (0);
8260 return GNUNET_SYSERR;
8261 }
8262 return GNUNET_YES;
8263}
8264
8265
8278static void
8279forward_dv_box (struct Neighbour *next_hop,
8280 struct TransportDVBoxMessage *hdr,
8281 uint16_t total_hops,
8282 uint16_t num_hops,
8283 const struct GNUNET_PeerIdentity *hops,
8284 const void *enc_payload,
8285 uint16_t enc_payload_size)
8286{
8287 struct VirtualLink *vl = next_hop->vl;
8288 struct PendingMessage *pm;
8289 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8290 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8291 + enc_payload_size;
8292 char *buf;
8293 char msg_buf[msg_size] GNUNET_ALIGN;
8294 struct GNUNET_PeerIdentity *dhops;
8295
8296 hdr->num_hops = htons (num_hops);
8297 hdr->total_hops = htons (total_hops);
8298 hdr->header.size = htons (msg_size);
8299 memcpy (msg_buf, hdr, sizeof(*hdr));
8300 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8302 ;
8303 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8304 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8305
8306 if (GNUNET_YES == ntohs (hdr->without_fc))
8307 {
8309 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8310 enc_payload_size,
8311 GNUNET_i2s (&next_hop->pid),
8312 (unsigned int) num_hops,
8313 (unsigned int) total_hops);
8314 route_via_neighbour (next_hop, (const struct
8315 GNUNET_MessageHeader *) msg_buf,
8317 }
8318 else
8319 {
8320 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8322 "2 created pm %p storing vl %p \n",
8323 pm,
8324 vl);
8325 pm->pmt = PMT_DV_BOX;
8326 pm->vl = vl;
8327 pm->target = next_hop->pid;
8329 pm->logging_uuid = logging_uuid_gen++;
8331 pm->bytes_msg = msg_size;
8332 buf = (char *) &pm[1];
8333 memcpy (buf, msg_buf, msg_size);
8334
8336 "Created pending message %" PRIu64
8337 " for DV Box with next hop %s (%u/%u)\n",
8338 pm->logging_uuid,
8339 GNUNET_i2s (&next_hop->pid),
8340 (unsigned int) num_hops,
8341 (unsigned int) total_hops);
8342
8343 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8344 {
8346 vl->pending_msg_head,
8347 vl->pending_msg_tail,
8348 pm);
8349
8351 }
8352 else
8353 {
8355 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8356
8358 {
8360
8361 GNUNET_free (pm_old);
8362 }
8365 {
8368 }
8369 else
8371
8373 "%u items stored in DV ring buffer\n",
8376 }
8377 }
8378}
8379
8380
8386static void
8388{
8389 if (NULL != b->get)
8390 {
8392 b->get = NULL;
8393 GNUNET_assert (NULL != b->cmc);
8395 b->cmc = NULL;
8396 }
8397 if (NULL != b->task)
8398 {
8400 b->task = NULL;
8401 }
8402 if (NULL != b->sc)
8403 {
8405 "store cancel\n");
8407 b->sc = NULL;
8408 }
8410 "Removing backtalker for %s\n",
8411 GNUNET_i2s (&b->pid));
8413 GNUNET_YES ==
8415 GNUNET_free (b);
8416}
8417
8418
8427static int
8429 const struct GNUNET_PeerIdentity *pid,
8430 void *value)
8431{
8432 struct Backtalker *b = value;
8433
8434 (void) cls;
8435 (void) pid;
8436 free_backtalker (b);
8437 return GNUNET_OK;
8438}
8439
8440
8446static void
8448{
8449 struct Backtalker *b = cls;
8450
8452 "backtalker timeout.\n");
8453 b->task = NULL;
8455 {
8457 return;
8458 }
8459 GNUNET_assert (NULL == b->sc);
8460 free_backtalker (b);
8461}
8462
8463
8472static void
8474 const struct GNUNET_PEERSTORE_Record *record,
8475 const char *emsg)
8476{
8477 struct Backtalker *b = cls;
8478 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8479 struct GNUNET_TIME_Absolute mt;
8480
8481 (void) emsg;
8482 if (NULL == record)
8483 {
8484 /* we're done with #backtalker_monotime_cb() invocations,
8485 continue normal processing */
8486 b->get = NULL;
8487 GNUNET_assert (NULL != b->cmc);
8488 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8489 if (0 != b->body_size)
8491 else
8493 b->cmc = NULL;
8494 return;
8495 }
8496 if (sizeof(*mtbe) != record->value_size)
8497 {
8499 GNUNET_break (0);
8500 return;
8501 }
8502 mtbe = record->value;
8503 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8505 {
8507 "Backtalker message from %s dropped, monotime in the past\n",
8508 GNUNET_i2s (&b->pid));
8510 GST_stats,
8511 "# Backchannel messages dropped: monotonic time not increasing",
8512 1,
8513 GNUNET_NO);
8514 b->monotonic_time = mt;
8515 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8516 */
8517 b->body_size = 0;
8518 }
8520}
8521
8522
8530static void
8531backtalker_monotime_store_cb (void *cls, int success)
8532{
8533 struct Backtalker *b = cls;
8534
8535 if (GNUNET_OK != success)
8536 {
8538 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8539 }
8540 b->sc = NULL;
8541 if (NULL != b->task)
8542 {
8544 b->task = NULL;
8545 }
8547}
8548
8549
8555static void
8557{
8558 struct GNUNET_TIME_AbsoluteNBO mtbe;
8559
8560 if (NULL != b->sc)
8561 {
8563 "store cancel before store with sc %p\n",
8564 b->sc);
8565 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8566 b->sc = NULL;*/
8568 "store cancel before store with sc %p is null\n",
8569 b->sc);
8570 }
8571 else
8572 {
8574 b->task = NULL;
8575 }
8577 b->sc =
8579 "transport",
8580 &b->pid,
8582 &mtbe,
8583 sizeof(mtbe),
8587 b);
8588}
8589
8590
8598static void
8599handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8600{
8601 struct CommunicatorMessageContext *cmc = cls;
8602 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
8603 uint16_t num_hops = ntohs (dvb->num_hops);
8604 const struct GNUNET_PeerIdentity *hops =
8605 (const struct GNUNET_PeerIdentity *) &dvb[1];
8606 const char *enc_payload = (const char *) &hops[num_hops];
8607 uint16_t enc_payload_size =
8608 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
8609 struct DVKeyState key;
8610 struct GNUNET_HashCode hmac;
8611 const char *hdr;
8612 size_t hdr_len;
8613
8614 if (GNUNET_EXTRA_LOGGING > 0)
8615 {
8616 char *path;
8617
8619 for (unsigned int i = 0; i < num_hops; i++)
8620 {
8621 char *tmp;
8622
8623 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
8624 GNUNET_free (path);
8625 path = tmp;
8626 }
8628 "Received DVBox with remaining path %s\n",
8629 path);
8630 GNUNET_free (path);
8631 }
8632
8633 if (num_hops > 0)
8634 {
8635 /* We're trying from the end of the hops array, as we may be
8636 able to find a shortcut unknown to the origin that way */
8637 for (int i = num_hops - 1; i >= 0; i--)
8638 {
8639 struct Neighbour *n;
8640
8641 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8642 {
8643 GNUNET_break_op (0);
8644 finish_cmc_handling (cmc);
8645 return;
8646 }
8647 n = lookup_neighbour (&hops[i]);
8648 if (NULL == n)
8649 continue;
8651 "Skipping %u/%u hops ahead while routing DV Box\n",
8652 i,
8653 num_hops);
8654
8655 forward_dv_box (n,
8656 (struct TransportDVBoxMessage *) dvb,
8657 ntohs (dvb->total_hops) + 1,
8658 num_hops - i - 1, /* number of hops left */
8659 &hops[i + 1], /* remaining hops */
8660 enc_payload,
8661 enc_payload_size);
8663 "# DV hops skipped routing boxes",
8664 i,
8665 GNUNET_NO);
8667 "# DV boxes routed (total)",
8668 1,
8669 GNUNET_NO);
8670 finish_cmc_handling (cmc);
8671 return;
8672 }
8673 /* Woopsie, next hop not in neighbours, drop! */
8675 "# DV Boxes dropped: next hop unknown",
8676 1,
8677 GNUNET_NO);
8678 finish_cmc_handling (cmc);
8679 return;
8680 }
8681 /* We are the target. Unbox and handle message. */
8683 "# DV boxes opened (ultimate target)",
8684 1,
8685 GNUNET_NO);
8686 cmc->total_hops = ntohs (dvb->total_hops);
8687
8688 // DH key derivation with received DV, could be garbage.
8689 struct GNUNET_ShortHashCode km;
8690
8692 &dvb->ephemeral_key,
8693 &km))
8694 {
8695 GNUNET_break_op (0);
8696 finish_cmc_handling (cmc);
8697 return;
8698 }
8699 dv_setup_key_state_from_km (&km, &dvb->iv, &key);
8700 hdr = (const char *) &dvb[1];
8701 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8703 * ntohs (dvb->total_hops);
8704
8705 dv_hmac (&key, &hmac, hdr, hdr_len);
8706 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
8707 {
8708 /* HMAC mismatch, discard! */
8709 GNUNET_break_op (0);
8710 finish_cmc_handling (cmc);
8711 return;
8712 }
8713 /* begin actual decryption */
8714 {
8715 struct Backtalker *b;
8716 struct GNUNET_TIME_Absolute monotime;
8717 struct TransportDVBoxPayloadP ppay;
8718 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
8719 const struct GNUNET_MessageHeader *mh;
8720
8721 GNUNET_assert (hdr_len >=
8722 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
8723 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
8724 {
8726 "Error decrypting DV payload header\n");
8727 GNUNET_break_op (0);
8728 finish_cmc_handling (cmc);
8729 return;
8730 }
8731 if (GNUNET_OK != dv_decrypt (&key, body,
8732 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
8733 {
8735 "Error decrypting DV payload\n");
8736 GNUNET_break_op (0);
8737 finish_cmc_handling (cmc);
8738 return;
8739 }
8740 mh = (const struct GNUNET_MessageHeader *) body;
8741 dv_key_clean (&key);
8742 if (ntohs (mh->size) != sizeof(body))
8743 {
8744 GNUNET_break_op (0);
8745 finish_cmc_handling (cmc);
8746 return;
8747 }
8748 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
8749 switch (ntohs (mh->type))
8750 {
8752 GNUNET_break_op (0);
8753 finish_cmc_handling (cmc);
8754 return;
8755
8757 GNUNET_break_op (0);
8758 finish_cmc_handling (cmc);
8759 return;
8760
8761 default:
8762 /* permitted, continue */
8763 break;
8764 }
8765 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
8767 "Decrypted backtalk from %s\n",
8768 GNUNET_i2s (&ppay.sender));
8770 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
8771 {
8773 GST_stats,
8774 "# Backchannel messages dropped: monotonic time not increasing",
8775 1,
8776 GNUNET_NO);
8777 finish_cmc_handling (cmc);
8778 return;
8779 }
8780 if ((NULL == b) ||
8781 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
8782 {
8783 /* Check signature */
8784 struct EphemeralConfirmationPS ec;
8785
8788 ec.ephemeral_key = dvb->ephemeral_key;
8789 ec.purpose.size = htonl (sizeof(ec));
8791 if (
8792 GNUNET_OK !=
8795 &ec,
8796 &ppay.sender_sig,
8797 &ppay.sender.public_key))
8798 {
8799 /* Signature invalid, discard! */
8800 GNUNET_break_op (0);
8801 finish_cmc_handling (cmc);
8802 return;
8803 }
8804 }
8805 /* Update sender, we now know the real origin! */
8807 "DVBox received for me from %s via %s\n",
8808 GNUNET_i2s2 (&ppay.sender),
8809 GNUNET_i2s (&cmc->im.sender));
8810 cmc->im.sender = ppay.sender;
8811
8812 if (NULL != b)
8813 {
8814 /* update key cache and mono time */
8815 b->last_ephemeral = dvb->ephemeral_key;
8816 b->monotonic_time = monotime;
8818 b->timeout =
8820 cmc->mh = mh;
8822 return;
8823 }
8824 /* setup data structure to cache signature AND check
8825 monotonic time with PEERSTORE before forwarding backchannel payload */
8826 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
8827 b->pid = ppay.sender;
8828 b->body_size = sizeof(body);
8829 memcpy (&b[1], body, sizeof(body));
8833 &b->pid,
8834 b,
8836 b->monotonic_time = monotime; /* NOTE: to be checked still! */
8837 b->cmc = cmc;
8838 b->timeout =
8841 b->get =
8843 "transport",
8844 &b->pid,
8847 b);
8848 } /* end actual decryption */
8849}
8850
8851
8859static int
8861 const struct GNUNET_TRANSPORT_IncomingMessage *im)
8862{
8863 struct TransportClient *tc = cls;
8864
8865 if (CT_COMMUNICATOR != tc->type)
8866 {
8867 GNUNET_break (0);
8868 return GNUNET_SYSERR;
8869 }
8871 return GNUNET_OK;
8872}
8873
8874
8879{
8883 const char *address;
8884
8889};
8890
8891
8901static int
8903 const struct GNUNET_PeerIdentity *pid,
8904 void *value)
8905{
8906 struct CheckKnownAddressContext *ckac = cls;
8907 struct ValidationState *vs = value;
8908
8909 (void) pid;
8910 if (0 != strcmp (vs->address, ckac->address))
8911 return GNUNET_OK;
8912 ckac->vs = vs;
8913 return GNUNET_NO;
8914}
8915
8916
8922static void
8923validation_start_cb (void *cls);
8924
8925
8933static void
8935 struct GNUNET_TIME_Absolute new_time)
8936{
8938
8939 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
8940 return; /* be lazy */
8941 vs->next_challenge = new_time;
8942 if (NULL == vs->hn)
8943 vs->hn =
8945 else
8948 (NULL != validation_task))
8949 return;
8950 if (NULL != validation_task)
8952 /* randomize a bit */
8955 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
8956 new_time = GNUNET_TIME_absolute_add (new_time, delta);
8959}
8960
8961
8968static void
8970 const char *address)
8971{
8972 struct GNUNET_TIME_Absolute now;
8973 struct ValidationState *vs;
8974 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
8975
8977 pid,
8979 &ckac);
8980 if (NULL != (vs = ckac.vs))
8981 {
8982 /* if 'vs' is not currently valid, we need to speed up retrying the
8983 * validation */
8984 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
8985 {
8986 /* reduce backoff as we got a fresh advertisement */
8987 vs->challenge_backoff =
8990 vs->challenge_backoff,
8991 2));
8994 vs->challenge_backoff));
8995 }
8996 return;
8997 }
8999 vs = GNUNET_new (struct ValidationState);
9000 vs->pid = *pid;
9001 vs->valid_until =
9003 vs->first_challenge_use = now;
9004 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9006 &vs->challenge,
9007 sizeof(vs->challenge));
9008 vs->address = GNUNET_strdup (address);
9009 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9011 "Starting address validation `%s' of peer %s using challenge %s\n",
9012 address,
9013 GNUNET_i2s (pid),
9014 GNUNET_sh2s (&vs->challenge.value));
9018 &vs->pid,
9019 vs,
9022}
9023
9024
9025static struct Queue *
9026find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9027
9028
9029static void
9030suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9031
9032
9033static void
9035 const struct GNUNET_PeerIdentity *pid,
9036 const char *uri)
9037{
9038 (void) cls;
9039 struct Queue *q;
9040 int pfx_len;
9041 const char *eou;
9042 char *address;
9043
9044 eou = strstr (uri,
9045 "://");
9046 pfx_len = eou - uri;
9047 eou += 3;
9049 "%.*s-%s",
9050 pfx_len,
9051 uri,
9052 eou);
9053
9055 "helo for client %s\n",
9056 address);
9057 q = find_queue (pid, address);
9058 if (NULL == q)
9059 {
9061 }
9062 else
9065}
9066
9067
9075static void
9077 const struct GNUNET_PEERSTORE_Record *record,
9078 const char *emsg)
9079{
9080 struct IncomingRequest *ir = cls;
9082 struct GNUNET_MessageHeader *hello;
9083
9084 if (NULL != emsg)
9085 {
9087 "Got failure from PEERSTORE: %s\n",
9088 emsg);
9089 return;
9090 }
9091 hello = record->value;
9092 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
9093 {
9095 return;
9096 }
9100 NULL);
9102}
9103
9104
9105static void
9107{
9109 "Error in PEERSTORE monitoring\n");
9110}
9111
9112
9113static void
9115{
9117 "Done with initial PEERSTORE iteration during monitoring\n");
9118}
9119
9120
9129static void
9131 void *cls,
9132 const struct TransportValidationChallengeMessage *tvc)
9133{
9134 struct CommunicatorMessageContext *cmc = cls;
9136 struct VirtualLink *vl;
9137 struct GNUNET_TIME_RelativeNBO validity_duration;
9138 struct IncomingRequest *ir;
9139 struct Neighbour *n;
9140 struct GNUNET_PeerIdentity sender;
9141
9142 /* DV-routed messages are not allowed for validation challenges */
9143 if (cmc->total_hops > 0)
9144 {
9145 GNUNET_break_op (0);
9146 finish_cmc_handling (cmc);
9147 return;
9148 }
9149 validity_duration = cmc->im.expected_address_validity;
9151 "Received address validation challenge %s\n",
9152 GNUNET_sh2s (&tvc->challenge.value));
9153 /* If we have a virtual link, we use this mechanism to signal the
9154 size of the flow control window, and to allow the sender
9155 to ask for increases. If for us the virtual link is still down,
9156 we will always give a window size of zero. */
9157 tvr.header.type =
9159 tvr.header.size = htons (sizeof(tvr));
9160 tvr.reserved = htonl (0);
9161 tvr.challenge = tvc->challenge;
9162 tvr.origin_time = tvc->sender_time;
9163 tvr.validity_duration = validity_duration;
9164 {
9165 /* create signature */
9166 struct TransportValidationPS tvp = {
9168 .purpose.size = htonl (sizeof(tvp)),
9169 .validity_duration = validity_duration,
9170 .challenge = tvc->challenge
9171 };
9172
9174 &tvp,
9175 &tvr.signature);
9176 }
9177 sender = cmc->im.sender;
9178 vl = lookup_virtual_link (&sender);
9179 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9180 {
9181 // route_control_message_without_fc (&cmc->im.sender,
9183 &tvr.header,
9185 }
9186 else
9187 {
9188 /* Use route via neighbour */
9189 n = lookup_neighbour (&sender);
9190 if (NULL != n)
9191 route_via_neighbour (n, &tvr.header,
9194 }
9195
9196 finish_cmc_handling (cmc);
9197 if (NULL != vl)
9198 return;
9199
9200 /* For us, the link is still down, but we need bi-directional
9201 connections (for flow-control and for this to be useful for
9202 CORE), so we must try to bring the link up! */
9203
9204 /* (1) Check existing queues, if any, we may be lucky! */
9205 n = lookup_neighbour (&sender);
9206 if (NULL != n)
9207 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9208 start_address_validation (&sender, q->address);
9209 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9210 we could use */
9211 for (ir = ir_head; NULL != ir; ir = ir->next)
9212 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9213 return;
9214 /* we are already trying */
9215 ir = GNUNET_new (struct IncomingRequest);
9216 ir->pid = sender;
9218
9220 GNUNET_YES,
9221 "peerstore",
9222 NULL,
9225 NULL,
9227 NULL,
9229 ir);
9230 ir_total++;
9231 /* Bound attempts we do in parallel here, might otherwise get excessive */
9234}
9235
9236
9241{
9246
9251};
9252
9253
9263static int
9265 const struct GNUNET_PeerIdentity *pid,
9266 void *value)
9267{
9268 struct CheckKnownChallengeContext *ckac = cls;
9269 struct ValidationState *vs = value;
9270
9271 (void) pid;
9272 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9273 return GNUNET_OK;
9274 ckac->vs = vs;
9275 return GNUNET_NO;
9276}
9277
9278
9286static void
9287peerstore_store_validation_cb (void *cls, int success)
9288{
9289 struct ValidationState *vs = cls;
9290
9291 vs->sc = NULL;
9292 if (GNUNET_YES == success)
9293 return;
9295 "# Peerstore failed to store foreign address",
9296 1,
9297 GNUNET_NO);
9298}
9299
9300
9308static struct Queue *
9309find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9310{
9311 struct Neighbour *n;
9312
9313 n = lookup_neighbour (pid);
9314 if (NULL == n)
9315 return NULL;
9316 for (struct Queue *pos = n->queue_head; NULL != pos;
9317 pos = pos->next_neighbour)
9318 {
9319 if (0 == strcmp (pos->address, address))
9320 return pos;
9321 }
9322 return NULL;
9323}
9324
9325
9326static void
9328
9329static void
9331{
9332 struct ValidationState *vs = cls;
9333 struct Queue *q;
9334 struct GNUNET_TIME_Absolute now;
9335
9336 vs->revalidation_task = NULL;
9337 q = find_queue (&vs->pid, vs->address);
9338 if (NULL == q)
9339 {
9340 now = GNUNET_TIME_absolute_get ();
9341 vs->awaiting_queue = GNUNET_YES;
9342 suggest_to_connect (&vs->pid, vs->address);
9344 }
9345 else
9347}
9348
9349
9350static enum GNUNET_GenericReturnValue
9352 void *cls,
9353 const struct GNUNET_HashCode *key,
9354 void *value)
9355{
9356 (void) cls;
9358 "Key in revalidate map %s \n",
9359 GNUNET_h2s (key));
9360 return GNUNET_YES;
9361}
9362
9363
9372static void
9374 void *cls,
9375 const struct TransportValidationResponseMessage *tvr)
9376{
9377 struct CommunicatorMessageContext *cmc = cls;
9378 struct ValidationState *vs;
9379 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9380 .vs = NULL};
9381 struct GNUNET_TIME_Absolute origin_time;
9382 struct Queue *q;
9383 struct Neighbour *n;
9384 struct VirtualLink *vl;
9386 GST_cfg);
9387
9388 /* check this is one of our challenges */
9390 &cmc->im.sender,
9392 &ckac);
9393 if (NULL == (vs = ckac.vs))
9394 {
9395 /* This can happen simply if we 'forgot' the challenge by now,
9396 i.e. because we received the validation response twice */
9398 "# Validations dropped, challenge unknown",
9399 1,
9400 GNUNET_NO);
9402 "Validation response %s dropped, challenge unknown\n",
9403 GNUNET_sh2s (&tvr->challenge.value));
9404 finish_cmc_handling (cmc);
9405 return;
9406 }
9407
9408 /* sanity check on origin time */
9409 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9410 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9411 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9412 {
9414 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9415 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9416 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9417 GNUNET_break_op (0);
9418 finish_cmc_handling (cmc);
9419 return;
9420 }
9421
9422 {
9423 /* check signature */
9424 struct TransportValidationPS tvp = {
9426 .purpose.size = htonl (sizeof(tvp)),
9427 .validity_duration = tvr->validity_duration,
9428 .challenge = tvr->challenge
9429 };
9430
9431 if (
9432 GNUNET_OK !=
9434 &tvp,
9435 &tvr->signature,
9436 &cmc->im.sender.public_key))
9437 {
9438 GNUNET_break_op (0);
9439 finish_cmc_handling (cmc);
9440 return;
9441 }
9442 }
9443
9444 /* validity is capped by our willingness to keep track of the
9445 validation entry and the maximum the other peer allows */
9448 tvr->validity_duration),
9450 vs->validated_until =
9454 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9455 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9457 &vs->challenge,
9458 sizeof(vs->challenge));
9459 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9460 vs->validated_until,
9461 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9463 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9464 {
9466 "First challenge use is now %" PRIu64 " %s \n",
9467 vs->first_challenge_use.abs_value_us,
9468 GNUNET_sh2s (&vs->challenge.value));
9469 vs->first_challenge_use = now;
9470 }
9471 else
9473 "First challenge use is later %" PRIu64 " %s \n",
9474 vs->first_challenge_use.abs_value_us,
9475 GNUNET_sh2s (&vs->challenge.value));
9476 vs->last_challenge_use =
9477 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
9478 update_next_challenge_time (vs, vs->first_challenge_use);
9480 "Validation response %s from %s accepted, address valid until %s\n",
9481 GNUNET_sh2s (&tvr->challenge.value),
9482 GNUNET_i2s (&cmc->im.sender),
9484 /*memcpy (&hkey,
9485 &hc,
9486 sizeof (hkey));*/
9488 "Key %s for address %s map size %u contains %u\n",
9489 GNUNET_h2s (&vs->hc),
9490 vs->address,
9493 &vs->hc));
9497 &vs->hc,
9498 vs,
9502 NULL);
9503 vs->revalidation_task =
9508 "transport",
9509 &cmc->im.sender,
9511 vs->address,
9512 strlen (vs->address) + 1,
9513 vs->valid_until,
9516 vs);
9517 finish_cmc_handling (cmc);
9518
9519 /* Finally, we now possibly have a confirmed (!) working queue,
9520 update queue status (if queue still is around) */
9521 q = find_queue (&vs->pid, vs->address);
9522 if (NULL == q)
9523 {
9525 "# Queues lost at time of successful validation",
9526 1,
9527 GNUNET_NO);
9528 return;
9529 }
9530 q->validated_until = vs->validated_until;
9531 q->pd.aged_rtt = vs->validation_rtt;
9532 n = q->neighbour;
9533 vl = lookup_virtual_link (&vs->pid);
9534 if (NULL == vl)
9535 {
9536 vl = GNUNET_new (struct VirtualLink);
9538 "Creating new virtual link %p to %s using direct neighbour!\n",
9539 vl,
9540 GNUNET_i2s (&vs->pid));
9541 vl->confirmed = GNUNET_YES;
9542 vl->message_uuid_ctr =
9544 vl->target = n->pid;
9550 links,
9551 &vl->target,
9552 vl,
9554 vl->n = n;
9555 n->vl = vl;
9556 q->idle = GNUNET_YES;
9557 vl->visibility_task =
9558 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9560 /* We lacked a confirmed connection to the target
9561 before, so tell CORE about it (finally!) */
9564 }
9565 else
9566 {
9567 /* Link was already up, remember n is also now available and we are done */
9568 if (NULL == vl->n)
9569 {
9570 vl->n = n;
9571 n->vl = vl;
9572 if (GNUNET_YES == vl->confirmed)
9574 "Virtual link to %s could now also use direct neighbour!\n",
9575 GNUNET_i2s (&vs->pid));
9576 }
9577 else
9578 {
9579 GNUNET_assert (n == vl->n);
9580 }
9581 if (GNUNET_NO == vl->confirmed)
9582 {
9583 vl->confirmed = GNUNET_YES;
9584 q->idle = GNUNET_YES;
9585 vl->visibility_task =
9586 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9588 /* We lacked a confirmed connection to the target
9589 before, so tell CORE about it (finally!) */
9592 }
9593 }
9594}
9595
9596
9602static void
9604 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9605{
9606 struct TransportClient *tc = cls;
9607 struct CommunicatorMessageContext *cmc =
9609
9610 cmc->tc = tc;
9611 cmc->im = *im;
9613 "Received message with size %u and flow control id %" PRIu64
9614 " via communicator from peer %s\n",
9615 ntohs (im->header.size),
9616 im->fc_id,
9617 GNUNET_i2s (&im->sender));
9618 cmc->im.neighbour_sender = cmc->im.sender;
9619 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
9621}
9622
9623
9632static int
9634{
9635 (void) cls;
9636 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
9637
9639 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
9640 ntohs (fc->header.size),
9641 ntohl (fc->size_of_addresses),
9642 ntohl (fc->number_of_addresses),
9643 sizeof(struct TransportFlowControlMessage),
9644 sizeof (struct TransportGlobalNattedAddress));
9645
9646 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
9648 + ntohl (fc->number_of_addresses) * sizeof (struct
9650 + ntohl (fc->size_of_addresses))
9651 return GNUNET_OK;
9652 else
9653 {
9654 GNUNET_break_op (0);
9655 return GNUNET_SYSERR;
9656 }
9657}
9658
9659
9668static void
9670{
9671 struct CommunicatorMessageContext *cmc = cls;
9672 struct VirtualLink *vl;
9673 uint32_t seq;
9674 struct GNUNET_TIME_Absolute st;
9675 uint64_t os;
9676 uint64_t wnd;
9677 uint32_t random;
9678
9680 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
9681 vl = lookup_virtual_link (&cmc->im.sender);
9682 if (NULL == vl)
9683 {
9684 vl = GNUNET_new (struct VirtualLink);
9686 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
9687 vl,
9688 GNUNET_i2s (&cmc->im.sender));
9689 vl->confirmed = GNUNET_NO;
9690 vl->message_uuid_ctr =
9692 vl->target = cmc->im.sender;
9698 links,
9699 &vl->target,
9700 vl,
9702 }
9703 if (0 != ntohl (fc->number_of_addresses))
9704 {
9705 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
9706 const char *tgnas;
9707 unsigned int off = 0;
9708
9709 tgnas = (const char *) &fc[1];
9710
9711 for (int i = 1; i <= number_of_addresses; i++)
9712 {
9713 struct TransportGlobalNattedAddress *tgna = (struct
9715 *) &tgnas[off];
9716 char *addr = (char *) &tgna[1];
9717 unsigned int address_length;
9718
9719 address_length = ntohl (tgna->address_length);
9720 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
9721
9723 "received address %s length %u\n",
9724 addr,
9725 ntohl (tgna->address_length));
9726
9727 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
9728 }
9729 }
9731 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
9732 {
9734 "FC dropped: Message out of order\n");
9735 /* out of order, drop */
9737 "# FC dropped: message out of order",
9738 1,
9739 GNUNET_NO);
9740 finish_cmc_handling (cmc);
9741 return;
9742 }
9743 seq = ntohl (fc->seq);
9744 if (seq < vl->last_fc_seq)
9745 {
9746 /* Wrap-around/reset of other peer; start all counters from zero */
9748 }
9749 vl->last_fc_seq = seq;
9750 vl->last_fc_timestamp = st;
9754 (int64_t) (os - vl->incoming_fc_window_size_used);
9756 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
9757 GNUNET_i2s (&vl->target),
9758 (unsigned int) seq,
9759 (unsigned long long) vl->outbound_fc_window_size,
9760 (long long) vl->incoming_fc_window_size_loss);
9763 UINT32_MAX);
9764 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
9768 != wnd) ||
9769 (0 == random
9771 {
9773 "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",
9774 (unsigned long long) wnd,
9775 (unsigned long long) vl->incoming_fc_window_size,
9776 (unsigned long long) vl->last_outbound_window_size_received,
9779 }
9780 if ((wnd == vl->incoming_fc_window_size
9784 (NULL != vl->fc_retransmit_task))
9785 {
9787 "Stopping FC retransmission to %s: peer is current at window %llu\n",
9788 GNUNET_i2s (&vl->target),
9789 (unsigned long long) wnd);
9791 vl->fc_retransmit_task = NULL;
9792 vl->fc_retransmit_count = 0;
9793 }
9795 /* FC window likely increased, check transmission possibilities! */
9797 finish_cmc_handling (cmc);
9798}
9799
9800
9808static void
9810{
9812 { GNUNET_MQ_hd_var_size (fragment_box,
9815 cmc),
9816 GNUNET_MQ_hd_var_size (reliability_box,
9819 cmc),
9820 GNUNET_MQ_hd_var_size (reliability_ack,
9823 cmc),
9824 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
9827 cmc),
9828 GNUNET_MQ_hd_var_size (dv_learn,
9831 cmc),
9832 GNUNET_MQ_hd_var_size (dv_box,
9834 struct TransportDVBoxMessage,
9835 cmc),
9836 GNUNET_MQ_hd_var_size (flow_control,
9839 cmc),
9841 validation_challenge,
9844 cmc),
9846 validation_response,
9849 cmc),
9851 int ret;
9852 const struct GNUNET_MessageHeader *msg = cmc->mh;
9853
9855 "Handling message of type %u with %u bytes\n",
9856 (unsigned int) ntohs (msg->type),
9857 (unsigned int) ntohs (msg->size));
9859 if (GNUNET_SYSERR == ret)
9860 {
9861 GNUNET_break (0);
9863 GNUNET_free (cmc);
9864 return;
9865 }
9866 if (GNUNET_NO == ret)
9867 {
9868 /* unencapsulated 'raw' message */
9869 handle_raw_message (cmc, msg);
9870 }
9871}
9872
9873
9880static int
9882 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
9883{
9884 struct TransportClient *tc = cls;
9885
9886 if (CT_COMMUNICATOR != tc->type)
9887 {
9888 GNUNET_break (0);
9889 return GNUNET_SYSERR;
9890 }
9892 return GNUNET_OK;
9893}
9894
9895
9901static void
9903{
9904 if (pm->msg_uuid_set)
9905 return;
9906 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
9907 pm->msg_uuid_set = GNUNET_YES;
9908}
9909
9910
9919static struct PendingAcknowledgement *
9921 struct DistanceVectorHop *dvh,
9922 struct PendingMessage *pm)
9923{
9924 struct PendingAcknowledgement *pa;
9925
9926 pa = GNUNET_new (struct PendingAcknowledgement);
9927 pa->queue = queue;
9928 pa->dvh = dvh;
9929 pa->pm = pm;
9930 do
9931 {
9933 &pa->ack_uuid,
9934 sizeof(pa->ack_uuid));
9935 }
9938 &pa->ack_uuid.value,
9939 pa,
9941 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
9942 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
9943 if (NULL != dvh)
9946 pa->message_size = pm->bytes_msg;
9948 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
9950 pm->logging_uuid);
9951 return pa;
9952}
9953
9954
9966static struct PendingMessage *
9968 struct DistanceVectorHop *dvh,
9969 struct PendingMessage *pm)
9970{
9971 struct PendingAcknowledgement *pa;
9972 struct PendingMessage *ff;
9973 uint16_t mtu;
9974 uint16_t msize;
9975
9976 mtu = (UINT16_MAX == queue->mtu)
9977 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
9978 : queue->mtu;
9980 "Fragmenting message <%" PRIu64
9981 "> with size %u to %s for MTU %u\n",
9982 pm->logging_uuid,
9983 pm->bytes_msg,
9984 GNUNET_i2s (&pm->vl->target),
9985 (unsigned int) mtu);
9988 "Fragmenting message %" PRIu64 " <%" PRIu64
9989 "> with size %u to %s for MTU %u\n",
9990 pm->msg_uuid.uuid,
9991 pm->logging_uuid,
9992 pm->bytes_msg,
9993 GNUNET_i2s (&pm->vl->target),
9994 (unsigned int) mtu);
9995
9996 /* This invariant is established in #handle_add_queue_message() */
9997 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
9998
9999 /* select fragment for transmission, descending the tree if it has
10000 been expanded until we are at a leaf or at a fragment that is small
10001 enough
10002 */
10003 ff = pm;
10004 msize = ff->bytes_msg;
10005
10006 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10007 (ff->frag_off == msize) && (NULL != ff->head_frag))
10008 {
10009 ff = ff->head_frag; /* descent into fragmented fragments */
10010 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10011 }
10012
10013 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10014 {
10015 /* Did not yet calculate all fragments, calculate next fragment */
10016 struct PendingMessage *frag;
10017 struct TransportFragmentBoxMessage tfb;
10018 const char *orig;
10019 char *msg;
10020 uint16_t fragmax;
10021 uint16_t fragsize;
10022 uint16_t msize;
10023 uint16_t xoff = 0;
10024 pm->frag_count++;
10025
10026 orig = (const char *) &ff[1];
10027 msize = ff->bytes_msg;
10028 if (pm != ff)
10029 {
10030 const struct TransportFragmentBoxMessage *tfbo;
10031
10032 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10033 orig += sizeof(struct TransportFragmentBoxMessage);
10034 msize -= sizeof(struct TransportFragmentBoxMessage);
10035 xoff = ntohs (tfbo->frag_off);
10036 }
10037 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10038 fragsize = GNUNET_MIN (msize - ff->frag_off, fragmax);
10039 frag =
10040 GNUNET_malloc (sizeof(struct PendingMessage)
10041 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10043 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10044 frag,
10045 ff,
10046 pm->vl,
10047 pm);
10049 frag->vl = pm->vl;
10050 frag->frag_parent = ff;
10051 frag->timeout = pm->timeout;
10052 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10053 frag->pmt = PMT_FRAGMENT_BOX;
10054 msg = (char *) &frag[1];
10056 tfb.header.size =
10057 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10058 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10059 tfb.ack_uuid = pa->ack_uuid;
10060 tfb.msg_uuid = pm->msg_uuid;
10061 tfb.frag_off = htons (ff->frag_off + xoff);
10062 tfb.msg_size = htons (pm->bytes_msg);
10063 memcpy (msg, &tfb, sizeof(tfb));
10064 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10066 ff->tail_frag, frag);
10067 ff->frag_off += fragsize;
10068 ff = frag;
10069 }
10070
10071 /* Move head to the tail and return it */
10075 ff);
10079 ff);
10080
10081 return ff;
10082}
10083
10084
10097static struct PendingMessage *
10099 struct DistanceVectorHop *dvh,
10100 struct PendingMessage *pm)
10101{
10103 struct PendingAcknowledgement *pa;
10104 struct PendingMessage *bpm;
10105 char *msg;
10106
10107 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10108 return pm; /* already fragmented or reliability boxed, or control message:
10109 do nothing */
10110 if (NULL != pm->bpm)
10111 return pm->bpm; /* already computed earlier: do nothing */
10112 // TODO I guess we do not need this assertion. We might have a DLL with
10113 // fragments, because the MTU changed, and we do not need to fragment anymore.
10114 // But we should keep the fragments until message was completed, because
10115 // the MTU might change again.
10116 // GNUNET_assert (NULL == pm->head_frag);
10117 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10118 {
10119 /* failed hard */
10120 GNUNET_break (0);
10122 return NULL;
10123 }
10124
10126
10127 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10128 + pm->bytes_msg);
10130 "4 created pm %p storing vl %p from pm %p\n",
10131 bpm,
10132 pm->vl,
10133 pm);
10135 bpm->vl = pm->vl;
10136 bpm->frag_parent = pm;
10137 // Why was this needed?
10138 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10139 bpm->timeout = pm->timeout;
10141 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10144 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10145 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10146
10147 rbox.ack_uuid = pa->ack_uuid;
10148 msg = (char *) &bpm[1];
10149 memcpy (msg, &rbox, sizeof(rbox));
10150 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10151 pm->bpm = bpm;
10153 "Preparing reliability box for message <%" PRIu64
10154 "> of size %d (%d) to %s on queue %s\n",
10155 pm->logging_uuid,
10156 pm->bytes_msg,
10157 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10158 GNUNET_i2s (&pm->vl->target),
10159 queue->address);
10160 return bpm;
10161}
10162
10163
10164static void
10167{
10168 struct VirtualLink *vl = pm->vl;
10169 struct PendingMessage *pos;
10170
10171 /* re-insert sort in neighbour list */
10175 pm);
10176 pos = vl->pending_msg_tail;
10177 while ((NULL != pos) &&
10179 pos = pos->prev_vl;
10183 pos,
10184 pm);
10185}
10186
10187
10188static unsigned int
10190{
10191 struct PendingMessage *pos;
10193
10194 pos = pm->head_frag;
10195 while (NULL != pos)
10196 {
10197 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10198 GNUNET_NO == check_next_attempt_tree (pos, root))
10200 else
10201 {
10203 break;
10204 }
10205 pos = pos->next_frag;
10206 }
10207
10208 return frags_in_flight;
10209}
10210
10211
10212static void
10214{
10215 struct PendingMessage *pos;
10216
10217 pos = pm->head_frag;
10218 while (NULL != pos)
10219 {
10220 pos->frags_in_flight_round = pm->frags_in_flight_round;
10222 pos = pos->next_frag;
10223 }
10224}
10225
10226
10235static void
10238{
10239 if (NULL == pm->frag_parent)
10240 {
10241 pm->next_attempt = next_attempt;
10243 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
10244 pm->logging_uuid,
10247 }
10248 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
10249 {
10250 struct PendingMessage *root = pm->frag_parent;
10251
10252 while (NULL != root->frag_parent)
10253 root = root->frag_parent;
10255 "Next attempt for root message <%" PRIu64 "> set to %s\n",
10256 root->logging_uuid,
10258 root->next_attempt = next_attempt;
10260 }
10261 else
10262 {
10263 struct PendingMessage *root = pm->frag_parent;
10264
10265 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10266 root = root->frag_parent;
10267
10269 "frag_count next attempt %u\n",
10270 root->frag_count);
10271
10272 if (GNUNET_NO == root->frags_in_flight)
10273 {
10274 root->next_attempt = next_attempt;
10276 root->frags_in_flight_round++;
10278 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
10279 ">)set to %" PRIu64 "\n",
10280 pm->logging_uuid,
10281 root->logging_uuid,
10283 }
10284
10285 pm->next_attempt = root->next_attempt;
10286 pm->frags_in_flight_round = root->frags_in_flight_round;
10288
10289 if (root->bytes_msg == root->frag_off)
10290 root->frags_in_flight = check_next_attempt_tree (root, root);
10291 else
10293
10294 if (GNUNET_NO == root->frags_in_flight)
10295 {
10297 "We have no fragments in flight for message %" PRIu64
10298 ", reorder root! Next attempt is %" PRIu64 "\n",
10299 root->logging_uuid,
10301 if (PMT_DV_BOX == root->pmt)
10302 root = root->frag_parent;
10303 reorder_root_pm (root, root->next_attempt);
10304 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
10305 }
10306 else
10307 {
10308 double factor = ((double) root->frag_count - 1)
10309 / (double) root->frag_count;
10310 struct GNUNET_TIME_Relative s1;
10311 struct GNUNET_TIME_Relative s2;
10312 struct GNUNET_TIME_Relative plus_mean =
10315 next_attempt);
10316
10318 "frag_count %u after factor\n",
10319 root->frag_count);
10321 factor);
10322 s2 = GNUNET_TIME_relative_divide (plus,
10323 root->frag_count);
10324 plus_mean = GNUNET_TIME_relative_add (s1, s2);
10327 "We have fragments in flight for message %" PRIu64
10328 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
10329 root->logging_uuid,
10331 }
10332 }
10333}
10334
10335
10340{
10345
10350
10355
10360
10364 int frag;
10365
10369 int relb;
10370
10375
10379 unsigned int frags_in_flight;
10380
10385};
10386
10387
10399static void
10401 struct Queue *queue,
10402 struct VirtualLink *vl,
10403 struct DistanceVectorHop *dvh,
10404 size_t overhead)
10405{
10406 struct GNUNET_TIME_Absolute now;
10407
10408 now = GNUNET_TIME_absolute_get ();
10409 sc->to_early = GNUNET_NO;
10410 sc->frags_in_flight = GNUNET_NO;
10411 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
10412 pos = pos->next_vl)
10413 {
10414 size_t real_overhead = overhead;
10415 int frag;
10416 int relb;
10417
10418 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
10419 {
10421 "DV messages must not be DV-routed to next hop!\n");
10422 continue; /* DV messages must not be DV-routed to next hop! */
10423 }
10424 if (pos->next_attempt.abs_value_us > now.abs_value_us)
10425 {
10426 if (GNUNET_YES == pos->frags_in_flight)
10427 {
10428 sc->frags_in_flight = GNUNET_YES;
10430 "Fragments in flight for message %" PRIu64 "\n",
10431 pos->logging_uuid);
10432 }
10433 else
10434 {
10436 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
10437 PRIu64 "\n",
10438 pos->logging_uuid);
10439 sc->to_early = GNUNET_YES;
10440 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
10441 pos->next_attempt);
10442 continue;
10443 }
10444 // break; /* too early for all messages, they are sorted by next_attempt */
10445 }
10446 if (NULL != pos->qe)
10447 {
10449 "not eligible\n");
10450 continue; /* not eligible */
10451 }
10452 sc->consideration_counter++;
10453 /* determine if we have to fragment, if so add fragmentation
10454 overhead! */
10456 "check %" PRIu64 " for sc->best\n",
10457 pos->logging_uuid);
10458 frag = GNUNET_NO;
10459 if (((0 != queue->mtu) &&
10460 (pos->bytes_msg + real_overhead > queue->mtu)) ||
10461 (pos->bytes_msg > UINT16_MAX - sizeof(struct
10463 ||
10464 (NULL != pos->head_frag /* fragments already exist, should
10465 respect that even if MTU is UINT16_MAX for
10466 this queue */))
10467 {
10469 "fragment msg with size %u, realoverhead is %lu\n",
10470 pos->bytes_msg,
10471 real_overhead);
10472 frag = GNUNET_YES;
10473 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
10474 {
10475 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
10476 header without the ACK UUID when using a *reliable* channel! */
10477 }
10478 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10479 }
10480 /* determine if we have to reliability-box, if so add reliability box
10481 overhead */
10482 relb = GNUNET_NO;
10483 if ((GNUNET_NO == frag) &&
10484 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
10485 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
10486 {
10487 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
10488
10489 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
10490 {
10491 frag = GNUNET_YES;
10492 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10493 }
10494 else
10495 {
10496 relb = GNUNET_YES;
10497 }
10499 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
10500 pos->bytes_msg,
10501 real_overhead,
10502 queue->mtu,
10503 frag,
10504 relb);
10505 }
10506
10507 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
10508 message would beat it! */
10509 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
10510 {
10511 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
10512 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
10513 experimentally validated. There may be some huge potential for
10514 improvement here. Also, we right now only compare how well the
10515 given message fits _this_ queue, and do not consider how well other
10516 queues might suit the message. Taking other queues into consideration
10517 may further improve the result, but could also be expensive
10518 in terms of CPU time. */
10519 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
10520 long long pm_score = frag * 40 + relb * 20 + real_overhead;
10521 long long time_delta =
10522 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
10523 / 1000LL;
10524
10525 /* "time_delta" considers which message has been 'ready' for transmission
10526 for longer, if a message has a preference for low latency, increase
10527 the weight of the time_delta by 10x if it is favorable for that message */
10528 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10529 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
10530 time_delta *= 10; /* increase weight (always, both are low latency) */
10531 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10532 (time_delta > 0))
10533 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
10534 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10535 (time_delta < 0))
10536 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
10537 if (0 != queue->mtu)
10538 {
10539 /* Grant bonus if we are below MTU, larger bonus the closer we will
10540 be to the MTU */
10541 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
10542 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
10543 if (queue->mtu > real_overhead + pos->bytes_msg)
10544 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
10545 }
10546 if (sc_score + time_delta > pm_score)
10547 {
10549 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
10550 "\n",
10551 pos->logging_uuid,
10552 sc->best->logging_uuid);
10553 continue; /* sc_score larger, keep sc->best */
10554 }
10555 }
10556 sc->best = pos;
10557 sc->dvh = dvh;
10558 sc->frag = frag;
10559 sc->relb = relb;
10560 sc->real_overhead = real_overhead;
10561 }
10562}
10563
10564
10575static void
10577 struct Neighbour *next_hop,
10578 const struct GNUNET_MessageHeader *hdr,
10580{
10581 struct PendingMessageScoreContext *sc = cls;
10582 struct PendingMessage *pm = sc->best;
10583 struct PendingMessage *bpm;
10584 uint16_t bsize = ntohs (hdr->size);
10585
10586 GNUNET_assert (NULL == pm->bpm);
10587 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
10589 "5 created pm %p storing vl %p from pm %p\n",
10590 bpm,
10591 pm->vl,
10592 pm);
10594 bpm->pmt = PMT_DV_BOX;
10595 bpm->vl = pm->vl;
10596 bpm->timeout = pm->timeout;
10597 bpm->bytes_msg = bsize;
10598 bpm->frag_parent = pm;
10601 "Creating DV Box %" PRIu64 " for original message %" PRIu64
10602 " (next hop is %s)\n",
10604 pm->logging_uuid,
10605 GNUNET_i2s (&next_hop->pid));
10606 memcpy (&bpm[1], hdr, bsize);
10607 pm->bpm = bpm;
10608}
10609
10610
10626static void
10628{
10629 struct Queue *queue = cls;
10630 struct Neighbour *n = queue->neighbour;
10632 struct PendingMessage *pm;
10633
10634 queue->transmit_task = NULL;
10635 if (NULL == n->vl)
10636 {
10638 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
10639 GNUNET_i2s (&n->pid),
10640 queue->address);
10641 queue->idle = GNUNET_YES;
10642 return;
10643 }
10644 memset (&sc, 0, sizeof(sc));
10645 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
10646 if (NULL == sc.best)
10647 {
10648 /* Also look at DVH that have the n as first hop! */
10649 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
10650 dvh = dvh->next_neighbour)
10651 {
10653 queue,
10654 dvh->dv->vl,
10655 dvh,
10656 sizeof(struct GNUNET_PeerIdentity)
10657 * (1 + dvh->distance)
10658 + sizeof(struct TransportDVBoxMessage)
10659 + sizeof(struct TransportDVBoxPayloadP));
10660 }
10661 }
10662 if (NULL == sc.best)
10663 {
10664 /* no message pending, nothing to do here! */
10666 "No pending messages, queue `%s' to %s now idle\n",
10667 queue->address,
10668 GNUNET_i2s (&n->pid));
10669 if (GNUNET_YES == sc.to_early)
10670 schedule_transmit_on_queue (sc.to_early_retry_delay,
10671 queue,
10673 queue->idle = GNUNET_YES;
10674 return;
10675 }
10676 /* There is a message pending, we are certainly not idle */
10677 queue->idle = GNUNET_NO;
10678
10679 /* Given selection in `sc`, do transmission */
10680 pm = sc.best;
10682 "Selected message <%" PRIu64 ">\n",
10683 pm->logging_uuid);
10684 if (NULL != sc.dvh)
10685 {
10687 "Is this %u a DV box?\n",
10688 pm->pmt);
10689 GNUNET_assert (PMT_DV_BOX != pm->pmt);
10690 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
10691 {
10693 "Discard old box, because we have a new DV path.\n");
10694 free_pending_message (sc.best->bpm);
10695 sc.best->bpm = NULL;
10696 }
10697
10698 if (NULL == sc.best->bpm)
10699 {
10701 "encapsulate_for_dv 2\n");
10702 encapsulate_for_dv (sc.dvh->dv,
10703 1,
10704 &sc.dvh,
10705 (const struct GNUNET_MessageHeader *) &sc.best[1],
10707 &sc,
10708 RMO_NONE,
10709 GNUNET_NO);
10710 GNUNET_assert (NULL != sc.best->bpm);
10712 "%lu %lu %lu %lu %u\n",
10713 sizeof(struct GNUNET_PeerIdentity),
10714 sizeof(struct TransportDVBoxMessage),
10715 sizeof(struct TransportDVBoxPayloadP),
10716 sizeof(struct TransportFragmentBoxMessage),
10717 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
10718 sc.best->bpm->used_dvh = sc.dvh;
10719 }
10720 pm = sc.best->bpm;
10721 }
10722 if (GNUNET_YES == sc.frag)
10723 {
10724 pm = fragment_message (queue, sc.dvh, pm);
10725 if (NULL == pm)
10726 {
10728 "Fragmentation failed queue %s to %s for <%" PRIu64
10729 ">, trying again\n",
10730 queue->address,
10731 GNUNET_i2s (&n->pid),
10732 sc.best->logging_uuid);
10734 queue,
10736 return;
10737 }
10738 }
10739 else if (GNUNET_YES == sc.relb)
10740 {
10742 if (NULL == pm)
10743 {
10744 /* Reliability boxing failed, try next message... */
10745 GNUNET_log (
10747 "Reliability boxing failed queue %s to %s for <%" PRIu64
10748 ">, trying again\n",
10749 queue->address,
10750 GNUNET_i2s (&n->pid),
10751 sc.best->logging_uuid);
10753 queue,
10755 return;
10756 }
10757 }
10758
10759 /* Pass 'pm' for transission to the communicator */
10760 GNUNET_log (
10762 "Passing message <%" PRIu64
10763 "> to queue %s for peer %s (considered %u others)\n",
10764 pm->logging_uuid,
10765 queue->address,
10766 GNUNET_i2s (&n->pid),
10767 sc.consideration_counter);
10768
10769 /* Flow control: increment amount of traffic sent; if we are routing
10770 via DV (and thus the ultimate target of the pending message is for
10771 a different virtual link than the one of the queue), then we need
10772 to use up not only the window of the direct link but also the
10773 flow control window for the DV link! */
10774 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
10775
10776 if (pm->vl != queue->neighbour->vl)
10777 {
10778 /* If the virtual link of the queue differs, this better be distance
10779 vector routing! */
10780 GNUNET_assert (NULL != sc.dvh);
10781 /* If we do distance vector routing, we better not do this for a
10782 message that was itself DV-routed */
10783 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
10784 /* We use the size of the unboxed message here, to avoid counting
10785 the DV-Box header which is eaten up on the way by intermediaries */
10786 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
10787 }
10788 else
10789 {
10790 GNUNET_assert (NULL == sc.dvh);
10791 }
10792
10793 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
10794
10795 /* Check if this transmission somehow conclusively finished handing 'pm'
10796 even without any explicit ACKs */
10797 if ((PMT_CORE == pm->pmt) ||
10798 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
10799 {
10801 }
10802 else
10803 {
10804 struct GNUNET_TIME_Relative wait_duration;
10805 unsigned int wait_multiplier;
10806
10807 if (PMT_FRAGMENT_BOX == pm->pmt)
10808 {
10809 struct PendingMessage *root;
10810
10811 root = pm->frag_parent;
10812 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10813 root = root->frag_parent;
10814
10815 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
10816 / ((double) root->frag_off
10817 / (double) root->frag_count))
10818 * 4;
10819 }
10820 else
10821 {
10822 // No fragments, we use 4 RTT before retransmitting.
10823 wait_multiplier = 4;
10824 }
10825
10826 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
10827 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
10828
10830 "Wait multiplier %u\n",
10831 wait_multiplier);
10832
10833 /* Message not finished, waiting for acknowledgement.
10834 Update time by which we might retransmit 's' based on queue
10835 characteristics (i.e. RTT); it takes one RTT for the message to
10836 arrive and the ACK to come back in the best case; but the other
10837 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
10838 retransmitting.
10839
10840 OPTIMIZE: Note that in the future this heuristic should likely
10841 be improved further (measure RTT stability, consider message
10842 urgency and size when delaying ACKs, etc.) */
10843
10844 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
10845 queue->pd.aged_rtt.rel_value_us)
10846 wait_duration = queue->pd.aged_rtt;
10847 else
10848 {
10849 wait_duration = DEFAULT_ACK_WAIT_DURATION;
10850 wait_multiplier = 4;
10851 }
10854 wait_duration, wait_multiplier));
10856 wait_duration, wait_multiplier);
10858 "Waiting %s for ACK until %s\n",
10863 GNUNET_TIME_relative_multiply (wait_duration,
10864 wait_multiplier)));
10865 }
10866 /* finally, re-schedule queue transmission task itself */
10868 queue,
10870}
10871
10872
10879static void
10881 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
10882{
10883 struct TransportClient *tc = cls;
10884
10885 if (CT_COMMUNICATOR != tc->type)
10886 {
10887 GNUNET_break (0);
10889 return;
10890 }
10891 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
10892 queue = queue->next_client)
10893 {
10894 struct Neighbour *neighbour = queue->neighbour;
10895
10896 if ((ntohl (dqm->qid) != queue->qid) ||
10897 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
10898 continue;
10900 "Dropped queue %s to peer %s\n",
10901 queue->address,
10902 GNUNET_i2s (&neighbour->pid));
10903 free_queue (queue);
10905 return;
10906 }
10907 GNUNET_break (0);
10909}
10910
10911
10912static void
10914 struct TransportClient *tc)
10915{
10916 struct PendingMessage *pm;
10917
10918 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
10919 qe->queue->queue_tail,
10920 qe);
10921 qe->queue->queue_length--;
10922 tc->details.communicator.total_queue_length--;
10924 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
10925 qe->queue->address,
10926 qe->queue->qid,
10927 GNUNET_i2s (&qe->queue->neighbour->pid),
10928 qe->queue->queue_length,
10929 tc->details.communicator.total_queue_length);
10930
10931 /* if applicable, resume transmissions that waited on ACK */
10933 tc->details.communicator.total_queue_length)
10934 {
10935 /* Communicator dropped below threshold, resume all queues
10936 incident with this client! */
10938 GST_stats,
10939 "# Transmission throttled due to communicator queue limit",
10940 -1,
10941 GNUNET_NO);
10942 for (struct Queue *queue = tc->details.communicator.queue_head;
10943 NULL != queue;
10944 queue = queue->next_client)
10945 {
10947 queue,
10949 }
10950 }
10951 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
10952 {
10953 /* queue dropped below threshold; only resume this one queue */
10955 "# Transmission throttled due to queue queue limit",
10956 -1,
10957 GNUNET_NO);
10959 qe->queue,
10961 }
10962 else if (1 == qe->queue->q_capacity)
10963 {
10964 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
10966 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
10967 PRIu64 ".\n",
10968 qe->queue->qid,
10969 qe->queue->q_capacity);
10970 /* message queue has capacity; only resume this one queue */
10971 /* queue dropped below threshold; only resume this one queue */
10973 "# Transmission throttled due to message queue capacity",
10974 -1,
10975 GNUNET_NO);
10977 qe->queue,
10979 }
10980
10981 if (NULL != (pm = qe->pm))
10982 {
10983 struct VirtualLink *vl;
10984
10985 // GNUNET_assert (qe == pm->qe);
10986 pm->qe = NULL;
10987 /* If waiting for this communicator may have blocked transmission
10988 of pm on other queues for this neighbour, force schedule
10989 transmit on queue for queues of the neighbour */
10990 if (NULL == pm->frag_parent)
10991 {
10992 vl = pm->vl;
10993 if ((NULL != vl) &&
10994 (NULL != vl->pending_msg_head) &&
10995 (vl->pending_msg_head == pm))
10997 }
10998 }
10999 GNUNET_free (qe);
11000}
11001
11002
11009static void
11011 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11012{
11013 struct TransportClient *tc = cls;
11014 struct QueueEntry *qe;
11015
11016 if (CT_COMMUNICATOR != tc->type)
11017 {
11018 GNUNET_break (0);
11020 return;
11021 }
11022
11023 /* find our queue entry matching the ACK */
11024 qe = NULL;
11026 "Looking for queue for PID %s\n",
11027 GNUNET_i2s (&sma->receiver));
11028 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11029 queue = queue->next_client)
11030 {
11031 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11032 continue;
11034 "Found PID %s\n",
11035 GNUNET_i2s (&queue->neighbour->pid));
11036
11037
11038 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11039 qep = qep->next)
11040 {
11041 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11042 sma->qid))
11043 continue;
11045 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11046 PRIu64 " Ack QID %u\n",
11047 qep->mid,
11048 queue->qid,
11049 GNUNET_ntohll (sma->mid),
11050 ntohl (sma->qid));
11051 qe = qep;
11052 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11054 "For pending message %" PRIu64 " we had retransmissions.\n",
11055 qe->pm->logging_uuid);
11056 break;
11057 }
11058 }
11059 if (NULL == qe)
11060 {
11062 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11063 GNUNET_ntohll (sma->mid),
11064 ntohl (sma->qid));
11065 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11066 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11067 /* this should never happen */
11068 // GNUNET_break (0);
11069 // GNUNET_SERVICE_client_drop (tc->client);
11071 return;
11072 }
11075}
11076
11077
11087static int
11089 const struct GNUNET_PeerIdentity *pid,
11090 void *value)
11091{
11092 struct TransportClient *tc = cls;
11093 struct Neighbour *neighbour = value;
11094
11095 GNUNET_assert (CT_MONITOR == tc->type);
11096 for (struct Queue *q = neighbour->queue_head; NULL != q;
11097 q = q->next_neighbour)
11098 {
11099 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11100 .cs = q->cs,
11101 .num_msg_pending = q->num_msg_pending,
11102 .num_bytes_pending = q->num_bytes_pending };
11103
11104 notify_monitor (tc, pid, q->address, q->nt, &me);
11105 }
11106 return GNUNET_OK;
11107}
11108
11109
11116static void
11119{
11120 struct TransportClient *tc = cls;
11121
11122 if (CT_NONE != tc->type)
11123 {
11124 GNUNET_break (0);
11126 return;
11127 }
11128 tc->type = CT_MONITOR;
11129 tc->details.monitor.peer = start->peer;
11130 tc->details.monitor.one_shot = ntohl (start->one_shot);
11134}
11135
11136
11144static struct TransportClient *
11146{
11147 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11148 {
11149 if (CT_COMMUNICATOR != tc->type)
11150 continue;
11151 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11152 return tc;
11153 }
11154 GNUNET_log (
11156 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11157 prefix);
11158 return NULL;
11159}
11160
11161
11169static void
11171{
11172 static uint32_t idgen;
11173 struct TransportClient *tc;
11174 char *prefix;
11175 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11176 struct GNUNET_MQ_Envelope *env;
11177 size_t alen;
11178
11180 if (NULL == prefix)
11181 {
11182 GNUNET_break (0); /* We got an invalid address!? */
11183 return;
11184 }
11186 if (NULL == tc)
11187 {
11189 "# Suggestions ignored due to missing communicator",
11190 1,
11191 GNUNET_NO);
11193 "Cannot connect to %s at `%s', no matching communicator present\n",
11194 GNUNET_i2s (pid),
11195 address);
11197 return;
11198 }
11199 /* forward suggestion for queue creation to communicator */
11201 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11202 (unsigned int) idgen,
11203 prefix,
11204 GNUNET_i2s (pid),
11205 address);
11207 alen = strlen (address) + 1;
11208 env =
11210 cqm->request_id = htonl (idgen++);
11211 cqm->receiver = *pid;
11212 memcpy (&cqm[1], address, alen);
11213 GNUNET_MQ_send (tc->mq, env);
11214}
11215
11216
11224static void
11226{
11228 struct GNUNET_TIME_Absolute monotonic_time;
11229
11230 if (NULL != vs->revalidation_task)
11231 {
11232 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
11233 vs->revalidation_task = NULL;
11234 }
11235 /*memcpy (&hkey,
11236 &hc,
11237 sizeof (hkey));*/
11239 "Remove key %s for address %s map size %u contains %u\n",
11240 GNUNET_h2s (&vs->hc),
11241 vs->address,
11244 &vs->hc));
11246
11248 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
11249 vs->last_challenge_use.abs_value_us)
11250 {
11251 vs->first_challenge_use = monotonic_time;
11252 }
11253 vs->last_challenge_use = monotonic_time;
11254 tvc.header.type =
11256 tvc.header.size = htons (sizeof(tvc));
11257 tvc.reserved = htonl (0);
11258 tvc.challenge = vs->challenge;
11259 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
11261 "Sending address validation challenge %s to %s\n",
11263 GNUNET_i2s (&q->neighbour->pid));
11264 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
11265}
11266
11267
11273static void
11275{
11276 struct ValidationState *vs;
11277 struct Queue *q;
11279 GST_cfg);
11280
11281 (void) cls;
11282 validation_task = NULL;
11284 /* drop validations past their expiration */
11285 while (
11286 (NULL != vs) &&
11288 {
11290 "Validation response %s cleaned up\n",
11291 GNUNET_sh2s (&vs->challenge.value));
11294 }
11295 if (NULL == vs)
11296 {
11298 "Address validation task not scheduled anymore, nothing to do\n");
11299 return; /* woopsie, no more addresses known, should only
11300 happen if we're really a lonely peer */
11301 }
11302 q = find_queue (&vs->pid, vs->address);
11303 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
11304 {
11306 "To early to start next address validation for challenge %s\n",
11307 GNUNET_sh2s (&vs->challenge.value));
11308 return;
11309 }
11310 if (NULL == q)
11311 {
11312 vs->awaiting_queue = GNUNET_YES;
11313 suggest_to_connect (&vs->pid, vs->address);
11314 }
11315 else
11317 /* Finally, reschedule next attempt */
11318 vs->challenge_backoff =
11319 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
11322 "Address validation task will run again in %s\n",
11323 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
11324 GNUNET_YES));
11327 vs->challenge_backoff));
11328}
11329
11330
11335{
11339 struct Queue *q;
11340
11344 unsigned int quality_count;
11345
11349 unsigned int num_queues;
11350
11355 unsigned int k;
11356};
11357
11358
11370static int
11372 const struct GNUNET_PeerIdentity *pid,
11373 void *value)
11374{
11375 struct QueueQualityContext *ctx = cls;
11376 struct Neighbour *n = value;
11377 int do_inc;
11378
11379 (void) pid;
11380 do_inc = GNUNET_NO;
11381 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
11382 {
11383 ctx->num_queues++;
11384 if (0 == ctx->k--)
11385 ctx->q = q;
11386 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
11387 statistics and consider those as well here? */
11388 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
11389 do_inc = GNUNET_YES;
11390 }
11391 if (GNUNET_YES == do_inc)
11392 ctx->quality_count++;
11393 return GNUNET_OK;
11394}
11395
11396
11408static void
11410{
11411 struct LearnLaunchEntry *lle;
11412 struct QueueQualityContext qqc;
11413 struct TransportDVLearnMessage dvl;
11414
11415 (void) cls;
11416 dvlearn_task = NULL;
11418 return; /* lost all connectivity, cannot do learning */
11419 qqc.quality_count = 0;
11420 qqc.num_queues = 0;
11424 &qqc);
11426 {
11427 struct GNUNET_TIME_Relative delay;
11428 unsigned int factor;
11429
11430 /* scale our retries by how far we are above the threshold */
11434 "At connection quality %u, will launch DV learn in %s\n",
11435 qqc.quality_count,
11438 return;
11439 }
11440 /* remove old entries in #dvlearn_map if it has grown too big */
11441 while (MAX_DV_LEARN_PENDING <=
11443 {
11444 lle = lle_tail;
11447 &lle->challenge.value,
11448 lle));
11450 GNUNET_free (lle);
11451 }
11452 /* setup data structure for learning */
11453 lle = GNUNET_new (struct LearnLaunchEntry);
11455 &lle->challenge,
11456 sizeof(lle->challenge));
11458 "Starting launch DV learn with challenge %s\n",
11459 GNUNET_sh2s (&lle->challenge.value));
11464 &lle->challenge.value,
11465 lle,
11468 dvl.header.size = htons (sizeof(dvl));
11469 dvl.num_hops = htons (0);
11470 dvl.bidirectional = htons (0);
11472 dvl.monotonic_time =
11474 {
11475 struct DvInitPS dvip = {
11476 .purpose.purpose = htonl (
11478 .purpose.size = htonl (sizeof(dvip)),
11479 .monotonic_time = dvl.monotonic_time,
11480 .challenge = lle->challenge
11481 };
11482
11484 &dvip,
11485 &dvl.init_sig);
11486 }
11488 dvl.challenge = lle->challenge;
11489
11490 qqc.quality_count = 0;
11492 qqc.num_queues = 0;
11493 qqc.q = NULL;
11496 &qqc);
11497 GNUNET_assert (NULL != qqc.q);
11498
11499 /* Do this as close to transmission time as possible! */
11501
11502 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
11503 /* reschedule this job, randomizing the time it runs (but no
11504 actual backoff!) */
11508 NULL);
11509}
11510
11511
11519static char *
11521{
11522 const char *colon;
11523 char *colon_rest;
11524 size_t colon_rest_length;
11525 char *address_without_port;
11526
11527 colon = strchr (address,':');
11528 colon_rest = GNUNET_strndup (address, colon - address);
11529 colon_rest_length = strlen (colon_rest);
11530 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
11531 GNUNET_free (colon_rest);
11532
11533 return address_without_port;
11534}
11535
11536
11546static int
11548 const struct GNUNET_PeerIdentity *pid,
11549 void *value)
11550{
11551 struct Queue *q = cls;
11552 struct ValidationState *vs = value;
11553 char *address_without_port_vs;
11554 char *address_without_port_q;
11555 int success = GNUNET_YES;
11556
11557 // TODO Check if this is really necessary.
11558 address_without_port_vs = get_address_without_port (vs->address);
11559 address_without_port_q = get_address_without_port (q->address);
11560
11562 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
11563 GNUNET_i2s (pid),
11564 address_without_port_vs,
11565 address_without_port_q);
11566 (void) pid;
11567 if ((GNUNET_YES == vs->awaiting_queue) &&
11568 (0 == strcmp (address_without_port_vs, address_without_port_q)))
11569 {
11570
11571 vs->awaiting_queue = GNUNET_NO;
11573 success = GNUNET_NO;
11574 }
11575
11576 GNUNET_free (address_without_port_vs);
11577 GNUNET_free (address_without_port_q);
11578 return success;
11579}
11580
11581
11590static void
11592 const struct GNUNET_PEERSTORE_Record *record,
11593 const char *emsg)
11594{
11595 struct Neighbour *n = cls;
11596 struct GNUNET_TIME_AbsoluteNBO *mtbe;
11597
11598 (void) emsg;
11599 if (NULL == record)
11600 {
11601 /* we're done with #neighbour_dv_monotime_cb() invocations,
11602 continue normal processing */
11603 n->get = NULL;
11605 return;
11606 }
11607 if (0 == record->value_size)
11608 {
11610 GNUNET_break (0);
11611 return;
11612 }
11613 mtbe = record->value;
11618}
11619
11620
11621static void
11623 const struct GNUNET_PeerIdentity *pid,
11624 const char *uri)
11625{
11626 struct Queue *queue = cls;
11627 const char *slash;
11628 char *address_uri;
11629 char *prefix;
11630 char *uri_without_port;
11631 char *address_uri_without_port;
11632
11633 slash = strrchr (uri, '/');
11634 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
11635 GNUNET_assert (NULL != slash);
11636 slash++;
11637 GNUNET_asprintf (&address_uri,
11638 "%s-%s",
11639 prefix,
11640 slash);
11641
11642 address_uri_without_port = get_address_without_port (queue->address);
11643 uri_without_port = get_address_without_port (address_uri);
11644 if (0 == strcmp (uri_without_port, address_uri_without_port))
11645 {
11646 queue->is_global_natted = GNUNET_NO;
11647 }
11648
11650 "not global natted %u %s %s %s %s %s %u\n",
11651 queue->is_global_natted,
11652 uri,
11653 queue->address,
11654 uri_without_port,
11655 address_uri_without_port,
11656 prefix,
11657 GNUNET_NO);
11659 GNUNET_free (address_uri);
11660 GNUNET_free (address_uri_without_port);
11661 GNUNET_free (uri_without_port);
11662}
11663
11664
11665static void
11667{
11669 "Error in PEERSTORE monitoring for checking global natted\n");
11670}
11671
11672
11673static void
11675{
11677 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
11678}
11679
11680
11682{
11686 char *addr;
11687
11692};
11693
11694
11695static enum GNUNET_GenericReturnValue
11697 const struct GNUNET_PeerIdentity *pid,
11698 void *value)
11699{
11700 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
11701 struct TransportGlobalNattedAddress *tgna = value;
11702 char *addr = (char *) &tgna[1];
11703
11704 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
11705 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
11706 {
11707 tgna_cls->tgna = tgna;
11708 return GNUNET_NO;
11709 }
11710 return GNUNET_YES;
11711}
11712
11713
11714static void
11716 const struct GNUNET_PEERSTORE_Record *record,
11717 const char *emsg)
11718{
11719 struct Queue *queue = cls;
11720 struct Neighbour *neighbour = queue->neighbour;
11722 struct GNUNET_MessageHeader *hello;
11724 size_t address_len_without_port;
11725
11726 if (NULL != emsg)
11727 {
11729 "Got failure from PEERSTORE: %s\n",
11730 emsg);
11731 return;
11732 }
11733 if (NULL == record)
11734 {
11735 queue->mo = NULL;
11736 return;
11737 }
11738 if (0 == record->value_size)
11739 {
11741 GNUNET_break (0);
11742 return;
11743 }
11744 queue->is_global_natted = GNUNET_YES;
11745 hello = record->value;
11748 "before not global natted %u\n",
11749 queue->is_global_natted);
11752 queue);
11754 "after not global natted %u\n",
11755 queue->is_global_natted);
11757
11758 tgna_cls.addr = get_address_without_port (queue->address);
11759 tgna_cls.tgna = NULL;
11760 address_len_without_port = strlen (tgna_cls.addr);
11762 &neighbour->pid,
11764 &tgna_cls);
11765 if (NULL != tgna_cls.tgna)
11767 " tgna_cls.tgna tgna %p %lu %u %u\n",
11768 tgna_cls.tgna,
11769 neighbour->size_of_global_addresses,
11770 ntohl (tgna_cls.tgna->address_length),
11771 neighbour->number_of_addresses);
11772 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
11773 {
11774 struct TransportGlobalNattedAddress *tgna;
11775
11776 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
11777 + address_len_without_port);
11778 tgna->address_length = htonl (address_len_without_port);
11779 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
11781 &neighbour->pid,
11782 tgna,
11784 neighbour->number_of_addresses++;
11785 neighbour->size_of_global_addresses += address_len_without_port;
11787 "Created tgna %p\n",
11788 tgna);
11789 }
11790 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
11791 {
11793 &neighbour->pid,
11794 tgna_cls.tgna);
11795 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
11797 );
11798 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
11799 ;
11800 GNUNET_assert (0 < neighbour->number_of_addresses);
11801 neighbour->number_of_addresses--;
11803 "removed tgna %p\n",
11804 tgna_cls.tgna);
11805 GNUNET_free (tgna_cls.tgna);
11806 }
11807 GNUNET_free (tgna_cls.addr);
11809}
11810
11811
11818static void
11820 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
11821{
11822 struct TransportClient *tc = cls;
11823 struct Queue *queue;
11824 struct Neighbour *neighbour;
11825 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
11826 const char *addr;
11827 uint16_t addr_len;
11828
11829 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
11830 {
11831 /* MTU so small as to be useless for transmissions,
11832 required for #fragment_message()! */
11833 GNUNET_break_op (0);
11835 return;
11836 }
11837 /* This may simply be a queue update */
11838 for (queue = tc->details.communicator.queue_head;
11839 NULL != queue;
11840 queue = queue->next_client)
11841 {
11842 validated_until = queue->validated_until;
11843 if (queue->qid != ntohl (aqm->qid))
11844 continue;
11845 break;
11846 }
11847
11848 if (NULL != queue)
11849 {
11850 neighbour = queue->neighbour;
11851 }
11852 else
11853 {
11854 neighbour = lookup_neighbour (&aqm->receiver);
11855 if (NULL == neighbour)
11856 {
11857 neighbour = GNUNET_new (struct Neighbour);
11859 GNUNET_YES);
11860 neighbour->pid = aqm->receiver;
11863 neighbours,
11864 &neighbour->pid,
11865 neighbour,
11867 neighbour->get =
11869 "transport",
11870 &neighbour->pid,
11873 neighbour);
11874 }
11875 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
11876 addr = (const char *) &aqm[1];
11878 "New queue %s to %s available with QID %u and q_len %" PRIu64
11879 " and mtu %u\n",
11880 addr,
11881 GNUNET_i2s (&aqm->receiver),
11882 ntohl (aqm->qid),
11883 GNUNET_ntohll (aqm->q_len),
11884 ntohl (aqm->mtu));
11885 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
11886 queue->tc = tc;
11887 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us != validated_until.abs_value_us)
11888 {
11890 "New queue with QID %u inherit validated until\n",
11891 ntohl (aqm->qid));
11892 queue->validated_until = validated_until;
11893 }
11894 queue->address = (const char *) &queue[1];
11895 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
11896 queue->qid = ntohl (aqm->qid);
11897 queue->neighbour = neighbour;
11899 queue->unlimited_length = GNUNET_YES;
11900 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
11901 memcpy (&queue[1], addr, addr_len);
11902 /* notify monitors about new queue */
11903 {
11904 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
11905
11906 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
11907 }
11909 neighbour->queue_head,
11910 neighbour->queue_tail,
11911 queue);
11913 tc->details.communicator.queue_head,
11914 tc->details.communicator.queue_tail,
11915 queue);
11916
11917 }
11918 queue->mtu = ntohl (aqm->mtu);
11919 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
11920 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
11921 queue->idle = GNUNET_YES;
11923 GNUNET_YES,
11924 "peerstore",
11925 &neighbour->pid,
11928 NULL,
11930 NULL,
11932 queue);
11933 /* check if valdiations are waiting for the queue */
11935 &aqm->receiver))
11936 {
11939 &aqm->
11940 receiver,
11941 &
11943 queue))
11944 start_address_validation (&aqm->receiver, queue->address);
11945 }
11946 else
11947 start_address_validation (&aqm->receiver, queue->address);
11948 /* look for traffic for this queue */
11949 // TODO Check whether this makes any sense at all.
11950 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
11951 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
11952 /* might be our first queue, try launching DV learning */
11953 if (NULL == dvlearn_task)
11956}
11957
11958
11965static void
11967 const struct
11969{
11970 struct TransportClient *tc = cls;
11971 struct Queue *target_queue = NULL;
11972
11974 "Received queue update message for %u with q_len %llu and mtu %u\n",
11975 ntohl (msg->qid),
11976 (unsigned long long) GNUNET_ntohll (msg->q_len),
11977 ntohl (msg->mtu));
11978 for (target_queue = tc->details.communicator.queue_head;
11979 NULL != target_queue;
11980 target_queue = target_queue->next_client)
11981 {
11982 if (ntohl (msg->qid) == target_queue->qid)
11983 break;
11984 }
11985 if (NULL == target_queue)
11986 {
11988 "Queue to update no longer exists! Discarding update.\n");
11989 return;
11990 }
11991
11992 target_queue->nt = msg->nt;
11993 target_queue->mtu = ntohl (msg->mtu);
11994 target_queue->cs = msg->cs;
11995 target_queue->priority = ntohl (msg->priority);
11996 /* The update message indicates how many messages
11997 * the queue should be able to handle.
11998 */
12000 target_queue->unlimited_length = GNUNET_YES;
12001 else
12002 target_queue->unlimited_length = GNUNET_NO;
12003 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12004 if (0 < target_queue->q_capacity)
12006 target_queue,
12009}
12010
12011
12019static void
12021 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12022{
12023 struct TransportClient *tc = cls;
12024
12025 if (CT_COMMUNICATOR != tc->type)
12026 {
12027 GNUNET_break (0);
12029 return;
12030 }
12032 "# Suggestions succeeded at communicator",
12033 1,
12034 GNUNET_NO);
12036 "Request #%u for communicator to create queue succeeded\n",
12037 (unsigned int) ntohs (cqr->request_id));
12039}
12040
12041
12050static void
12052 void *cls,
12053 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12054{
12055 struct TransportClient *tc = cls;
12056
12057 if (CT_COMMUNICATOR != tc->type)
12058 {
12059 GNUNET_break (0);
12061 return;
12062 }
12064 "Request #%u for communicator to create queue failed\n",
12065 (unsigned int) ntohs (cqr->request_id));
12067 "# Suggestions failed in queue creation at communicator",
12068 1,
12069 GNUNET_NO);
12071}
12072
12073
12081static void
12083{
12084 struct TransportClient *tc = cls;
12085 struct PeerRequest *pr;
12086
12087 if (CT_APPLICATION != tc->type)
12088 {
12089 GNUNET_break (0);
12091 return;
12092 }
12093 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
12094 &msg->peer);
12095 if (NULL == pr)
12096 {
12097 GNUNET_break (0);
12099 return;
12100 }
12101 (void) stop_peer_request (tc, &pr->pid, pr);
12103}
12104
12105
12106static void
12108 const struct GNUNET_PeerIdentity *pid,
12109 const char *uri)
12110{
12111 (void) cls;
12112 struct Queue *q;
12113 int pfx_len;
12114 const char *eou;
12115 char *address;
12116
12117 eou = strstr (uri,
12118 "://");
12119 pfx_len = eou - uri;
12120 eou += 3;
12122 "%.*s-%s",
12123 pfx_len,
12124 uri,
12125 eou);
12126
12128 "hello for client %s\n",
12129 address);
12130
12131 q = find_queue (pid, address);
12132 if (NULL == q)
12133 {
12135 }
12136 else
12139}
12140
12141
12149static void
12151 const struct GNUNET_PEERSTORE_Record *record,
12152 const char *emsg)
12153{
12154 struct PeerRequest *pr = cls;
12156 struct GNUNET_MessageHeader *hello;
12157
12158 if (NULL != emsg)
12159 {
12161 "Got failure from PEERSTORE: %s\n",
12162 emsg);
12163 return;
12164 }
12165 hello = record->value;
12166 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
12167 {
12169 return;
12170 }
12174 NULL);
12176}
12177
12178
12179static void
12181{
12183 "Error in PEERSTORE monitoring\n");
12184}
12185
12186
12187static void
12189{
12191 "Done with initial PEERSTORE iteration during monitoring\n");
12192}
12193
12194
12202static void
12204{
12205 struct TransportClient *tc = cls;
12206 struct PeerRequest *pr;
12207
12208 if (CT_NONE == tc->type)
12209 {
12210 tc->type = CT_APPLICATION;
12211 tc->details.application.requests =
12213 }
12214 if (CT_APPLICATION != tc->type)
12215 {
12216 GNUNET_break (0);
12218 return;
12219 }
12221 "Client suggested we talk to %s with preference %d at rate %u\n",
12222 GNUNET_i2s (&msg->peer),
12223 (int) ntohl (msg->pk),
12224 (int) ntohl (msg->bw.value__));
12225 pr = GNUNET_new (struct PeerRequest);
12226 pr->tc = tc;
12227 pr->pid = msg->peer;
12228 pr->bw = msg->bw;
12229 pr->pk = (enum GNUNET_MQ_PriorityPreferences) ntohl (msg->pk);
12231 tc->details.application.requests,
12232 &pr->pid,
12233 pr,
12235 {
12236 GNUNET_break (0);
12237 GNUNET_free (pr);
12239 return;
12240 }
12241 pr->nc =
12243 GNUNET_YES,
12244 "peerstore",
12245 NULL,
12248 NULL,
12250 NULL,
12252 pr);
12254}
12255
12256
12265static int
12267 const struct RequestHelloValidationMessage *m)
12268{
12269 (void) cls;
12271 return GNUNET_OK;
12272}
12273
12274
12282static void
12284 const struct RequestHelloValidationMessage *m)
12285{
12286 struct TransportClient *tc = cls;
12287 struct Queue *q;
12288
12289 q = find_queue (&m->peer, (const char *) &m[1]);
12290 if (NULL == q)
12291 {
12292 suggest_to_connect (&m->peer, (const char *) &m[1]);
12293 }
12294 else
12295 start_address_validation (&m->peer, (const char *) &m[1]);
12297}
12298
12299
12308static int
12310 const struct GNUNET_PeerIdentity *pid,
12311 void *value)
12312{
12313 struct Neighbour *neighbour = value;
12314
12315 (void) cls;
12316 (void) pid;
12317 GNUNET_break (0); // should this ever happen?
12318 free_neighbour (neighbour);
12319
12320 return GNUNET_OK;
12321}
12322
12323
12332static int
12334 const struct GNUNET_PeerIdentity *pid,
12335 void *value)
12336{
12337 struct DistanceVector *dv = value;
12338
12339 (void) cls;
12340 (void) pid;
12341 free_dv_route (dv);
12342
12343 return GNUNET_OK;
12344}
12345
12346
12355static int
12357 const struct GNUNET_PeerIdentity *pid,
12358 void *value)
12359{
12360 struct ValidationState *vs = value;
12361
12362 (void) cls;
12363 (void) pid;
12365 return GNUNET_OK;
12366}
12367
12368
12377static int
12378free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
12379{
12380 struct PendingAcknowledgement *pa = value;
12381
12382 (void) cls;
12383 (void) key;
12385 return GNUNET_OK;
12386}
12387
12388
12397static int
12399 const struct GNUNET_PeerIdentity *pid,
12400 void *value)
12401{
12402 struct AcknowledgementCummulator *ac = value;
12403
12404 (void) cls;
12405 (void) pid;
12407 GNUNET_free (ac);
12408 return GNUNET_OK;
12409}
12410
12411
12418static void
12419do_shutdown (void *cls)
12420{
12421 struct LearnLaunchEntry *lle;
12422 (void) cls;
12423
12425 "shutdown logic\n");
12428 &free_neighbour_cb, NULL);
12429 if (NULL != validation_task)
12430 {
12432 validation_task = NULL;
12433 }
12434 if (NULL != dvlearn_task)
12435 {
12437 dvlearn_task = NULL;
12438 }
12439 if (NULL != GST_stats)
12440 {
12442 GST_stats = NULL;
12443 }
12444 if (NULL != GST_my_hello)
12445 {
12447 GST_my_hello = NULL;
12448 }
12449 if (NULL != GST_my_private_key)
12450 {
12452 GST_my_private_key = NULL;
12453 }
12456 NULL);
12458 ack_cummulators = NULL;
12461 NULL);
12463 pending_acks = NULL;
12466 neighbours = NULL;
12469 links = NULL;
12472 NULL);
12474 backtalkers = NULL;
12477 NULL);
12479 validation_map = NULL;
12481 revalidation_map = NULL;
12482 while (NULL != ir_head)
12484 GNUNET_assert (0 == ir_total);
12485 while (NULL != (lle = lle_head))
12486 {
12488 GNUNET_free (lle);
12489 }
12490 if (NULL != peerstore)
12491 {
12493 "Disconnecting from PEERSTORE service\n");
12495 peerstore = NULL;
12496 }
12498 dvlearn_map = NULL;
12500 validation_heap = NULL;
12503 dv_routes = NULL;
12505}
12506
12507
12508static void
12509shutdown_task (void *cls)
12510{
12512
12514 "Shutdown task executed\n");
12515 if (NULL != clients_head)
12516 {
12517 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
12518 {
12520 "client still connected: %u\n",
12521 tc->type);
12522 }
12523 }
12524 else
12525 do_shutdown (cls);
12526
12527}
12528
12529
12537static void
12538run (void *cls,
12539 const struct GNUNET_CONFIGURATION_Handle *c,
12541{
12542 (void) cls;
12543 (void) service;
12544 /* setup globals */
12547 GST_cfg = c;
12555 GNUNET_YES);
12562 if (NULL == GST_my_private_key)
12563 {
12564 GNUNET_log (
12566 _ (
12567 "Transport service is lacking key configuration settings. Exiting.\n"));
12569 return;
12570 }
12574 "My identity is `%s'\n",
12581 "transport",
12582 0,
12583 0,
12584 NULL,
12585 0,
12586 NULL,
12587 NULL,
12588 NULL);
12589 if (NULL == peerstore)
12590 {
12591 GNUNET_break (0);
12593 return;
12594 }
12595}
12596
12597
12602 "transport",
12604 &run,
12607 NULL,
12608 /* communication with applications */
12609 GNUNET_MQ_hd_fixed_size (suggest,
12612 NULL),
12613 GNUNET_MQ_hd_fixed_size (suggest_cancel,
12616 NULL),
12617 GNUNET_MQ_hd_var_size (request_hello_validation,
12620 NULL),
12621 /* communication with core */
12622 GNUNET_MQ_hd_fixed_size (client_start,
12624 struct StartMessage,
12625 NULL),
12626 GNUNET_MQ_hd_var_size (client_send,
12628 struct OutboundMessage,
12629 NULL),
12630 GNUNET_MQ_hd_fixed_size (client_recv_ok,
12632 struct RecvOkMessage,
12633 NULL),
12634 /* communication with communicators */
12635 GNUNET_MQ_hd_var_size (communicator_available,
12638 NULL),
12639 GNUNET_MQ_hd_var_size (communicator_backchannel,
12642 NULL),
12643 GNUNET_MQ_hd_var_size (add_address,
12646 NULL),
12647 GNUNET_MQ_hd_fixed_size (del_address,
12650 NULL),
12651 GNUNET_MQ_hd_var_size (incoming_msg,
12654 NULL),
12655 GNUNET_MQ_hd_fixed_size (queue_create_ok,
12658 NULL),
12659 GNUNET_MQ_hd_fixed_size (queue_create_fail,
12662 NULL),
12663 GNUNET_MQ_hd_var_size (add_queue_message,
12666 NULL),
12667 GNUNET_MQ_hd_fixed_size (update_queue_message,
12670 NULL),
12671 GNUNET_MQ_hd_fixed_size (del_queue_message,
12674 NULL),
12675 GNUNET_MQ_hd_fixed_size (send_message_ack,
12678 NULL),
12679 /* communication with monitors */
12680 GNUNET_MQ_hd_fixed_size (monitor_start,
12683 NULL),
12685
12686
12687/* 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_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int ret
Final status code.
Definition: gnunet-arm.c:94
static char * init
Set to the name of a service to start.
Definition: gnunet-arm.c:74
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
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.
Definition: gnunet-config.c:66
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 HostSet * builder
NULL if we are not currently iterating over peer information.
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 ogg_stream_state os
Ogg stream state.
static OpusEncoder * enc
OPUS encoder.
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_REVOCATION_Query * q
Handle for revocation query.
static struct GNUNET_FS_SearchContext * sc
Definition: gnunet-search.c:87
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 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 GNUNET_PeerIdentity GST_my_identity
Our public key.
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?...
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 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 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.
#define BACKCHANNEL_INACTIVITY_TIMEOUT
How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
static void hello_for_client_error_cb(void *cls)
static void free_neighbour(struct Neighbour *neighbour)
Release memory used by neighbour.
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 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...
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 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 struct GNUNET_CRYPTO_EddsaPrivateKey * GST_my_private_key
Our private key.
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 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.
struct GNUNET_HELLO_Builder * GST_my_hello
Our HELLO.
#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.
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT
How many messages can we have pending for a given communicator process before we start to throttle th...
static void free_reassembly_context(struct ReassemblyContext *rc)
Free rc.
static struct VirtualLink * lookup_virtual_link(const struct GNUNET_PeerIdentity *pid)
Lookup virtual link for peer pid.
static int check_connection_quality(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counte...
static void reorder_root_pm(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
static void core_env_sent_cb(void *cls)
Function called when we are done giving a message of a certain size to CORE and should thus decrement...
static unsigned int ir_total
Length of the DLL starting at ir_head.
static int in_shutdown
Indication if we have received a shutdown signal and are in the process of cleaning up.
static void select_best_pending_from_link(struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
Select the best pending message from vl for transmission via queue.
static void suggest_to_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Signature of a function called with a communicator address of a peer pid that an application wants us...
static void free_timedout_queue_entry(void *cls)
static void handle_send_message_ack(void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
Message was transmitted.
static void shutdown_task(void *cls)
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?
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 void do_shutdown(void *cls)
Function called when the service shuts down.
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 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.
GNUNET_SERVICE_MAIN("transport", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(suggest, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST, struct ExpressPreferenceMessage, NULL), GNUNET_MQ_hd_fixed_size(suggest_cancel, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL, struct ExpressPreferenceMessage, NULL), GNUNET_MQ_hd_var_size(request_hello_validation, GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION, struct RequestHelloValidationMessage, NULL), GNUNET_MQ_hd_fixed_size(client_start, GNUNET_MESSAGE_TYPE_TRANSPORT_START, struct StartMessage, NULL), GNUNET_MQ_hd_var_size(client_send, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, struct OutboundMessage, NULL), GNUNET_MQ_hd_fixed_size(client_recv_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK, struct RecvOkMessage, NULL), GNUNET_MQ_hd_var_size(communicator_available, GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, NULL), GNUNET_MQ_hd_var_size(communicator_backchannel, GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL, struct GNUNET_TRANSPORT_CommunicatorBackchannel, NULL), GNUNET_MQ_hd_var_size(add_address, GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, struct GNUNET_TRANSPORT_AddAddressMessage, NULL), GNUNET_MQ_hd_fixed_size(del_address, GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS, struct GNUNET_TRANSPORT_DelAddressMessage, NULL), GNUNET_MQ_hd_var_size(incoming_msg, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG, struct GNUNET_TRANSPORT_IncomingMessage, NULL), GNUNET_MQ_hd_fixed_size(queue_create_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL), GNUNET_MQ_hd_fixed_size(queue_create_fail, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL), GNUNET_MQ_hd_var_size(add_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, struct GNUNET_TRANSPORT_AddQueueMessage, NULL), GNUNET_MQ_hd_fixed_size(update_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE, struct GNUNET_TRANSPORT_UpdateQueueMessage, NULL), GNUNET_MQ_hd_fixed_size(del_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN, struct GNUNET_TRANSPORT_DelQueueMessage, NULL), GNUNET_MQ_hd_fixed_size(send_message_ack, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, struct GNUNET_TRANSPORT_SendMessageToAck, NULL), GNUNET_MQ_hd_fixed_size(monitor_start, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START, struct GNUNET_TRANSPORT_MonitorStart, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
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 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 hello_for_incoming_sync_cb(void *cls)
static enum GNUNET_GenericReturnValue resume_communicators(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
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 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 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_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 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 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 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 ...
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.
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.
void(* DVMessageHandler)(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static char * get_address_without_port(const char *address)
Get the IP address without the 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
static void queue(const char *hostname)
Add hostname to the list of requests to be made.
Helper library for handling HELLO URIs.
API to the peerstore service.
uint32_t dim
Definition: gnunet_pq_lib.h:3
API to create, modify and access statistics.
Monitoring / diagnostics API for the transport service.
#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_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
Definition: crypto_hpke.c:407
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.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:201
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.
Definition: crypto_hpke.c:312
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
#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.
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer's key from the file specified in the configuration.
@ 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)
Definition: crypto_hash.c:330
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf_expand(void *result, size_t out_len, const struct GNUNET_ShortHashCode *prk,...)
HKDF-Expand using SHA256.
Definition: crypto_hkdf.c:156
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_sign_address(const char *address, enum GNUNET_NetworkType nt, struct GNUNET_TIME_Absolute mono_time, const struct GNUNET_CRYPTO_EddsaPrivateKey *private_key, void **result, size_t *result_size)
Build address record by signing raw information with private key.
Definition: hello-ng.c:66
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition: hello-uri.c:373
const struct GNUNET_PeerIdentity * 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:909
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new(const struct GNUNET_PeerIdentity *pid)
Allocate builder.
Definition: hello-uri.c:355
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_msg(const struct GNUNET_MessageHeader *msg)
Parse msg into builder.
Definition: hello-uri.c:391
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:835
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-ng.c:190
struct GNUNET_MQ_Envelope * GNUNET_HELLO_builder_to_env(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_TIME_Relative expiration_time)
Generate envelope with GNUnet HELLO message (including peer ID) from a builder.
Definition: hello-uri.c:631
#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)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
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.
Definition: common_endian.c:37
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#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.
Definition: gnunet_mq_lib.h:63
#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.
Definition: gnunet_mq_lib.h:78
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.
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:702
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:459
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:44
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_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_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:567
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:1255
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:1340
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1305
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
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:1208
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2549
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2484
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2455
@ 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).
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:343
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:628
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:436
#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:405
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:367
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:570
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:603
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:504
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:585
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:469
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:484
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:359
#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:618
#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:450
#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:550
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:421
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:617
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
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
#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.
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:88
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition: transport.h:111
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 GNUNET_CRYPTO_AuthKey hmac_key
Key used for HMAC calculations (via GNUNET_CRYPTO_hmac()).
gcry_cipher_hd_t cipher
State of our block cipher.
struct DVKeyState::@65 material
Actual key material.
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.
Message from the transport service to the library informing about disconnects.
Definition: transport.h:120
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_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
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_EccSignaturePurpose 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:774
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.
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.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Private ECC key encoded for transmission.
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
Context for building (or parsing) HELLO URIs.
Definition: hello-uri.c:205
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.
Definition: peerstore_api.c:44
Context for a iterate request.
Context for a monitor.
Single PEERSTORE record.
Context for a store request.
Context for a add hello uri request.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a client that is connected to a service.
Definition: service.c:246
Handle to a service.
Definition: service.c:117
Handle for the service.
A 256-bit hashcode.
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:282
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
Definition: transport.h:286
struct GNUNET_TIME_RelativeNBO expiration
When does the address expire?
Definition: transport.h:296
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition: transport.h:301
uint32_t aid
Address identifier (used during deletion).
Definition: transport.h:291
Add queue to the transport.
Definition: transport.h:396
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition: transport.h:415
uint32_t mtu
Maximum transmission unit, in NBO.
Definition: transport.h:420
uint64_t q_len
Queue length, in NBO.
Definition: transport.h:426
uint32_t qid
Queue identifier (used to identify the queue).
Definition: transport.h:405
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition: transport.h:410
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
Definition: transport.h:400
uint32_t cs
An enum GNUNET_TRANSPORT_ConnectionStatus in NBO.
Definition: transport.h:436
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
Definition: transport.h:267
uint32_t cc
NBO encoding of enum GNUNET_TRANSPORT_CommunicatorCharacteristics
Definition: transport.h:272
Message from transport to communicator passing along a backchannel message from the given peer pid.
Definition: transport.h:650
struct GNUNET_PeerIdentity pid
Origin peer.
Definition: transport.h:665
Message from communicator to transport service asking for transmission of a backchannel message with ...
Definition: transport.h:621
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL.
Definition: transport.h:625
struct GNUNET_PeerIdentity pid
Target peer.
Definition: transport.h:635
Communicator tells transport how queue creation went down.
Definition: transport.h:540
uint32_t request_id
Unique ID for the request.
Definition: transport.h:550
Transport tells communicator that it wants a new queue.
Definition: transport.h:516
uint32_t request_id
Unique ID for the request.
Definition: transport.h:525
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition: transport.h:530
Remove address from the list.
Definition: transport.h:311
uint32_t aid
Address identifier.
Definition: transport.h:320
Remove queue, it is no longer available.
Definition: transport.h:494
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition: transport.h:508
uint32_t qid
Address identifier.
Definition: transport.h:503
Transport informs us about being done with an incoming message.
Definition: transport.h:369
struct GNUNET_PeerIdentity sender
Sender identifier of the original message.
Definition: transport.h:388
uint64_t fc_id
Which message is being ACKed?
Definition: transport.h:383
uint32_t reserved
Reserved (0)
Definition: transport.h:378
Inform transport about an incoming message.
Definition: transport.h:328
struct GNUNET_PeerIdentity neighbour_sender
Direct neighbour sender identifier.
Definition: transport.h:358
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:348
struct GNUNET_PeerIdentity sender
Sender identifier.
Definition: transport.h:353
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
Definition: transport.h:332
uint32_t fc_on
Do we use flow control or not?
Definition: transport.h:337
uint64_t fc_id
64-bit number to identify the matching ACK.
Definition: transport.h:342
uint32_t num_msg_pending
Messages pending (in NBO).
Definition: transport.h:734
struct GNUNET_PeerIdentity peer
Target identifier.
Definition: transport.h:712
struct GNUNET_TIME_AbsoluteNBO valid_until
Definition: transport.h:718
struct GNUNET_TIME_AbsoluteNBO last_validation
Definition: transport.h:717
uint32_t num_bytes_pending
Bytes pending (in NBO).
Definition: transport.h:739
struct GNUNET_TIME_AbsoluteNBO next_validation
Definition: transport.h:719
uint32_t nt
Network type (an enum GNUNET_NetworkType in NBO).
Definition: transport.h:707
struct GNUNET_TIME_RelativeNBO rtt
Current round-trip time estimate.
Definition: transport.h:724
uint32_t cs
Connection status (in NBO).
Definition: transport.h:729
Request to start monitoring.
Definition: transport.h:676
Inform transport that message was sent.
Definition: transport.h:587
uint64_t mid
Message ID of the original message.
Definition: transport.h:601
uint32_t qid
Queue ID for the queue which was used to send the message.
Definition: transport.h:606
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition: transport.h:611
Inform communicator about transport's desire to send a message.
Definition: transport.h:558
uint32_t qid
Which queue should we use?
Definition: transport.h:567
uint64_t mid
Message ID, used for flow control.
Definition: transport.h:572
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
Definition: transport.h:562
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition: transport.h:577
A UUID, a 128 bit "random" value.
Message used to notify the transport API about a message received from the network.
Definition: transport.h:143
struct GNUNET_PeerIdentity peer
Which peer sent the message?
Definition: transport.h:152
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:229
uint32_t priority
An enum GNUNET_MQ_PriorityPreferences in NBO.
Definition: transport.h:238
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND.
Definition: transport.h:233
struct GNUNET_PeerIdentity peer
Which peer should receive the message?
Definition: transport.h:252
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.
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 not 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:205
struct GNUNET_PeerIdentity peer
Which peer can CORE handle more from now?
Definition: transport.h:220
uint32_t increase_window_delta
Number of messages by which to increase the window, greater or equal to one.
Definition: transport.h:215
We got an address of another peer, TRANSPORT service should validate it.
Definition: transport.h:805
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:161
struct GNUNET_PeerIdentity peer
Which peer can send more now?
Definition: transport.h:195
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 * next
Kept in a DLL.
struct GNUNET_MQ_Handle * mq
Message queue to the client.
struct GNUNET_SCHEDULER_Task * free_queue_entry_task
Task to check for timed out QueueEntry.
struct PendingMessage * pending_msg_tail
Tail of list of messages pending for this client.
struct TransportClient::@60::@62 monitor
Information for type CT_MONITOR.
struct Queue * queue_head
Head of DLL of queues offered by this communicator.
struct TransportClient::@60::@61 core
Information for type CT_CORE.
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 TransportClient::@60::@64 application
Information for type CT_APPLICATION.
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 Queue * queue_tail
Tail of DLL of queues offered by this communicator.
union TransportClient::@60 details
struct TransportClient::@60::@63 communicator
Information for type CT_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.
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 re-used for EPHEMERAL_VALIDITY time to avoid re-signing it ...
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_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL.
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.
char * addr
The address to search for.
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_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
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_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.
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