GNUnet 0.21.1
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
3662
3668static void
3669free_neighbour (struct Neighbour *neighbour)
3670{
3671 struct DistanceVectorHop *dvh;
3672 struct VirtualLink *vl;
3673
3674 GNUNET_assert (NULL == neighbour->queue_head);
3677 &neighbour->pid,
3678 neighbour));
3680 "Freeing neighbour\n");
3683 NULL);
3684 while (NULL != (dvh = neighbour->dv_head))
3685 {
3686 struct DistanceVector *dv = dvh->dv;
3687
3689 if (NULL == dv->dv_head)
3690 free_dv_route (dv);
3691 }
3692 if (NULL != neighbour->get)
3693 {
3695 neighbour->get = NULL;
3696 }
3697 if (NULL != neighbour->sc)
3698 {
3700 "store cancel\n");
3701 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3702 neighbour->sc = NULL;
3703 }
3704 if (NULL != (vl = neighbour->vl))
3705 {
3706 GNUNET_assert (neighbour == vl->n);
3707 vl->n = NULL;
3708 if (NULL == vl->dv)
3709 {
3712 }
3713 else
3714 {
3717 }
3718 neighbour->vl = NULL;
3719 }
3720 GNUNET_free (neighbour);
3721}
3722
3723
3730static void
3732 const struct GNUNET_PeerIdentity *pid)
3733{
3734 struct GNUNET_MQ_Envelope *env;
3735 struct ConnectInfoMessage *cim;
3736
3737 GNUNET_assert (CT_CORE == tc->type);
3739 cim->id = *pid;
3740 GNUNET_MQ_send (tc->mq, env);
3741}
3742
3743
3749static void
3751{
3753 "Informing CORE clients about connection to %s\n",
3754 GNUNET_i2s (pid));
3755 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3756 {
3757 if (CT_CORE != tc->type)
3758 continue;
3760 }
3761}
3762
3763
3771static void
3772transmit_on_queue (void *cls);
3773
3774
3778static unsigned int
3780{
3781 for (struct Queue *s = queue_head; NULL != s;
3782 s = s->next_client)
3783 {
3784 if (s->tc->details.communicator.address_prefix !=
3785 queue->tc->details.communicator.address_prefix)
3786 {
3788 "queue address %s qid %u compare with queue: address %s qid %u\n",
3789 queue->address,
3790 queue->qid,
3791 s->address,
3792 s->qid);
3793 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3794 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3795 return GNUNET_YES;
3797 "Lower prio\n");
3798 }
3799 }
3800 return GNUNET_NO;
3801}
3802
3803
3811static void
3813 struct Queue *queue,
3815{
3817
3818 if (queue->validated_until.abs_value_us < now.abs_value_us)
3819 return;
3821 queue->tc->details.communicator.
3822 queue_head))
3823 return;
3824
3825 if (queue->tc->details.communicator.total_queue_length >=
3827 {
3829 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3830 queue->address,
3831 queue->qid);
3833 GST_stats,
3834 "# Transmission throttled due to communicator queue limit",
3835 1,
3836 GNUNET_NO);
3837 queue->idle = GNUNET_NO;
3838 return;
3839 }
3840 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3841 {
3843 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3844 queue->address,
3845 queue->qid);
3847 "# Transmission throttled due to queue queue limit",
3848 1,
3849 GNUNET_NO);
3850 queue->idle = GNUNET_NO;
3851 return;
3852 }
3853 if (0 == queue->q_capacity)
3854 {
3856 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3857 PRIu64 ".\n",
3858 queue->address,
3859 queue->qid,
3860 queue->q_capacity);
3862 "# Transmission throttled due to message queue capacity",
3863 1,
3864 GNUNET_NO);
3865 queue->idle = GNUNET_NO;
3866 return;
3867 }
3868 /* queue might indeed be ready, schedule it */
3869 if (NULL != queue->transmit_task)
3870 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3871 queue->transmit_task =
3873 queue);
3875 "Considering transmission on queue `%s' QID %llu to %s\n",
3876 queue->address,
3877 (unsigned long long) queue->qid,
3878 GNUNET_i2s (&queue->neighbour->pid));
3879}
3880
3881
3888static void
3890{
3891 struct VirtualLink *vl = cls;
3892 struct DistanceVector *dv = vl->dv;
3893 struct Neighbour *n = vl->n;
3894 struct GNUNET_TIME_Absolute dvh_timeout;
3895 struct GNUNET_TIME_Absolute q_timeout;
3896
3898 "Checking if link is down\n");
3899 vl->visibility_task = NULL;
3900 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3901 if (NULL != dv)
3902 {
3903 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3904 pos = pos->next_dv)
3905 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
3906 pos->path_valid_until);
3907 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3908 {
3909 vl->dv->vl = NULL;
3910 vl->dv = NULL;
3911 }
3912 }
3913 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3914 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3915 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3916 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3917 {
3918 vl->n->vl = NULL;
3919 vl->n = NULL;
3920 }
3921 if ((NULL == vl->n) && (NULL == vl->dv))
3922 {
3924 free_virtual_link (vl);
3925 return;
3926 }
3927 vl->visibility_task =
3928 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3930 vl);
3931}
3932
3933
3939static void
3941{
3942 struct Neighbour *neighbour = queue->neighbour;
3943 struct TransportClient *tc = queue->tc;
3944 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
3946 struct QueueEntry *qe;
3947 int maxxed;
3948 struct PendingAcknowledgement *pa;
3949 struct VirtualLink *vl;
3950
3952 "Cleaning up queue %u\n", queue->qid);
3953 if (NULL != queue->mo)
3954 {
3956 queue->mo = NULL;
3957 }
3958 if (NULL != queue->transmit_task)
3959 {
3960 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3961 queue->transmit_task = NULL;
3962 }
3963 while (NULL != (pa = queue->pa_head))
3964 {
3965 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
3966 pa->queue = NULL;
3967 }
3968
3970 neighbour->queue_head,
3971 neighbour->queue_tail,
3972 queue);
3974 tc->details.communicator.queue_head,
3975 tc->details.communicator.queue_tail,
3976 queue);
3978 tc->details.communicator.total_queue_length);
3980 "Cleaning up queue with length %u\n",
3981 queue->queue_length);
3982 while (NULL != (qe = queue->queue_head))
3983 {
3984 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
3985 queue->queue_length--;
3986 tc->details.communicator.total_queue_length--;
3987 if (NULL != qe->pm)
3988 {
3989 GNUNET_assert (qe == qe->pm->qe);
3990 qe->pm->qe = NULL;
3991 }
3992 GNUNET_free (qe);
3993 }
3994 GNUNET_assert (0 == queue->queue_length);
3995 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
3996 tc->details.communicator.total_queue_length))
3997 {
3998 /* Communicator dropped below threshold, resume all _other_ queues */
4000 GST_stats,
4001 "# Transmission throttled due to communicator queue limit",
4002 -1,
4003 GNUNET_NO);
4004 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4005 s = s->next_client)
4007 s,
4009 }
4010 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4012
4013 vl = lookup_virtual_link (&neighbour->pid);
4014 if ((NULL != vl) && (neighbour == vl->n))
4015 {
4017 check_link_down (vl);
4018 }
4019 if (NULL == neighbour->queue_head)
4020 {
4021 free_neighbour (neighbour);
4022 }
4023}
4024
4025
4031static void
4033{
4034 struct TransportClient *tc = ale->tc;
4035
4036 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4037 tc->details.communicator.addr_tail,
4038 ale);
4039 if (NULL != ale->sc)
4040 {
4042 "store cancel\n");
4044 ale->sc = NULL;
4045 }
4046 if (NULL != ale->st)
4047 {
4049 ale->st = NULL;
4050 }
4051 if (NULL != ale->signed_address)
4053 GNUNET_free (ale);
4054}
4055
4056
4065static int
4067 const struct GNUNET_PeerIdentity *pid,
4068 void *value)
4069{
4070 struct TransportClient *tc = cls;
4071 struct PeerRequest *pr = value;
4072
4073 if (NULL != pr->nc)
4075 pr->nc = NULL;
4077 GNUNET_YES ==
4078 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4079 pid,
4080 pr));
4081 GNUNET_free (pr);
4082
4083 return GNUNET_OK;
4084}
4085
4086
4087static void
4088do_shutdown (void *cls);
4089
4098static void
4100 struct GNUNET_SERVICE_Client *client,
4101 void *app_ctx)
4102{
4103 struct TransportClient *tc = app_ctx;
4104
4105 (void) cls;
4106 (void) client;
4108 switch (tc->type)
4109 {
4110 case CT_NONE:
4112 "Unknown Client %p disconnected, cleaning up.\n",
4113 tc);
4114 break;
4115
4116 case CT_CORE: {
4118 "CORE Client %p disconnected, cleaning up.\n",
4119 tc);
4120
4121 struct PendingMessage *pm;
4122
4123 while (NULL != (pm = tc->details.core.pending_msg_head))
4124 {
4126 tc->details.core.pending_msg_head,
4127 tc->details.core.pending_msg_tail,
4128 pm);
4129 pm->client = NULL;
4130 }
4131 }
4132 break;
4133
4134 case CT_MONITOR:
4136 "MONITOR Client %p disconnected, cleaning up.\n",
4137 tc);
4138
4139 break;
4140
4141 case CT_COMMUNICATOR: {
4143 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4144 tc);
4145
4146 struct Queue *q;
4147 struct AddressListEntry *ale;
4148
4149 if (NULL != tc->details.communicator.free_queue_entry_task)
4151 tc->details.communicator.free_queue_entry_task);
4152 while (NULL != (q = tc->details.communicator.queue_head))
4153 free_queue (q);
4154 while (NULL != (ale = tc->details.communicator.addr_head))
4156 GNUNET_free (tc->details.communicator.address_prefix);
4157 }
4158 break;
4159
4160 case CT_APPLICATION:
4162 "APPLICATION Client %p disconnected, cleaning up.\n",
4163 tc);
4164
4165 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4167 tc);
4168 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4169 break;
4170 }
4171 GNUNET_free (tc);
4172 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4173 {
4175 "Our last client disconnected\n");
4176 do_shutdown (cls);
4177 }
4178}
4179
4180
4190static int
4192 const struct GNUNET_PeerIdentity *pid,
4193 void *value)
4194{
4195 struct TransportClient *tc = cls;
4196 struct VirtualLink *vl = value;
4197
4198 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4199 return GNUNET_OK;
4200
4202 "Telling new CORE client about existing connection to %s\n",
4203 GNUNET_i2s (pid));
4205 return GNUNET_OK;
4206}
4207
4208
4214static void
4216 unsigned
4217 int free_cmc);
4218
4219static enum GNUNET_GenericReturnValue
4221 const struct GNUNET_PeerIdentity *pid,
4222 void *value)
4223{
4224 struct VirtualLink *vl = value;
4225 struct CommunicatorMessageContext *cmc;
4226
4227 /* resume communicators */
4228 while (NULL != (cmc = vl->cmc_tail))
4229 {
4231 if (GNUNET_NO == cmc->continue_send)
4233 }
4234 return GNUNET_OK;
4235}
4236
4237
4246static void
4247handle_client_start (void *cls, const struct StartMessage *start)
4248{
4249 struct TransportClient *tc = cls;
4250 uint32_t options;
4251
4252 options = ntohl (start->options);
4253 if ((0 != (1 & options)) &&
4254 (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4255 {
4256 /* client thinks this is a different peer, reject */
4257 GNUNET_break (0);
4259 return;
4260 }
4261 if (CT_NONE != tc->type)
4262 {
4263 GNUNET_break (0);
4265 return;
4266 }
4267 tc->type = CT_CORE;
4269 "New CORE client with PID %s registered\n",
4270 GNUNET_i2s (&start->self));
4273 tc);
4276 NULL);
4278}
4279
4280
4287static int
4288check_client_send (void *cls, const struct OutboundMessage *obm)
4289{
4290 struct TransportClient *tc = cls;
4291 uint16_t size;
4292 const struct GNUNET_MessageHeader *obmm;
4293
4294 if (CT_CORE != tc->type)
4295 {
4296 GNUNET_break (0);
4297 return GNUNET_SYSERR;
4298 }
4299 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4300 if (size < sizeof(struct GNUNET_MessageHeader))
4301 {
4302 GNUNET_break (0);
4303 return GNUNET_SYSERR;
4304 }
4305 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4306 if (size != ntohs (obmm->size))
4307 {
4308 GNUNET_break (0);
4309 return GNUNET_SYSERR;
4310 }
4311 return GNUNET_OK;
4312}
4313
4314
4322static void
4324{
4325 struct TransportClient *tc = pm->client;
4326 struct VirtualLink *vl = pm->vl;
4327
4329 "client send response\n");
4330 if (NULL != tc)
4331 {
4332 struct GNUNET_MQ_Envelope *env;
4333 struct SendOkMessage *so_msg;
4334
4336 so_msg->peer = vl->target;
4338 "Confirming transmission of <%" PRIu64 "> to %s\n",
4339 pm->logging_uuid,
4340 GNUNET_i2s (&vl->target));
4341 GNUNET_MQ_send (tc->mq, env);
4342 }
4344}
4345
4346
4356static unsigned int
4359 struct DistanceVectorHop **hops_array,
4360 unsigned int hops_array_length)
4361{
4362 uint64_t choices[hops_array_length];
4363 uint64_t num_dv;
4364 unsigned int dv_count;
4365
4366 /* Pick random vectors, but weighted by distance, giving more weight
4367 to shorter vectors */
4368 num_dv = 0;
4369 dv_count = 0;
4370 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4371 pos = pos->next_dv)
4372 {
4373 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4374 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4375 .rel_value_us == 0))
4376 continue; /* pos unconfirmed and confirmed required */
4377 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4378 dv_count++;
4379 }
4380 if (0 == dv_count)
4381 return 0;
4382 if (dv_count <= hops_array_length)
4383 {
4384 dv_count = 0;
4385 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4386 pos = pos->next_dv)
4387 hops_array[dv_count++] = pos;
4388 return dv_count;
4389 }
4390 for (unsigned int i = 0; i < hops_array_length; i++)
4391 {
4392 int ok = GNUNET_NO;
4393 while (GNUNET_NO == ok)
4394 {
4395 choices[i] =
4397 ok = GNUNET_YES;
4398 for (unsigned int j = 0; j < i; j++)
4399 if (choices[i] == choices[j])
4400 {
4401 ok = GNUNET_NO;
4402 break;
4403 }
4404 }
4405 }
4406 dv_count = 0;
4407 num_dv = 0;
4408 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4409 pos = pos->next_dv)
4410 {
4411 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4412
4413 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4414 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4415 .rel_value_us == 0))
4416 continue; /* pos unconfirmed and confirmed required */
4417 for (unsigned int i = 0; i < hops_array_length; i++)
4418 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4419 hops_array[dv_count++] = pos;
4420 num_dv += delta;
4421 }
4422 return dv_count;
4423}
4424
4425
4432static int
4434 void *cls,
4436{
4437 struct TransportClient *tc = cls;
4438 uint16_t size;
4439
4440 if (CT_NONE != tc->type)
4441 {
4442 GNUNET_break (0);
4443 return GNUNET_SYSERR;
4444 }
4445 tc->type = CT_COMMUNICATOR;
4446 size = ntohs (cam->header.size) - sizeof(*cam);
4447 if (0 == size)
4448 return GNUNET_OK; /* receive-only communicator */
4450 return GNUNET_OK;
4451}
4452
4453
4459static void
4461 unsigned
4462 int free_cmc)
4463{
4464 if (0 != ntohl (cmc->im.fc_on))
4465 {
4466 /* send ACK when done to communicator for flow control! */
4467 struct GNUNET_MQ_Envelope *env;
4469
4471 "Acknowledge message with flow control id %" PRIu64 "\n",
4472 cmc->im.fc_id);
4474 ack->reserved = htonl (0);
4475 ack->fc_id = cmc->im.fc_id;
4476 ack->sender = cmc->im.neighbour_sender;
4477 GNUNET_MQ_send (cmc->tc->mq, env);
4478 }
4479
4481
4482 if (GNUNET_YES == free_cmc)
4483 {
4484 GNUNET_free (cmc);
4485 }
4486}
4487
4488
4489static void
4491{
4493}
4494
4495
4505static void
4506handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4507{
4508 struct TransportClient *tc = cls;
4509 struct VirtualLink *vl;
4510 uint32_t delta;
4511 struct CommunicatorMessageContext *cmc;
4512
4513 if (CT_CORE != tc->type)
4514 {
4515 GNUNET_break (0);
4517 return;
4518 }
4519 vl = lookup_virtual_link (&rom->peer);
4520 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4521 {
4523 "# RECV_OK dropped: virtual link unknown",
4524 1,
4525 GNUNET_NO);
4527 return;
4528 }
4529 delta = ntohl (rom->increase_window_delta);
4530 vl->core_recv_window += delta;
4532 "CORE ack receiving message, increased CORE recv window to %d\n",
4533 vl->core_recv_window);
4535 if (vl->core_recv_window <= 0)
4536 return;
4537 /* resume communicators */
4538 while (NULL != (cmc = vl->cmc_tail))
4539 {
4541 if (GNUNET_NO == cmc->continue_send)
4543 }
4544}
4545
4546
4553static void
4555 void *cls,
4557{
4558 struct TransportClient *tc = cls;
4559 uint16_t size;
4560
4561 size = ntohs (cam->header.size) - sizeof(*cam);
4562 if (0 == size)
4563 {
4565 "Receive-only communicator connected\n");
4566 return; /* receive-only communicator */
4567 }
4568 tc->details.communicator.address_prefix =
4569 GNUNET_strdup ((const char *) &cam[1]);
4570 tc->details.communicator.cc =
4573 "Communicator with prefix `%s' connected\n",
4574 tc->details.communicator.address_prefix);
4576}
4577
4578
4586static int
4588 void *cls,
4590{
4591 const struct GNUNET_MessageHeader *inbox;
4592 const char *is;
4593 uint16_t msize;
4594 uint16_t isize;
4595
4596 (void) cls;
4597 msize = ntohs (cb->header.size) - sizeof(*cb);
4598 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4599 isize = ntohs (inbox->size);
4600 if (isize >= msize)
4601 {
4602 GNUNET_break (0);
4603 return GNUNET_SYSERR;
4604 }
4605 is = (const char *) inbox;
4606 is += isize;
4607 msize -= isize;
4608 GNUNET_assert (0 < msize);
4609 if ('\0' != is[msize - 1])
4610 {
4611 GNUNET_break (0);
4612 return GNUNET_SYSERR;
4613 }
4614 return GNUNET_OK;
4615}
4616
4617
4623static void
4625{
4626 struct EphemeralConfirmationPS ec;
4627
4629 dv->ephemeral_validity =
4632 ec.target = dv->target;
4635 ec.purpose.size = htonl (sizeof(ec));
4637 &ec,
4638 &dv->sender_sig);
4639}
4640
4641
4642static void
4644 struct TransportClient *tc);
4645
4646
4647static void
4649{
4650 struct TransportClient *tc = cls;
4652
4654 "freeing timedout queue entries\n");
4655
4656 tc->details.communicator.free_queue_entry_task = NULL;
4657 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4658 queue = queue->next_client)
4659 {
4660 struct QueueEntry *qep = queue->queue_head;
4661
4663 "checking QID %u for timedout queue entries\n",
4664 queue->qid);
4665 while (NULL != qep)
4666 {
4667 struct QueueEntry *pos = qep;
4668
4669 qep = qep->next;
4671 pos->creation_timestamp, now);
4672
4674 "diff to now %s \n",
4677 {
4679 "Freeing timed out QueueEntry with MID %" PRIu64
4680 " and QID %u\n",
4681 pos->mid,
4682 queue->qid);
4683 free_queue_entry (pos, tc);
4684 }
4685 }
4686 }
4687}
4688
4689
4699static void
4701 struct PendingMessage *pm,
4702 const void *payload,
4703 size_t payload_size)
4704{
4705 struct Neighbour *n = queue->neighbour;
4707 struct GNUNET_MQ_Envelope *env;
4708 struct PendingAcknowledgement *pa;
4709
4710 GNUNET_log (
4712 "Queueing %u bytes of payload for transmission <%" PRIu64
4713 "> on queue %llu to %s\n",
4714 (unsigned int) payload_size,
4715 (NULL == pm) ? 0 : pm->logging_uuid,
4716 (unsigned long long) queue->qid,
4717 GNUNET_i2s (&queue->neighbour->pid));
4718 env = GNUNET_MQ_msg_extra (smt,
4719 payload_size,
4721 smt->qid = htonl (queue->qid);
4722 smt->mid = GNUNET_htonll (queue->mid_gen);
4723 smt->receiver = n->pid;
4724 memcpy (&smt[1], payload, payload_size);
4725 {
4726 /* Pass the env to the communicator of queue for transmission. */
4727 struct QueueEntry *qe;
4728
4729 qe = GNUNET_new (struct QueueEntry);
4730 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4731 qe->mid = queue->mid_gen;
4733 "Create QueueEntry with MID %" PRIu64
4734 " and QID %u and prefix %s\n",
4735 qe->mid,
4736 queue->qid,
4737 queue->tc->details.communicator.address_prefix);
4738 queue->mid_gen++;
4739 qe->queue = queue;
4740 if (NULL != pm)
4741 {
4742 qe->pm = pm;
4743 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4744 // GNUNET_assert (NULL == pm->qe);
4745 if (NULL != pm->qe)
4746 {
4748 "Retransmitting message <%" PRIu64
4749 "> remove pm from qe with MID: %llu \n",
4750 pm->logging_uuid,
4751 (unsigned long long) pm->qe->mid);
4752 pm->qe->pm = NULL;
4753 }
4754 pm->qe = qe;
4755 }
4756 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4757 if (0 == queue->q_capacity)
4758 {
4759 // Messages without FC or fragments can get here.
4760 if (NULL != pm)
4761 {
4763 "Message %" PRIu64
4764 " (pm type %u) was not send because queue has no capacity.\n",
4765 pm->logging_uuid,
4766 pm->pmt);
4767 pm->qe = NULL;
4768 }
4769 GNUNET_free (env);
4770 GNUNET_free (qe);
4771 return;
4772 }
4773 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4774 queue->queue_length++;
4775 queue->tc->details.communicator.total_queue_length++;
4776 if (GNUNET_NO == queue->unlimited_length)
4777 queue->q_capacity--;
4779 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4780 queue->address,
4781 queue->qid,
4782 queue->q_capacity);
4784 queue->tc->details.communicator.total_queue_length)
4785 queue->idle = GNUNET_NO;
4786 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4787 queue->idle = GNUNET_NO;
4788 if (0 == queue->q_capacity)
4789 queue->idle = GNUNET_NO;
4790
4791 if (GNUNET_NO == queue->idle)
4792 {
4793 struct TransportClient *tc = queue->tc;
4794
4795 if (NULL == tc->details.communicator.free_queue_entry_task)
4796 tc->details.communicator.free_queue_entry_task =
4798 &
4800 tc);
4801 }
4802 if (NULL != pm && NULL != (pa = pm->pa_head))
4803 {
4804 while (pm != pa->pm)
4805 pa = pa->next_pa;
4806 pa->num_send++;
4807 }
4808 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4810 "Sending message MID %" PRIu64
4811 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4812 PRIu64 "\n",
4813 GNUNET_ntohll (smt->mid),
4814 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4815 ntohs (smt->header.size),
4816 (unsigned long) payload_size,
4817 queue->tc->mq,
4818 queue->address,
4819 queue->qid,
4820 (NULL == pm) ? 0 : pm->logging_uuid);
4821 GNUNET_MQ_send (queue->tc->mq, env);
4822 }
4823}
4824
4825
4836static struct GNUNET_TIME_Relative
4838 const struct GNUNET_MessageHeader *hdr,
4840{
4841 struct GNUNET_TIME_Absolute now;
4842 unsigned int candidates;
4843 unsigned int sel1;
4844 unsigned int sel2;
4845 struct GNUNET_TIME_Relative rtt;
4846
4847 /* Pick one or two 'random' queues from n (under constraints of options) */
4848 now = GNUNET_TIME_absolute_get ();
4849 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4850 weight in the future; weight could be assigned by observed
4851 bandwidth (note: not sure if we should do this for this type
4852 of control traffic though). */
4853 candidates = 0;
4854 for (struct Queue *pos = n->queue_head; NULL != pos;
4855 pos = pos->next_neighbour)
4856 {
4857 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4858 (pos->validated_until.abs_value_us > now.abs_value_us))
4859 candidates++;
4860 }
4861 if (0 == candidates)
4862 {
4863 /* This can happen rarely if the last confirmed queue timed
4864 out just as we were beginning to process this message. */
4866 "Could not route message of type %u to %s: no valid queue\n",
4867 ntohs (hdr->type),
4868 GNUNET_i2s (&n->pid));
4870 "# route selection failed (all no valid queue)",
4871 1,
4872 GNUNET_NO);
4874 }
4875
4878 if (0 == (options & RMO_REDUNDANT))
4879 sel2 = candidates; /* picks none! */
4880 else
4882 candidates = 0;
4883 for (struct Queue *pos = n->queue_head; NULL != pos;
4884 pos = pos->next_neighbour)
4885 {
4886 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4887 (pos->validated_until.abs_value_us > now.abs_value_us))
4888 {
4889 if ((sel1 == candidates) || (sel2 == candidates))
4890 {
4892 "Routing message of type %u to %s using %s (#%u)\n",
4893 ntohs (hdr->type),
4894 GNUNET_i2s (&n->pid),
4895 pos->address,
4896 (sel1 == candidates) ? 1 : 2);
4897 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4898 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4899 }
4900 candidates++;
4901 }
4902 }
4903 return rtt;
4904}
4905
4906
4911{
4915 gcry_cipher_hd_t cipher;
4916
4920 struct
4921 {
4926
4930 char aes_key[256 / 8];
4931
4935 char aes_ctr[128 / 8];
4937};
4938
4939
4948static void
4950 const struct GNUNET_ShortHashCode *iv,
4951 struct DVKeyState *key)
4952{
4953 /* must match what we defive from decapsulated key */
4955 GNUNET_CRYPTO_kdf (&key->material,
4956 sizeof(key->material),
4957 "transport-backchannel-key",
4958 strlen ("transport-backchannel-key"),
4959 km,
4960 sizeof(*km),
4961 iv,
4962 sizeof(*iv),
4963 NULL));
4965 "Deriving backchannel key based on KM %s and IV %s\n",
4966 GNUNET_h2s (km),
4967 GNUNET_sh2s (iv));
4968 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
4969 GCRY_CIPHER_AES256 /* low level: go for speed */,
4970 GCRY_CIPHER_MODE_CTR,
4971 0 /* flags */));
4972 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
4973 &key->material.aes_key,
4974 sizeof(key->material.aes_key)));
4975 gcry_cipher_setctr (key->cipher,
4976 &key->material.aes_ctr,
4977 sizeof(key->material.aes_ctr));
4978}
4979
4980
4990static void
4991dv_hmac (const struct DVKeyState *key,
4992 struct GNUNET_HashCode *hmac,
4993 const void *data,
4994 size_t data_size)
4995{
4996 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
4997}
4998
4999
5009static void
5010dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5011{
5012 GNUNET_assert (0 ==
5013 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5014}
5015
5016
5027static enum GNUNET_GenericReturnValue
5029 void *out,
5030 const void *ciph,
5031 size_t out_size)
5032{
5033 return (0 ==
5034 gcry_cipher_decrypt (key->cipher,
5035 out, out_size,
5036 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5037}
5038
5039
5045static void
5047{
5048 gcry_cipher_close (key->cipher);
5049 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5050}
5051
5052
5063typedef void (*DVMessageHandler) (void *cls,
5064 struct Neighbour *next_hop,
5065 const struct GNUNET_MessageHeader *hdr,
5067
5082static struct GNUNET_TIME_Relative
5084 unsigned int num_dvhs,
5085 struct DistanceVectorHop **dvhs,
5086 const struct GNUNET_MessageHeader *hdr,
5087 DVMessageHandler use,
5088 void *use_cls,
5090 enum GNUNET_GenericReturnValue without_fc)
5091{
5092 struct TransportDVBoxMessage box_hdr;
5093 struct TransportDVBoxPayloadP payload_hdr;
5094 uint16_t enc_body_size = ntohs (hdr->size);
5095 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5096 struct DVKeyState *key;
5097 struct GNUNET_TIME_Relative rtt;
5098 struct GNUNET_HashCode km;
5099
5100 key = GNUNET_new (struct DVKeyState);
5101 /* Encrypt payload */
5103 box_hdr.total_hops = htons (0);
5104 box_hdr.without_fc = htons (without_fc);
5105 // update_ephemeral (dv);
5106 if (0 ==
5107 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5108 {
5109 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5110 &dv->ephemeral_key,
5111 &km);
5112 dv->km = GNUNET_new (struct GNUNET_HashCode);
5113 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_HashCode));
5114 sign_ephemeral (dv);
5115 }
5116 box_hdr.ephemeral_key = dv->ephemeral_key;
5117 payload_hdr.sender_sig = dv->sender_sig;
5118
5120 &box_hdr.iv,
5121 sizeof(box_hdr.iv));
5122 // We are creating this key, so this must work.
5123 // FIXME: Possibly also add return values here. We are processing
5124 // Input from other peers...
5125 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5126 payload_hdr.sender = GST_my_identity;
5127 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5128 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5129 dv_encrypt (key,
5130 hdr,
5131 &enc[sizeof(struct TransportDVBoxPayloadP)],
5132 enc_body_size);
5133 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5134 dv_key_clean (key);
5136 /* For each selected path, take the pre-computed header and body
5137 and add the path in the middle of the message; then send it. */
5138 for (unsigned int i = 0; i < num_dvhs; i++)
5139 {
5140 struct DistanceVectorHop *dvh = dvhs[i];
5141 unsigned int num_hops = dvh->distance + 1;
5142 char buf[sizeof(struct TransportDVBoxMessage)
5143 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5144 + sizeof(struct TransportDVBoxPayloadP)
5145 + enc_body_size] GNUNET_ALIGN;
5146 struct GNUNET_PeerIdentity *dhops;
5147
5148 box_hdr.header.size = htons (sizeof(buf));
5149 box_hdr.orig_size = htons (sizeof(buf));
5150 box_hdr.num_hops = htons (num_hops);
5151 memcpy (buf, &box_hdr, sizeof(box_hdr));
5152 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5153 memcpy (dhops,
5154 dvh->path,
5155 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5156 dhops[dvh->distance] = dv->target;
5157 if (GNUNET_EXTRA_LOGGING > 0)
5158 {
5159 char *path;
5160
5162 for (unsigned int j = 0; j < num_hops; j++)
5163 {
5164 char *tmp;
5165
5166 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5167 GNUNET_free (path);
5168 path = tmp;
5169 }
5171 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5172 ntohs (hdr->type),
5173 GNUNET_i2s (&dv->target),
5174 i + 1,
5175 num_dvhs,
5176 path);
5177 GNUNET_free (path);
5178 }
5179 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5180 memcpy (&dhops[num_hops], enc, sizeof(enc));
5181 use (use_cls,
5182 dvh->next_hop,
5183 (const struct GNUNET_MessageHeader *) buf,
5184 options);
5185 GNUNET_free (key);
5186 }
5187 return rtt;
5188}
5189
5190
5200static void
5202 struct Neighbour *next_hop,
5203 const struct GNUNET_MessageHeader *hdr,
5205{
5206 (void) cls;
5207 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5208}
5209
5210
5222static struct GNUNET_TIME_Relative
5224// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5225 const struct GNUNET_MessageHeader *hdr,
5227{
5228 // struct VirtualLink *vl;
5229 struct Neighbour *n;
5230 struct DistanceVector *dv;
5231 struct GNUNET_TIME_Relative rtt1;
5232 struct GNUNET_TIME_Relative rtt2;
5233 const struct GNUNET_PeerIdentity *target = &vl->target;
5234
5236 "Trying to route message of type %u to %s without fc\n",
5237 ntohs (hdr->type),
5238 GNUNET_i2s (target));
5239
5240 // TODO Do this elsewhere. vl should be given as parameter to method.
5241 // vl = lookup_virtual_link (target);
5242 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5243 if (NULL == vl)
5245 n = vl->n;
5246 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5247 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5248 {
5249 /* if confirmed is required, and we do not have anything
5250 confirmed, drop respective options */
5251 if (NULL == n)
5252 n = lookup_neighbour (target);
5253 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5255 }
5256 if ((NULL == n) && (NULL == dv))
5257 {
5259 "Cannot route message of type %u to %s: no route\n",
5260 ntohs (hdr->type),
5261 GNUNET_i2s (target));
5263 "# Messages dropped in routing: no acceptable method",
5264 1,
5265 GNUNET_NO);
5267 }
5269 "Routing message of type %u to %s with options %X\n",
5270 ntohs (hdr->type),
5271 GNUNET_i2s (target),
5272 (unsigned int) options);
5273 /* If both dv and n are possible and we must choose:
5274 flip a coin for the choice between the two; for now 50/50 */
5275 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5276 {
5278 n = NULL;
5279 else
5280 dv = NULL;
5281 }
5282 if ((NULL != n) && (NULL != dv))
5283 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5284 enough for redundancy, so clear the flag. */
5287 if (NULL != n)
5288 {
5290 "Try to route message of type %u to %s without fc via neighbour\n",
5291 ntohs (hdr->type),
5292 GNUNET_i2s (target));
5293 rtt1 = route_via_neighbour (n, hdr, options);
5294 }
5295 if (NULL != dv)
5296 {
5297 struct DistanceVectorHop *hops[2];
5298 unsigned int res;
5299
5301 options,
5302 hops,
5303 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5304 if (0 == res)
5305 {
5307 "Failed to route message, could not determine DV path\n");
5308 return rtt1;
5309 }
5311 "encapsulate_for_dv 1\n");
5312 rtt2 = encapsulate_for_dv (dv,
5313 res,
5314 hops,
5315 hdr,
5317 NULL,
5319 GNUNET_YES);
5320 }
5321 return GNUNET_TIME_relative_min (rtt1, rtt2);
5322}
5323
5324
5325static void
5326consider_sending_fc (void *cls);
5327
5334static void
5336{
5337 struct VirtualLink *vl = cls;
5338 vl->fc_retransmit_task = NULL;
5339 consider_sending_fc (cls);
5340}
5341
5342
5343static char *
5344get_address_without_port (const char *address);
5345
5346
5347static enum GNUNET_GenericReturnValue
5349 const struct GNUNET_PeerIdentity *pid,
5350 void *value)
5351{
5352 char *tgnas = cls;
5353 struct TransportGlobalNattedAddress *tgna = value;
5354 char *addr = (char *) &tgna[1];
5355 size_t address_len = strlen (addr);
5356 unsigned int off = 0;
5357
5359 "sending address %s length %u\n",
5360 addr,
5361 address_len);
5362 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress) + address_len);
5363 tgna->address_length = htonl (address_len);
5364 GNUNET_memcpy (&tgna[1], addr, address_len);
5365 GNUNET_memcpy (&tgnas[off], tgna, sizeof (struct TransportGlobalNattedAddress) + address_len);
5366 GNUNET_free (tgna);
5367 off += sizeof(struct TransportGlobalNattedAddress) + address_len;
5368}
5369
5370
5377static void
5379{
5380 struct VirtualLink *vl = cls;
5381 struct GNUNET_TIME_Absolute monotime;
5382 struct TransportFlowControlMessage *fc;
5384 struct GNUNET_TIME_Relative rtt;
5385 struct Neighbour *n = vl->n;
5386
5387 if (0 < n->number_of_addresses)
5388 {
5390 size_t addresses_size;
5391
5392 addresses_size = n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n->size_of_global_addresses;
5393 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage) + addresses_size);
5394 fc->header.size = htons (sizeof(struct TransportFlowControlMessage) + addresses_size);
5395 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5396 fc->number_of_addresses = htonl (n->number_of_addresses);
5397 GNUNET_CONTAINER_multipeermap_iterate (n->natted_addresses,
5399 tgnas);
5400 GNUNET_memcpy (&fc[1], tgnas, addresses_size);
5401 GNUNET_free (tgnas);
5402 }
5403 else
5404 {
5405 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5406 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5407 }
5408
5410 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5411 it always! */
5412 /* For example, we should probably ONLY do this if a bit more than
5413 an RTT has passed, or if the window changed "significantly" since
5414 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5415 need an estimate for the bandwidth-delay-product for the entire
5416 VL, as that determines "significantly". We have the delay, but
5417 the bandwidth statistics need to be added for the VL!*/(void) duration;
5418
5420 "Sending FC seq %u to %s with new window %llu\n",
5421 (unsigned int) vl->fc_seq_gen,
5422 GNUNET_i2s (&vl->target),
5423 (unsigned long long) vl->incoming_fc_window_size);
5425 vl->last_fc_transmission = monotime;
5427 fc->seq = htonl (vl->fc_seq_gen++);
5433 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5435 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5436 {
5439 "FC retransmission to %s failed, will retry in %s\n",
5440 GNUNET_i2s (&vl->target),
5443 }
5444 else
5445 {
5446 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5447 vl->last_fc_rtt = rtt;
5448 }
5449 if (NULL != vl->fc_retransmit_task)
5452 {
5454 vl->fc_retransmit_count = 0;
5455 }
5456 vl->fc_retransmit_task =
5458 vl->fc_retransmit_count++;
5459 GNUNET_free (fc);
5460}
5461
5462
5479static void
5481{
5482 struct Neighbour *n = vl->n;
5483 struct DistanceVector *dv = vl->dv;
5484 struct GNUNET_TIME_Absolute now;
5485 struct VirtualLink *vl_next_hop;
5486 int elig;
5487
5489 "check_vl_transmission to target %s\n",
5490 GNUNET_i2s (&vl->target));
5491 /* Check that we have an eligible pending message!
5492 (cheaper than having #transmit_on_queue() find out!) */
5493 elig = GNUNET_NO;
5494 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5495 pm = pm->next_vl)
5496 {
5498 "check_vl_transmission loop\n");
5499 if (NULL != pm->qe)
5500 continue; /* not eligible, is in a queue! */
5501 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5503 {
5505 "Stalled message %" PRIu64
5506 " transmission on VL %s due to flow control: %llu < %llu\n",
5507 pm->logging_uuid,
5508 GNUNET_i2s (&vl->target),
5509 (unsigned long long) vl->outbound_fc_window_size,
5510 (unsigned long long) (pm->bytes_msg
5513 return; /* We have a message, but flow control says "nope" */
5514 }
5516 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5517 GNUNET_i2s (&vl->target));
5518 /* Notify queues at direct neighbours that we are interested */
5519 now = GNUNET_TIME_absolute_get ();
5520 if (NULL != n)
5521 {
5522 for (struct Queue *queue = n->queue_head; NULL != queue;
5523 queue = queue->next_neighbour)
5524 {
5525 if ((GNUNET_YES == queue->idle) &&
5526 (queue->validated_until.abs_value_us > now.abs_value_us))
5527 {
5529 "Direct neighbour %s not stalled\n",
5530 GNUNET_i2s (&n->pid));
5532 queue,
5534 elig = GNUNET_YES;
5535 }
5536 else
5538 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5539 queue->qid,
5540 queue->idle);
5541 }
5542 }
5543 /* Notify queues via DV that we are interested */
5544 if (NULL != dv)
5545 {
5546 /* Do DV with lower scheduler priority, which effectively means that
5547 IF a neighbour exists and is available, we prefer it. */
5548 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5549 pos = pos->next_dv)
5550 {
5551 struct Neighbour *nh = pos->next_hop;
5552
5553
5554 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5555 continue; /* skip this one: path not validated */
5556 else
5557 {
5558 vl_next_hop = lookup_virtual_link (&nh->pid);
5559 GNUNET_assert (NULL != vl_next_hop);
5560 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5561 vl_next_hop->outbound_fc_window_size)
5562 {
5564 "Stalled message %" PRIu64
5565 " transmission on next hop %s due to flow control: %llu < %llu\n",
5566 pm->logging_uuid,
5567 GNUNET_i2s (&vl_next_hop->target),
5568 (unsigned long
5569 long) vl_next_hop->outbound_fc_window_size,
5570 (unsigned long long) (pm->bytes_msg
5571 + vl_next_hop->
5572 outbound_fc_window_size_used));
5573 consider_sending_fc (vl_next_hop);
5574 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5575 }
5576 for (struct Queue *queue = nh->queue_head; NULL != queue;
5577 queue = queue->next_neighbour)
5578 if ((GNUNET_YES == queue->idle) &&
5579 (queue->validated_until.abs_value_us > now.abs_value_us))
5580 {
5582 "Next hop neighbour %s not stalled\n",
5583 GNUNET_i2s (&nh->pid));
5585 queue,
5587 elig = GNUNET_YES;
5588 }
5589 else
5591 "DV Queue QID: %u (%u) busy or invalid\n",
5592 queue->qid,
5593 queue->idle);
5594 }
5595 }
5596 }
5597 if (GNUNET_YES == elig)
5599 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5600 pm->logging_uuid,
5601 pm->bytes_msg,
5602 GNUNET_i2s (&vl->target),
5603 (unsigned long long) vl->outbound_fc_window_size,
5604 (unsigned long long) (pm->bytes_msg
5606 break;
5607 }
5608}
5609
5610
5617static void
5618handle_client_send (void *cls, const struct OutboundMessage *obm)
5619{
5620 struct TransportClient *tc = cls;
5621 struct PendingMessage *pm;
5622 const struct GNUNET_MessageHeader *obmm;
5623 uint32_t bytes_msg;
5624 struct VirtualLink *vl;
5626
5627 GNUNET_assert (CT_CORE == tc->type);
5628 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5629 bytes_msg = ntohs (obmm->size);
5630 pp = (enum GNUNET_MQ_PriorityPreferences) ntohl (obm->priority);
5631 vl = lookup_virtual_link (&obm->peer);
5632 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5633 {
5635 "Don't have %s as a neighbour (anymore).\n",
5636 GNUNET_i2s (&obm->peer));
5637 /* Failure: don't have this peer as a neighbour (anymore).
5638 Might have gone down asynchronously, so this is NOT
5639 a protocol violation by CORE. Still count the event,
5640 as this should be rare. */
5643 "# messages dropped (neighbour unknown)",
5644 1,
5645 GNUNET_NO);
5646 return;
5647 }
5648
5649 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5651 "1 created pm %p storing vl %p\n",
5652 pm,
5653 vl);
5654 pm->logging_uuid = logging_uuid_gen++;
5655 pm->prefs = pp;
5656 pm->client = tc;
5657 pm->vl = vl;
5658 pm->bytes_msg = bytes_msg;
5659 memcpy (&pm[1], obmm, bytes_msg);
5661 "Sending message of type %u with %u bytes as <%" PRIu64
5662 "> to %s\n",
5663 ntohs (obmm->type),
5664 bytes_msg,
5665 pm->logging_uuid,
5666 GNUNET_i2s (&obm->peer));
5668 tc->details.core.pending_msg_head,
5669 tc->details.core.pending_msg_tail,
5670 pm);
5672 vl->pending_msg_head,
5673 vl->pending_msg_tail,
5674 pm);
5677}
5678
5679
5689static void
5691 void *cls,
5693{
5694 struct Neighbour *n;
5695 struct VirtualLink *vl;
5696 struct TransportClient *tc = cls;
5697 const struct GNUNET_MessageHeader *inbox =
5698 (const struct GNUNET_MessageHeader *) &cb[1];
5699 uint16_t isize = ntohs (inbox->size);
5700 const char *is = ((const char *) &cb[1]) + isize;
5701 size_t slen = strlen (is) + 1;
5702 char
5703 mbuf[slen + isize
5704 + sizeof(struct
5708
5709 /* 0-termination of 'is' was checked already in
5710 #check_communicator_backchannel() */
5712 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5713 GNUNET_i2s (&cb->pid),
5714 is,
5715 ntohs (inbox->type),
5716 ntohs (inbox->size));
5717 /* encapsulate and encrypt message */
5718 be->header.type =
5720 be->header.size = htons (sizeof(mbuf));
5721 memcpy (&be[1], inbox, isize);
5722 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5723 + isize],
5724 is,
5725 strlen (is) + 1);
5726 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5727 vl = lookup_virtual_link (&cb->pid);
5728 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5729 {
5731 }
5732 else
5733 {
5734 /* Use route via neighbour */
5735 n = lookup_neighbour (&cb->pid);
5736 if (NULL != n)
5738 n,
5739 &be->header,
5740 RMO_NONE);
5741 }
5743}
5744
5745
5753static int
5755 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5756{
5757 struct TransportClient *tc = cls;
5758
5759 if (CT_COMMUNICATOR != tc->type)
5760 {
5761 GNUNET_break (0);
5762 return GNUNET_SYSERR;
5763 }
5765 return GNUNET_OK;
5766}
5767
5768
5774static void
5775store_pi (void *cls);
5776
5777
5784static void
5785peerstore_store_own_cb (void *cls, int success)
5786{
5787 struct AddressListEntry *ale = cls;
5788
5789 ale->sc = NULL;
5790 if (GNUNET_YES != success)
5792 "Failed to store our own address `%s' in peerstore!\n",
5793 ale->address);
5794 else
5796 "Successfully stored our own address `%s' in peerstore!\n",
5797 ale->address);
5798 /* refresh period is 1/4 of expiration time, that should be plenty
5799 without being excessive. */
5800 ale->st =
5802 4ULL),
5803 &store_pi,
5804 ale);
5805}
5806
5807
5808static void
5809shc_cont (void *cls, int success)
5810{
5811 struct AddressListEntry *ale = cls;
5813
5816 "transport",
5819 ale->signed_address,
5820 ale->signed_address_len,
5821 expiration,
5824 ale);
5825 if (NULL == ale->sc)
5826 {
5828 "Failed to store our address `%s' with peerstore\n",
5829 ale->address);
5831 &store_pi,
5832 ale);
5833 }
5834}
5835
5836
5842static void
5843store_pi (void *cls)
5844{
5845 struct AddressListEntry *ale = cls;
5846 struct GNUNET_MQ_Envelope *env;
5847 const struct GNUNET_MessageHeader *msg;
5848 const char *dash;
5849 char *address_uri;
5851 unsigned int add_success;
5852
5853 dash = strchr (ale->address, '-');
5854 GNUNET_assert (NULL != dash);
5855 dash++;
5856 GNUNET_asprintf (&address_uri,
5857 "%s://%s",
5858 prefix,
5859 dash);
5861 ale->st = NULL;
5863 "Storing our address `%s' in peerstore until %s!\n",
5864 ale->address,
5867 address_uri);
5868 if (GNUNET_OK != add_success)
5869 {
5871 "Storing our address `%s' %s\n",
5872 address_uri,
5873 GNUNET_NO == add_success ? "not done" : "failed");
5874 GNUNET_free (address_uri);
5875 return;
5876 }
5877 else
5878 {
5879
5881 "Storing our address `%s'\n",
5882 address_uri);
5883 }
5884 // FIXME hello_mono_time used here?? What about expiration in ale?
5886 ale->nt,
5889 &ale->signed_address,
5890 &ale->signed_address_len);
5891 GNUNET_free (address_uri);
5897 "store_pi 1\n");
5899 msg,
5900 shc_cont,
5901 ale);
5902 GNUNET_free (env);
5903}
5904
5905
5906static struct AddressListEntry *
5910 const char *address,
5911 uint32_t aid,
5912 size_t slen)
5913{
5914 struct AddressListEntry *ale;
5915
5916 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
5917 ale->tc = tc;
5918 ale->address = (const char *) &ale[1];
5919 ale->expiration = expiration;
5920 ale->aid = aid;
5921 ale->nt = nt;
5922 memcpy (&ale[1], address, slen);
5923 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
5924
5925 return ale;
5926}
5927
5928
5935static void
5937 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5938{
5939 struct TransportClient *tc = cls;
5940 struct AddressListEntry *ale;
5941 size_t slen;
5942 char *address;
5943
5944 /* 0-termination of &aam[1] was checked in #check_add_address */
5946 "Communicator added address `%s'!\n",
5947 (const char *) &aam[1]);
5948 slen = ntohs (aam->header.size) - sizeof(*aam);
5949 address = GNUNET_malloc (slen);
5950 memcpy (address, &aam[1], slen);
5951 ale = create_address_entry (tc,
5953 (enum GNUNET_NetworkType) ntohl (aam->nt),
5954 address,
5955 aam->aid,
5956 slen);
5957 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
5958 tc->details.communicator.addr_tail,
5959 ale);
5961}
5962
5963
5970static void
5972 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5973{
5974 struct TransportClient *tc = cls;
5975 struct AddressListEntry *alen;
5976
5977 if (CT_COMMUNICATOR != tc->type)
5978 {
5979 GNUNET_break (0);
5981 return;
5982 }
5983 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
5984 NULL != ale;
5985 ale = alen)
5986 {
5987 alen = ale->next;
5988 if (dam->aid != ale->aid)
5989 continue;
5990 GNUNET_assert (ale->tc == tc);
5992 "Communicator deleted address `%s'!\n",
5993 ale->address);
5996 return;
5997 }
5999 "Communicator removed address we did not even have.\n");
6001 // GNUNET_SERVICE_client_drop (tc->client);
6002}
6003
6004
6012static void
6014
6015
6023static void
6025{
6026 struct CoreSentContext *ctx = cls;
6027 struct VirtualLink *vl = ctx->vl;
6028
6029 if (NULL == vl)
6030 {
6031 /* lost the link in the meantime, ignore */
6032 GNUNET_free (ctx);
6033 return;
6034 }
6037 vl->incoming_fc_window_size_ram -= ctx->size;
6038 vl->incoming_fc_window_size_used += ctx->isize;
6040 GNUNET_free (ctx);
6041}
6042
6043
6044static void
6046 const struct GNUNET_MessageHeader *mh,
6047 struct CommunicatorMessageContext *cmc,
6048 unsigned int free_cmc)
6049{
6050 uint16_t size = ntohs (mh->size);
6051 int have_core;
6052
6053 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6054 {
6056 "# CORE messages dropped (FC arithmetic overflow)",
6057 1,
6058 GNUNET_NO);
6060 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6061 (unsigned int) ntohs (mh->type),
6062 (unsigned int) ntohs (mh->size));
6063 if (GNUNET_YES == free_cmc)
6065 return;
6066 }
6068 {
6070 "# CORE messages dropped (FC window overflow)",
6071 1,
6072 GNUNET_NO);
6074 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6075 (unsigned int) ntohs (mh->type),
6076 (unsigned int) ntohs (mh->size));
6077 if (GNUNET_YES == free_cmc)
6079 return;
6080 }
6081
6082 /* Forward to all CORE clients */
6083 have_core = GNUNET_NO;
6084 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6085 {
6086 struct GNUNET_MQ_Envelope *env;
6087 struct InboundMessage *im;
6088 struct CoreSentContext *ctx;
6089
6090 if (CT_CORE != tc->type)
6091 continue;
6094 ctx = GNUNET_new (struct CoreSentContext);
6095 ctx->vl = vl;
6096 ctx->size = size;
6097 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6098 have_core = GNUNET_YES;
6101 im->peer = cmc->im.sender;
6102 memcpy (&im[1], mh, size);
6103 GNUNET_MQ_send (tc->mq, env);
6105 }
6106 if (GNUNET_NO == have_core)
6107 {
6109 "Dropped message to CORE: no CORE client connected!\n");
6110 /* Nevertheless, count window as used, as it is from the
6111 perspective of the other peer! */
6113 /* TODO-M1 */
6115 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6116 (unsigned int) ntohs (mh->type),
6117 (unsigned int) ntohs (mh->size));
6118 if (GNUNET_YES == free_cmc)
6120 return;
6121 }
6123 "Delivered message from %s of type %u to CORE recv window %d\n",
6124 GNUNET_i2s (&cmc->im.sender),
6125 ntohs (mh->type),
6127 if (vl->core_recv_window > 0)
6128 {
6129 if (GNUNET_YES == free_cmc)
6131 return;
6132 }
6133 /* Wait with calling #finish_cmc_handling(cmc) until the message
6134 was processed by CORE MQs (for CORE flow control)! */
6135 if (GNUNET_YES == free_cmc)
6137}
6138
6139
6148static void
6150{
6151 struct CommunicatorMessageContext *cmc = cls;
6152 // struct CommunicatorMessageContext *cmc_copy =
6153 // GNUNET_new (struct CommunicatorMessageContext);
6154 struct GNUNET_MessageHeader *mh_copy;
6155 struct RingBufferEntry *rbe;
6156 struct VirtualLink *vl;
6157 uint16_t size = ntohs (mh->size);
6158
6160 "Handling raw message of type %u with %u bytes\n",
6161 (unsigned int) ntohs (mh->type),
6162 (unsigned int) ntohs (mh->size));
6163
6164 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6165 (size < sizeof(struct GNUNET_MessageHeader)))
6166 {
6167 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6168
6169 GNUNET_break (0);
6170 finish_cmc_handling (cmc);
6172 return;
6173 }
6174 vl = lookup_virtual_link (&cmc->im.sender);
6175 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6176 {
6177 /* FIXME: sender is giving us messages for CORE but we don't have
6178 the link up yet! I *suspect* this can happen right now (i.e.
6179 sender has verified us, but we didn't verify sender), but if
6180 we pass this on, CORE would be confused (link down, messages
6181 arrive). We should investigate more if this happens often,
6182 or in a persistent manner, and possibly do "something" about
6183 it. Thus logging as error for now. */
6184
6185 mh_copy = GNUNET_malloc (size);
6186 rbe = GNUNET_new (struct RingBufferEntry);
6187 rbe->cmc = cmc;
6188 /*cmc_copy->tc = cmc->tc;
6189 cmc_copy->im = cmc->im;*/
6190 GNUNET_memcpy (mh_copy, mh, size);
6191
6192 rbe->mh = mh_copy;
6193
6195 {
6196 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6197 GNUNET_free (rbe_old->cmc);
6198 GNUNET_free (rbe_old->mh);
6199 GNUNET_free (rbe_old);
6200 }
6201 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6202 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6203 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6205 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6206 GNUNET_i2s (&cmc->im.sender),
6207 (unsigned int) ntohs (mh->type),
6208 (unsigned int) ntohs (mh_copy->type),
6212 {
6213 ring_buffer_head = 0;
6215 }
6216 else
6218
6220 "%u items stored in ring buffer\n",
6223
6224 /*GNUNET_break_op (0);
6225 GNUNET_STATISTICS_update (GST_stats,
6226 "# CORE messages dropped (virtual link still down)",
6227 1,
6228 GNUNET_NO);
6229
6230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6231 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6232 (unsigned int) ntohs (mh->type),
6233 (unsigned int) ntohs (mh->size));
6234 finish_cmc_handling (cmc);*/
6237 // GNUNET_free (cmc);
6238 return;
6239 }
6241}
6242
6243
6251static int
6253{
6254 uint16_t size = ntohs (fb->header.size);
6255 uint16_t bsize = size - sizeof(*fb);
6256
6257 (void) cls;
6258 if (0 == bsize)
6259 {
6260 GNUNET_break_op (0);
6261 return GNUNET_SYSERR;
6262 }
6263 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6264 {
6265 GNUNET_break_op (0);
6266 return GNUNET_SYSERR;
6267 }
6268 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6269 {
6270 GNUNET_break_op (0);
6271 return GNUNET_SYSERR;
6272 }
6273 return GNUNET_YES;
6274}
6275
6276
6282static void
6284{
6285 struct AcknowledgementCummulator *ac = cls;
6286
6287 ac->task = NULL;
6288 GNUNET_assert (0 == ac->num_acks);
6290 GNUNET_YES ==
6292 GNUNET_free (ac);
6293}
6294
6295
6301static void
6303{
6304 struct Neighbour *n;
6305 struct VirtualLink *vl;
6306 struct AcknowledgementCummulator *ac = cls;
6307 char buf[sizeof(struct TransportReliabilityAckMessage)
6308 + ac->num_acks
6310 struct TransportReliabilityAckMessage *ack =
6311 (struct TransportReliabilityAckMessage *) buf;
6313
6314 ac->task = NULL;
6316 "Sending ACK with %u components to %s\n",
6317 ac->num_acks,
6318 GNUNET_i2s (&ac->target));
6319 GNUNET_assert (0 < ac->num_acks);
6321 ack->header.size =
6322 htons (sizeof(*ack)
6323 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6324 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6325 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6326 for (unsigned int i = 0; i < ac->num_acks; i++)
6327 {
6328 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6331 }
6332 /*route_control_message_without_fc (
6333 &ac->target,
6334 &ack->header,
6335 RMO_DV_ALLOWED);*/
6336 vl = lookup_virtual_link (&ac->target);
6337 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6338 {
6340 vl,
6341 &ack->header,
6343 }
6344 else
6345 {
6346 /* Use route via neighbour */
6347 n = lookup_neighbour (&ac->target);
6348 if (NULL != n)
6350 n,
6351 &ack->header,
6352 RMO_NONE);
6353 }
6354 ac->num_acks = 0;
6357 ac);
6358}
6359
6360
6369static void
6371 const struct AcknowledgementUUIDP *ack_uuid,
6372 struct GNUNET_TIME_Absolute max_delay)
6373{
6374 struct AcknowledgementCummulator *ac;
6375
6377 "Scheduling ACK %s for transmission to %s\n",
6378 GNUNET_uuid2s (&ack_uuid->value),
6379 GNUNET_i2s (pid));
6381 if (NULL == ac)
6382 {
6384 ac->target = *pid;
6385 ac->min_transmission_time = max_delay;
6389 &ac->target,
6390 ac,
6392 }
6393 else
6394 {
6395 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6396 {
6397 /* must run immediately, ack buffer full! */
6399 }
6403 }
6406 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6407 ac->num_acks++;
6410 ac);
6411}
6412
6413
6418{
6423
6428};
6429
6430
6440static int
6441find_by_message_uuid (void *cls, uint32_t key, void *value)
6442{
6443 struct FindByMessageUuidContext *fc = cls;
6444 struct ReassemblyContext *rc = value;
6445
6446 (void) key;
6447 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6448 {
6449 fc->rc = rc;
6450 return GNUNET_NO;
6451 }
6452 return GNUNET_YES;
6453}
6454
6455
6463static void
6465{
6466 struct CommunicatorMessageContext *cmc = cls;
6467 struct VirtualLink *vl;
6468 struct ReassemblyContext *rc;
6469 const struct GNUNET_MessageHeader *msg;
6470 uint16_t msize;
6471 uint16_t fsize;
6472 uint16_t frag_off;
6473 char *target;
6474 struct GNUNET_TIME_Relative cdelay;
6475 struct FindByMessageUuidContext fc;
6476
6477 vl = lookup_virtual_link (&cmc->im.sender);
6478 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6479 {
6480 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6481
6483 "No virtual link for %s to handle fragment\n",
6484 GNUNET_i2s (&cmc->im.sender));
6485 GNUNET_break (0);
6486 finish_cmc_handling (cmc);
6488 return;
6489 }
6490 if (NULL == vl->reassembly_map)
6491 {
6493 vl->reassembly_heap =
6498 vl);
6499 }
6500 msize = ntohs (fb->msg_size);
6501 fc.message_uuid = fb->msg_uuid;
6502 fc.rc = NULL;
6504 fb->msg_uuid.uuid,
6506 &fc);
6507 fsize = ntohs (fb->header.size) - sizeof(*fb);
6508 if (NULL == (rc = fc.rc))
6509 {
6510 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6511 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6512 rc->msg_uuid = fb->msg_uuid;
6513 rc->virtual_link = vl;
6514 rc->msg_size = msize;
6515 rc->reassembly_timeout =
6519 rc,
6523 vl->reassembly_map,
6524 rc->msg_uuid.uuid,
6525 rc,
6527 target = (char *) &rc[1];
6528 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6529 if (fsize != rc->msg_size)
6530 rc->msg_missing = rc->msg_size;
6531 else
6532 rc->msg_missing = 0;
6534 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6535 PRIu64 "\n",
6536 fsize,
6537 ntohs (fb->frag_off),
6538 msize,
6539 rc->msg_missing,
6540 GNUNET_i2s (&cmc->im.sender),
6541 fb->msg_uuid.uuid);
6542 }
6543 else
6544 {
6545 target = (char *) &rc[1];
6547 "Received fragment at offset %u/%u from %s for message %u\n",
6548 ntohs (fb->frag_off),
6549 msize,
6550 GNUNET_i2s (&cmc->im.sender),
6551 (unsigned int) fb->msg_uuid.uuid);
6552 }
6553 if (msize != rc->msg_size)
6554 {
6555 GNUNET_break (0);
6556 finish_cmc_handling (cmc);
6557 return;
6558 }
6559
6560 /* reassemble */
6561 if (0 == fsize)
6562 {
6563 GNUNET_break (0);
6564 finish_cmc_handling (cmc);
6565 return;
6566 }
6567 frag_off = ntohs (fb->frag_off);
6568 if (frag_off + fsize > msize)
6569 {
6570 /* Fragment (plus fragment size) exceeds message size! */
6571 GNUNET_break_op (0);
6572 finish_cmc_handling (cmc);
6573 return;
6574 }
6575 memcpy (&target[frag_off], &fb[1], fsize);
6576 /* update bitfield and msg_missing */
6577 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6578 {
6579 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6580 {
6581 rc->bitfield[i / 8] |= (1 << (i % 8));
6582 rc->msg_missing--;
6583 }
6584 }
6585
6586 /* Compute cumulative ACK */
6588 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6589 if (0 == rc->msg_missing)
6590 cdelay = GNUNET_TIME_UNIT_ZERO;
6591 cummulative_ack (&cmc->im.sender,
6592 &fb->ack_uuid,
6595 /* is reassembly complete? */
6596 if (0 != rc->msg_missing)
6597 {
6598 finish_cmc_handling (cmc);
6599 return;
6600 }
6601 /* reassembly is complete, verify result */
6602 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6603 if (ntohs (msg->size) != rc->msg_size)
6604 {
6605 GNUNET_break (0);
6607 finish_cmc_handling (cmc);
6608 return;
6609 }
6610 /* successful reassembly */
6612 "Fragment reassembly complete for message %u\n",
6613 (unsigned int) fb->msg_uuid.uuid);
6614 /* FIXME: check that the resulting msg is NOT a
6615 DV Box or Reliability Box, as that is NOT allowed! */
6616 cmc->mh = msg;
6618 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6619 en-route and we forget that we finished this reassembly immediately!
6620 -> keep around until timeout?
6621 -> shorten timeout based on ACK? */
6623}
6624
6625
6633static int
6635 const struct TransportReliabilityBoxMessage *rb)
6636{
6637 (void) cls;
6638 const struct GNUNET_MessageHeader *inbox = (const struct
6639 GNUNET_MessageHeader *) &rb[1];
6640
6642 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6643 ntohs (rb->header.size),
6644 ntohs (inbox->type),
6645 ntohs (inbox->size),
6646 sizeof (struct TransportReliabilityBoxMessage),
6647 sizeof (struct GNUNET_MessageHeader));
6649 return GNUNET_YES;
6650}
6651
6652
6660static void
6662 const struct TransportReliabilityBoxMessage *rb)
6663{
6664 struct CommunicatorMessageContext *cmc = cls;
6665 const struct GNUNET_MessageHeader *inbox =
6666 (const struct GNUNET_MessageHeader *) &rb[1];
6667 struct GNUNET_TIME_Relative rtt;
6668
6670 "Received reliability box from %s with UUID %s of type %u\n",
6671 GNUNET_i2s (&cmc->im.sender),
6673 (unsigned int) ntohs (inbox->type));
6674 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6675 do not really have an RTT for the
6676 * incoming* queue (should we have
6677 the sender add it to the rb message?) */
6679 &cmc->im.sender,
6680 &rb->ack_uuid,
6681 (0 == ntohl (rb->ack_countdown))
6684 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6685 /* continue with inner message */
6686 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6687 reliability box (not allowed!) */
6688 cmc->mh = inbox;
6690}
6691
6692
6701static void
6702update_pd_age (struct PerformanceData *pd, unsigned int age)
6703{
6704 unsigned int sage;
6705
6706 if (age == pd->last_age)
6707 return; /* nothing to do */
6708 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6709 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6710 {
6711 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6712
6713 the->bytes_sent = 0;
6714 the->bytes_received = 0;
6715 }
6716 pd->last_age = age;
6717}
6718
6719
6728static void
6730 struct GNUNET_TIME_Relative rtt,
6731 uint16_t bytes_transmitted_ok)
6732{
6733 uint64_t nval = rtt.rel_value_us;
6734 uint64_t oval = pd->aged_rtt.rel_value_us;
6735 unsigned int age = get_age ();
6736 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
6737
6738 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
6739 pd->aged_rtt = rtt;
6740 else
6741 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
6742 update_pd_age (pd, age);
6743 the->bytes_received += bytes_transmitted_ok;
6744}
6745
6746
6754static void
6756 struct GNUNET_TIME_Relative rtt,
6757 uint16_t bytes_transmitted_ok)
6758{
6759 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
6760}
6761
6762
6770static void
6772 struct GNUNET_TIME_Relative rtt,
6773 uint16_t bytes_transmitted_ok)
6774{
6775 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
6776}
6777
6778
6786static void
6788{
6789 struct PendingMessage *pos;
6790
6792 "Complete transmission of message %" PRIu64 " %u\n",
6793 pm->logging_uuid,
6794 pm->pmt);
6795 switch (pm->pmt)
6796 {
6797 case PMT_CORE:
6799 /* Full message sent, we are done */
6801 return;
6802
6803 case PMT_FRAGMENT_BOX:
6804 /* Fragment sent over reliable channel */
6805 pos = pm->frag_parent;
6809 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
6810 (unsigned long) pos->frag_off,
6811 (unsigned long) pos->bytes_msg,
6812 pos->pmt,
6813 NULL == pos->frag_parent ? 1 : 0);
6814 /* check if subtree is done */
6815 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
6816 - sizeof(struct
6818 &&
6819 (NULL != pos->frag_parent))
6820 {
6821 pm = pos;
6822 pos = pm->frag_parent;
6823 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
6824 {
6826 return;
6827 }
6828 else if (PMT_DV_BOX == pm->pmt)
6829 {
6831 return;
6832 }
6835 }
6836
6837 /* Was this the last applicable fragment? */
6838 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
6839 pos->pmt) &&
6840 (pos->frag_off == pos->bytes_msg))
6842 return;
6843
6844 case PMT_DV_BOX:
6846 "Completed transmission of message %" PRIu64 " (DV Box)\n",
6847 pm->logging_uuid);
6848 if (NULL != pm->frag_parent)
6849 {
6850 pos = pm->frag_parent;
6852 pos->bpm = NULL;
6854 }
6855 else
6857 return;
6858 }
6859}
6860
6861
6869static void
6871 struct GNUNET_TIME_Relative ack_delay)
6872{
6873 struct GNUNET_TIME_Relative delay;
6874
6876 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
6877 if (NULL != pa->queue && 1 == pa->num_send)
6879 if (NULL != pa->dvh && 1 == pa->num_send)
6880 update_dvh_performance (pa->dvh, delay, pa->message_size);
6881 if (NULL != pa->pm)
6884}
6885
6886
6894static int
6896 const struct TransportReliabilityAckMessage *ra)
6897{
6898 unsigned int n_acks;
6899
6900 (void) cls;
6901 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
6902 / sizeof(struct TransportCummulativeAckPayloadP);
6903 if (0 == n_acks)
6904 {
6905 GNUNET_break_op (0);
6906 return GNUNET_SYSERR;
6907 }
6908 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
6909 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
6910 {
6911 GNUNET_break_op (0);
6912 return GNUNET_SYSERR;
6913 }
6914 return GNUNET_OK;
6915}
6916
6917
6925static void
6927 const struct TransportReliabilityAckMessage *ra)
6928{
6929 struct CommunicatorMessageContext *cmc = cls;
6930 const struct TransportCummulativeAckPayloadP *ack;
6931 unsigned int n_acks;
6932 uint32_t ack_counter;
6933
6934 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
6935 / sizeof(struct TransportCummulativeAckPayloadP);
6936 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
6937 for (unsigned int i = 0; i < n_acks; i++)
6938 {
6939 struct PendingAcknowledgement *pa =
6941 if (NULL == pa)
6942 {
6944 "Received ACK from %s with UUID %s which is unknown to us!\n",
6945 GNUNET_i2s (&cmc->im.sender),
6946 GNUNET_uuid2s (&ack[i].ack_uuid.value));
6948 GST_stats,
6949 "# FRAGMENT_ACKS dropped, no matching pending message",
6950 1,
6951 GNUNET_NO);
6952 continue;
6953 }
6955 "Received ACK from %s with UUID %s\n",
6956 GNUNET_i2s (&cmc->im.sender),
6957 GNUNET_uuid2s (&ack[i].ack_uuid.value));
6958 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
6959 }
6960
6961 ack_counter = htonl (ra->ack_counter);
6962 (void) ack_counter; /* silence compiler warning for now */
6963 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
6964 // (DV and/or Neighbour?)
6965 finish_cmc_handling (cmc);
6966}
6967
6968
6976static int
6978 void *cls,
6980{
6981 uint16_t size = ntohs (be->header.size) - sizeof(*be);
6982 const struct GNUNET_MessageHeader *inbox =
6983 (const struct GNUNET_MessageHeader *) &be[1];
6984 const char *is;
6985 uint16_t isize;
6986
6987 (void) cls;
6988 if (ntohs (inbox->size) >= size)
6989 {
6990 GNUNET_break_op (0);
6991 return GNUNET_SYSERR;
6992 }
6993 isize = ntohs (inbox->size);
6994 is = ((const char *) inbox) + isize;
6995 size -= isize;
6996 if ('\0' != is[size - 1])
6997 {
6998 GNUNET_break_op (0);
6999 return GNUNET_SYSERR;
7000 }
7001 return GNUNET_YES;
7002}
7003
7004
7013static void
7015 void *cls,
7017{
7018 struct CommunicatorMessageContext *cmc = cls;
7020 struct GNUNET_MQ_Envelope *env;
7021 struct TransportClient *tc;
7022 const struct GNUNET_MessageHeader *inbox =
7023 (const struct GNUNET_MessageHeader *) &be[1];
7024 uint16_t isize = ntohs (inbox->size);
7025 const char *target_communicator = ((const char *) inbox) + isize;
7026 char *sender;
7027 char *self;
7028
7029 GNUNET_asprintf (&sender,
7030 "%s",
7031 GNUNET_i2s (&cmc->im.sender));
7032 GNUNET_asprintf (&self,
7033 "%s",
7035
7036 /* Find client providing this communicator */
7037 for (tc = clients_head; NULL != tc; tc = tc->next)
7038 if ((CT_COMMUNICATOR == tc->type) &&
7039 (0 ==
7040 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7041 break;
7042 if (NULL == tc)
7043 {
7044 char *stastr;
7045
7047 &stastr,
7048 "# Backchannel message dropped: target communicator `%s' unknown",
7049 target_communicator);
7051 GNUNET_free (stastr);
7052 finish_cmc_handling (cmc);
7053 return;
7054 }
7055 /* Finally, deliver backchannel message to communicator */
7057 "Delivering backchannel message from %s to %s of type %u to %s\n",
7058 sender,
7059 self,
7060 ntohs (inbox->type),
7061 target_communicator);
7063 cbi,
7064 isize,
7066 cbi->pid = cmc->im.sender;
7067 memcpy (&cbi[1], inbox, isize);
7068 GNUNET_MQ_send (tc->mq, env);
7069 finish_cmc_handling (cmc);
7070}
7071
7072
7082static void
7084{
7085 struct DistanceVector *dv = cls;
7086 struct DistanceVectorHop *pos;
7087
7088 dv->timeout_task = NULL;
7089 while (NULL != (pos = dv->dv_head))
7090 {
7091 GNUNET_assert (dv == pos->dv);
7093 break;
7095 }
7096 if (NULL == pos)
7097 {
7098 free_dv_route (dv);
7099 return;
7100 }
7101 dv->timeout_task =
7103}
7104
7105
7106static void
7108{
7109
7110 const struct GNUNET_PeerIdentity target = vl->target;
7111
7112
7114 {
7115 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7116 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7117 0;
7118 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7121 struct CommunicatorMessageContext *cmc;
7122 struct RingBufferEntry *rbe;
7123 struct GNUNET_MessageHeader *mh;
7124
7126 "Sending from ring buffer, which has %u items\n",
7127 head);
7128
7129 ring_buffer_head = 0;
7130 for (unsigned int i = 0; i < head; i++)
7131 {
7132 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7133 cmc = rbe->cmc;
7134 mh = rbe->mh;
7135
7136 im = cmc->im;
7137 // mh = cmc->mh;
7139 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7140 mh->type,
7141 GNUNET_i2s (&im.sender),
7142 GNUNET_i2s2 (&target),
7143 (i + tail) % RING_BUFFER_SIZE);
7144 if (0 == GNUNET_memcmp (&target, &im.sender))
7145 {
7147 "Finish handling message of type %u and size %u\n",
7148 (unsigned int) ntohs (mh->type),
7149 (unsigned int) ntohs (mh->size));
7151 GNUNET_free (mh);
7152 GNUNET_free (rbe->cmc);
7153 GNUNET_free (rbe);
7154 }
7155 else
7156 {
7157 ring_buffer_copy[ring_buffer_head] = rbe;
7159 }
7160 }
7161
7164 {
7166 }
7167
7168 for (unsigned int i = 0; i < ring_buffer_head; i++)
7169 {
7170 ring_buffer[i] = ring_buffer_copy[i];
7172 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7173 i,
7174 ring_buffer_copy[i]->mh->type);
7176 "ring_buffer[i]->mh->type for i %u %u\n",
7177 i,
7178 ring_buffer[i]->mh->type);
7179 }
7180
7182 "%u items still in ring buffer\n",
7184 }
7185
7187 {
7188 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7189 struct PendingMessage *pm;
7190 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7192 0;
7193 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7196
7198 "Sending from ring buffer dv, which has %u items\n",
7199 head);
7200
7202 for (unsigned int i = 0; i < head; i++)
7203 {
7204 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7205
7207 "Sending to ring buffer target %s using vl target %s\n",
7208 GNUNET_i2s (&pm->target),
7209 GNUNET_i2s2 (&target));
7210 if (0 == GNUNET_memcmp (&target, &pm->target))
7211 {
7213 "Adding PendingMessage to vl, checking transmission.\n");
7214 pm->vl = vl;
7218 pm);
7219
7221 }
7222 else
7223 {
7224 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7226 }
7227 }
7228
7230 {
7232 }
7233
7234 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7235 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7236
7238 "%u items still in ring buffer dv.\n",
7240
7241 }
7242}
7243
7244
7252static void
7254{
7255 struct DistanceVector *dv = hop->dv;
7256 struct VirtualLink *vl;
7257
7258 vl = lookup_virtual_link (&dv->target);
7259 if (NULL == vl)
7260 {
7261
7262 vl = GNUNET_new (struct VirtualLink);
7264 "Creating new virtual link %p to %s using DV!\n",
7265 vl,
7266 GNUNET_i2s (&dv->target));
7267 vl->confirmed = GNUNET_YES;
7268 vl->message_uuid_ctr =
7270 vl->target = dv->target;
7276 links,
7277 &vl->target,
7278 vl,
7280 vl->dv = dv;
7281 dv->vl = vl;
7282 vl->visibility_task =
7285 /* We lacked a confirmed connection to the target
7286 before, so tell CORE about it (finally!) */
7289 }
7290 else
7291 {
7292 /* Link was already up, remember dv is also now available and we are done */
7293 vl->dv = dv;
7294 dv->vl = vl;
7295 if (GNUNET_NO == vl->confirmed)
7296 {
7297 vl->confirmed = GNUNET_YES;
7298 vl->visibility_task =
7301 /* We lacked a confirmed connection to the target
7302 before, so tell CORE about it (finally!) */
7305 }
7306 else
7308 "Virtual link to %s could now also use DV!\n",
7309 GNUNET_i2s (&dv->target));
7310 }
7311}
7312
7313
7339static int
7341 unsigned int path_len,
7342 struct GNUNET_TIME_Relative network_latency,
7343 struct GNUNET_TIME_Absolute path_valid_until)
7344{
7345 struct DistanceVectorHop *hop;
7346 struct DistanceVector *dv;
7347 struct Neighbour *next_hop;
7348 unsigned int shorter_distance;
7349
7350 if (path_len < 3)
7351 {
7352 /* what a boring path! not allowed! */
7353 GNUNET_break (0);
7354 return GNUNET_SYSERR;
7355 }
7356 GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
7357 next_hop = lookup_neighbour (&path[1]);
7358 if (NULL == next_hop)
7359 {
7360 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7361 GNUNET_break (0);
7362 return GNUNET_SYSERR;
7363 }
7364 for (unsigned int i = 2; i < path_len; i++)
7365 if (NULL != lookup_neighbour (&path[i]))
7366 {
7367 /* Useless path: we have a direct connection to some hop
7368 in the middle of the path, so this one is not even
7369 terribly useful for redundancy */
7371 "Path of %u hops useless: directly link to hop %u (%s)\n",
7372 path_len,
7373 i,
7374 GNUNET_i2s (&path[i]));
7376 "# Useless DV path ignored: hop is neighbour",
7377 1,
7378 GNUNET_NO);
7379 return GNUNET_SYSERR;
7380 }
7381 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7382 if (NULL == dv)
7383 {
7384 dv = GNUNET_new (struct DistanceVector);
7385 dv->target = path[path_len - 1];
7388 dv);
7391 dv_routes,
7392 &dv->target,
7393 dv,
7395 }
7396 /* Check if we have this path already! */
7397 shorter_distance = 0;
7398 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7399 pos = pos->next_dv)
7400 {
7401 if (pos->distance < path_len - 3)
7402 shorter_distance++;
7403 /* Note that the distances in 'pos' excludes us (path[0]),
7404 the next_hop (path[1]) and the target so we need to subtract three
7405 and check next_hop explicitly */
7406 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7407 {
7408 int match = GNUNET_YES;
7409
7410 for (unsigned int i = 0; i < pos->distance; i++)
7411 {
7412 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7413 {
7414 match = GNUNET_NO;
7415 break;
7416 }
7417 }
7418 if (GNUNET_YES == match)
7419 {
7420 struct GNUNET_TIME_Relative last_timeout;
7421
7422 /* Re-discovered known path, update timeout */
7424 "# Known DV path refreshed",
7425 1,
7426 GNUNET_NO);
7427 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7428 pos->timeout =
7430 pos->path_valid_until =
7431 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7432 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7433 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7434 if (0 <
7437 if (last_timeout.rel_value_us <
7440 .rel_value_us)
7441 {
7442 /* Some peer send DV learn messages too often, we are learning
7443 the same path faster than it would be useful; do not forward! */
7445 "Rediscovered path too quickly, not forwarding further\n");
7446 return GNUNET_NO;
7447 }
7449 "Refreshed known path to %s valid until %s, forwarding further\n",
7450 GNUNET_i2s (&dv->target),
7452 pos->path_valid_until));
7453 return GNUNET_YES;
7454 }
7455 }
7456 }
7457 /* Count how many shorter paths we have (incl. direct
7458 neighbours) before simply giving up on this one! */
7459 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7460 {
7461 /* We have a shorter path already! */
7463 "Have many shorter DV paths %s, not forwarding further\n",
7464 GNUNET_i2s (&dv->target));
7465 return GNUNET_NO;
7466 }
7467 /* create new DV path entry */
7469 "Discovered new DV path to %s valid until %s\n",
7470 GNUNET_i2s (&dv->target),
7471 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7472 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7473 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7474 hop->next_hop = next_hop;
7475 hop->dv = dv;
7476 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7477 memcpy (&hop[1],
7478 &path[2],
7479 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7481 hop->path_valid_until = path_valid_until;
7482 hop->distance = path_len - 3;
7483 hop->pd.aged_rtt = network_latency;
7484 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7486 next_hop->dv_head,
7487 next_hop->dv_tail,
7488 hop);
7489 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7491 return GNUNET_YES;
7492}
7493
7494
7502static int
7503check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7504{
7505 uint16_t size = ntohs (dvl->header.size);
7506 uint16_t num_hops = ntohs (dvl->num_hops);
7507 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7508
7509 (void) cls;
7510 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7511 {
7512 GNUNET_break_op (0);
7513 return GNUNET_SYSERR;
7514 }
7515 if (num_hops > MAX_DV_HOPS_ALLOWED)
7516 {
7517 GNUNET_break_op (0);
7518 return GNUNET_SYSERR;
7519 }
7520 for (unsigned int i = 0; i < num_hops; i++)
7521 {
7522 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7523 {
7524 GNUNET_break_op (0);
7525 return GNUNET_SYSERR;
7526 }
7527 if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
7528 {
7529 GNUNET_break_op (0);
7530 return GNUNET_SYSERR;
7531 }
7532 }
7533 return GNUNET_YES;
7534}
7535
7536
7548static void
7550 const struct TransportDVLearnMessage *msg,
7551 uint16_t bi_history,
7552 uint16_t nhops,
7553 const struct DVPathEntryP *hops,
7554 struct GNUNET_TIME_Absolute in_time)
7555{
7556 struct Neighbour *n;
7557 struct VirtualLink *vl;
7558 struct DVPathEntryP *dhops;
7559 char buf[sizeof(struct TransportDVLearnMessage)
7560 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7561 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7562 struct GNUNET_TIME_Relative nnd;
7563
7564 /* compute message for forwarding */
7566 "Forwarding DV learn message originating from %s to %s\n",
7567 GNUNET_i2s (&msg->initiator),
7568 GNUNET_i2s2 (next_hop));
7571 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7572 + (nhops + 1) * sizeof(struct DVPathEntryP));
7573 fwd->num_hops = htons (nhops + 1);
7574 fwd->bidirectional = htons (bi_history);
7577 msg->non_network_delay));
7579 fwd->init_sig = msg->init_sig;
7580 fwd->initiator = msg->initiator;
7581 fwd->challenge = msg->challenge;
7582 fwd->monotonic_time = msg->monotonic_time;
7583 dhops = (struct DVPathEntryP *) &fwd[1];
7584 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7585 dhops[nhops].hop = GST_my_identity;
7586 {
7587 struct DvHopPS dhp = {
7589 .purpose.size = htonl (sizeof(dhp)),
7590 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7591 .succ = *next_hop,
7592 .challenge = msg->challenge
7593 };
7595 &dhp,
7596 &dhops[nhops].hop_sig);
7597 }
7598 /*route_control_message_without_fc (next_hop,
7599 &fwd->header,
7600 RMO_UNCONFIRMED_ALLOWED);*/
7601 vl = lookup_virtual_link (next_hop);
7602 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7603 {
7605 &fwd->header,
7607 }
7608 else
7609 {
7610 /* Use route via neighbour */
7611 n = lookup_neighbour (next_hop);
7612 if (NULL != n)
7614 n,
7615 &fwd->header,
7617 }
7618}
7619
7620
7630static int
7632 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
7633 const struct GNUNET_PeerIdentity *init,
7635 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
7636{
7637 struct DvInitPS ip = { .purpose.purpose = htonl (
7639 .purpose.size = htonl (sizeof(ip)),
7640 .monotonic_time = sender_monotonic_time,
7641 .challenge = *challenge };
7642
7643 if (
7644 GNUNET_OK !=
7646 &ip,
7647 init_sig,
7648 &init->public_key))
7649 {
7650 GNUNET_break_op (0);
7651 return GNUNET_SYSERR;
7652 }
7653 return GNUNET_OK;
7654}
7655
7656
7661{
7666
7670 const struct DVPathEntryP *hops;
7671
7676
7681
7685 unsigned int num_eligible;
7686
7690 unsigned int num_selections;
7691
7695 uint16_t nhops;
7696
7700 uint16_t bi_history;
7701};
7702
7703
7712static int
7714 const struct GNUNET_PeerIdentity *pid,
7715 void *value)
7716{
7717 struct NeighbourSelectionContext *nsc = cls;
7718
7719 (void) value;
7720 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7721 return GNUNET_YES; /* skip initiator */
7722 for (unsigned int i = 0; i < nsc->nhops; i++)
7723 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7724 return GNUNET_YES;
7725 /* skip peers on path */
7726 nsc->num_eligible++;
7727 return GNUNET_YES;
7728}
7729
7730
7741static int
7743 const struct GNUNET_PeerIdentity *pid,
7744 void *value)
7745{
7746 struct NeighbourSelectionContext *nsc = cls;
7747
7749 "transmission %s\n",
7750 GNUNET_i2s (pid));
7751 (void) value;
7752 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7753 return GNUNET_YES; /* skip initiator */
7754 for (unsigned int i = 0; i < nsc->nhops; i++)
7755 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7756 return GNUNET_YES;
7757 /* skip peers on path */
7758 for (unsigned int i = 0; i < nsc->num_selections; i++)
7759 {
7760 if (nsc->selections[i] == nsc->num_eligible)
7761 {
7763 nsc->dvl,
7764 nsc->bi_history,
7765 nsc->nhops,
7766 nsc->hops,
7767 nsc->in_time);
7768 break;
7769 }
7770 }
7771 nsc->num_eligible++;
7772 return GNUNET_YES;
7773}
7774
7775
7819static unsigned int
7820calculate_fork_degree (unsigned int hops_taken,
7821 unsigned int neighbour_count,
7822 unsigned int eligible_count)
7823{
7824 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
7825 double eligible_ratio =
7826 ((double) eligible_count) / ((double) neighbour_count);
7827 double boost_factor = eligible_ratio * eligible_ratio;
7828 unsigned int rnd;
7829 double left;
7830
7831 if (hops_taken >= 64)
7832 {
7833 GNUNET_break (0);
7834 return 0; /* precaution given bitshift below */
7835 }
7836 for (unsigned int i = 1; i < hops_taken; i++)
7837 {
7838 /* For each hop, subtract the expected number of targets
7839 reached at distance d (so what remains divided by 2^d) */
7840 target_total -= (target_total * boost_factor / (1LLU << i));
7841 }
7842 rnd =
7843 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
7844 /* round up or down probabilistically depending on how close we were
7845 when floor()ing to rnd */
7846 left = target_total - (double) rnd;
7847 if (UINT32_MAX * left >
7849 rnd++; /* round up */
7851 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
7852 hops_taken,
7853 rnd,
7854 eligible_count,
7855 neighbour_count);
7856 return rnd;
7857}
7858
7859
7866static void
7867neighbour_store_dvmono_cb (void *cls, int success)
7868{
7869 struct Neighbour *n = cls;
7870
7871 n->sc = NULL;
7872 if (GNUNET_YES != success)
7874 "Failed to store other peer's monotonic time in peerstore!\n");
7875}
7876
7877
7885static void
7886handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7887{
7888 struct CommunicatorMessageContext *cmc = cls;
7890 int bi_hop;
7891 uint16_t nhops;
7892 uint16_t bi_history;
7893 const struct DVPathEntryP *hops;
7894 int do_fwd;
7895 int did_initiator;
7896 struct GNUNET_TIME_Absolute in_time;
7897 struct Neighbour *n;
7898
7899 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
7900 bi_history = ntohs (dvl->bidirectional);
7901 hops = (const struct DVPathEntryP *) &dvl[1];
7902 if (0 == nhops)
7903 {
7904 /* sanity check */
7905 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
7906 {
7907 GNUNET_break (0);
7908 finish_cmc_handling (cmc);
7909 return;
7910 }
7911 }
7912 else
7913 {
7915 "handle dv learn message last hop %s\n",
7916 GNUNET_i2s (&hops[nhops - 1].hop));
7917 /* sanity check */
7918 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
7919 {
7920 GNUNET_break (0);
7921 finish_cmc_handling (cmc);
7922 return;
7923 }
7924 }
7925
7927 cc = cmc->tc->details.communicator.cc;
7928 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
7929 cc); // FIXME: add bi-directional flag to cc?
7930 in_time = GNUNET_TIME_absolute_get ();
7931
7932 /* continue communicator here, everything else can happen asynchronous! */
7933 finish_cmc_handling (cmc);
7934
7935 n = lookup_neighbour (&dvl->initiator);
7936 if (NULL != n)
7937 {
7938 if ((n->dv_monotime_available == GNUNET_YES) &&
7941 {
7943 "DV learn from %s discarded due to time travel",
7944 GNUNET_i2s (&dvl->initiator));
7946 "# DV learn discarded due to time travel",
7947 1,
7948 GNUNET_NO);
7949 return;
7950 }
7952 &dvl->initiator,
7953 &dvl->challenge,
7954 &dvl->init_sig))
7955 {
7957 "DV learn signature from %s invalid\n",
7958 GNUNET_i2s (&dvl->initiator));
7959 GNUNET_break_op (0);
7960 return;
7961 }
7964 {
7965 if (NULL != n->sc)
7966 {
7968 "store cancel\n");
7970 }
7971 n->sc =
7973 "transport",
7974 &dvl->initiator,
7976 &dvl->monotonic_time,
7977 sizeof(dvl->monotonic_time),
7981 n);
7982 }
7983 }
7984 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
7985 If signature verification load too high, implement random drop strategy */
7986 for (unsigned int i = 0; i < nhops; i++)
7987 {
7988 struct DvHopPS dhp = { .purpose.purpose =
7990 .purpose.size = htonl (sizeof(dhp)),
7991 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
7992 .succ = (nhops == i + 1) ? GST_my_identity
7993 : hops[i + 1].hop,
7994 .challenge = dvl->challenge };
7995
7996 if (GNUNET_OK !=
7998 &dhp,
7999 &hops[i].hop_sig,
8000 &hops[i].hop.public_key))
8001 {
8003 "DV learn from %s signature of hop %u invalid\n",
8004 GNUNET_i2s (&dvl->initiator),
8005 i);
8007 "signature of hop %s invalid\n",
8008 GNUNET_i2s (&hops[i].hop));
8010 "pred %s\n",
8011 GNUNET_i2s (&dhp.pred));
8013 "succ %s\n",
8014 GNUNET_i2s (&dhp.succ));
8016 "hash %s\n",
8017 GNUNET_sh2s (&dhp.challenge.value));
8018 GNUNET_break_op (0);
8019 return;
8020 }
8021 }
8022 if (GNUNET_EXTRA_LOGGING > 0)
8023 {
8024 char *path;
8025
8026 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8027 for (unsigned int i = 0; i < nhops; i++)
8028 {
8029 char *tmp;
8030
8031 GNUNET_asprintf (&tmp,
8032 "%s%s%s",
8033 path,
8034 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8035 GNUNET_i2s (&hops[i].hop));
8036 GNUNET_free (path);
8037 path = tmp;
8038 }
8040 "Received DVInit via %s%s%s\n",
8041 path,
8042 bi_hop ? "<->" : "-->",
8044 GNUNET_free (path);
8045 }
8046 do_fwd = GNUNET_YES;
8047 if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
8048 {
8049 struct GNUNET_PeerIdentity path[nhops + 1];
8050 struct GNUNET_TIME_Relative host_latency_sum;
8051 struct GNUNET_TIME_Relative latency;
8052 struct GNUNET_TIME_Relative network_latency;
8053
8054 /* We initiated this, learn the forward path! */
8055 path[0] = GST_my_identity;
8056 path[1] = hops[0].hop;
8057 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8058
8059 // Need also something to lookup initiation time
8060 // to compute RTT! -> add RTT argument here?
8062 dvl->monotonic_time));
8063 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8064 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8065 // (based on dvl->challenge, we can identify time of origin!)
8066
8067 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8068 /* assumption: latency on all links is the same */
8069 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8070
8071 for (unsigned int i = 2; i <= nhops; i++)
8072 {
8073 struct GNUNET_TIME_Relative ilat;
8074
8075 /* assumption: linear latency increase per hop */
8076 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8077 path[i] = hops[i - 1].hop;
8079 "Learned path with %u hops to %s with latency %s\n",
8080 i,
8081 GNUNET_i2s (&path[i]),
8083 learn_dv_path (path,
8084 i + 1,
8085 ilat,
8088 }
8089 /* as we initiated, do not forward again (would be circular!) */
8090 do_fwd = GNUNET_NO;
8091 return;
8092 }
8093 if (bi_hop)
8094 {
8095 /* last hop was bi-directional, we could learn something here! */
8096 struct GNUNET_PeerIdentity path[nhops + 2];
8097
8098 path[0] = GST_my_identity;
8099 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8100 for (unsigned int i = 0; i < nhops; i++)
8101 {
8102 int iret;
8103
8104 if (0 == (bi_history & (1 << i)))
8105 break; /* i-th hop not bi-directional, stop learning! */
8106 if (i == nhops - 1)
8107 {
8108 path[i + 2] = dvl->initiator;
8109 }
8110 else
8111 {
8112 path[i + 2] = hops[nhops - i - 2].hop;
8113 }
8114
8116 "Learned inverse path with %u hops to %s\n",
8117 i + 2,
8118 GNUNET_i2s (&path[i + 2]));
8119 iret = learn_dv_path (path,
8120 i + 3,
8124 if (GNUNET_SYSERR == iret)
8125 {
8126 /* path invalid or too long to be interesting for US, thus should also
8127 not be interesting to our neighbours, cut path when forwarding to
8128 'i' hops, except of course for the one that goes back to the
8129 initiator */
8131 "# DV learn not forwarded due invalidity of path",
8132 1,
8133 GNUNET_NO);
8134 do_fwd = GNUNET_NO;
8135 break;
8136 }
8137 if ((GNUNET_NO == iret) && (nhops == i + 1))
8138 {
8139 /* we have better paths, and this is the longest target,
8140 so there cannot be anything interesting later */
8142 "# DV learn not forwarded, got better paths",
8143 1,
8144 GNUNET_NO);
8145 do_fwd = GNUNET_NO;
8146 break;
8147 }
8148 }
8149 }
8150 if (MAX_DV_HOPS_ALLOWED == nhops)
8151 {
8152 /* At limit, we're out of here! */
8153 return;
8154 }
8155
8156 /* Forward to initiator, if path non-trivial and possible */
8157 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8158 did_initiator = GNUNET_NO;
8159 if ((1 <= nhops) &&
8160 (GNUNET_YES ==
8162 {
8163 /* send back to origin! */
8165 "Sending DVL back to initiator %s\n",
8166 GNUNET_i2s (&dvl->initiator));
8167 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8168 did_initiator = GNUNET_YES;
8169 }
8170 /* We forward under two conditions: either we still learned something
8171 ourselves (do_fwd), or the path was darn short and thus the initiator is
8172 likely to still be very interested in this (and we did NOT already
8173 send it back to the initiator) */
8174 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8175 (GNUNET_NO == did_initiator)))
8176 {
8177 /* Pick random neighbours that are not yet on the path */
8178 struct NeighbourSelectionContext nsc;
8179 unsigned int n_cnt;
8180
8182 nsc.nhops = nhops;
8183 nsc.dvl = dvl;
8184 nsc.bi_history = bi_history;
8185 nsc.hops = hops;
8186 nsc.in_time = in_time;
8187 nsc.num_eligible = 0;
8190 &nsc);
8191 if (0 == nsc.num_eligible)
8192 return; /* done here, cannot forward to anyone else */
8194 nsc.num_selections =
8197 "Forwarding DVL to %u other peers\n",
8198 nsc.num_selections);
8199 for (unsigned int i = 0; i < nsc.num_selections; i++)
8200 nsc.selections[i] =
8201 (nsc.num_selections == n_cnt)
8202 ? i /* all were selected, avoid collisions by chance */
8204 nsc.num_eligible = 0;
8207 &nsc);
8208 }
8209}
8210
8211
8219static int
8220check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8221{
8222 uint16_t size = ntohs (dvb->header.size);
8223 uint16_t num_hops = ntohs (dvb->num_hops);
8224 const struct GNUNET_PeerIdentity *hops =
8225 (const struct GNUNET_PeerIdentity *) &dvb[1];
8226
8227 (void) cls;
8228 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8229 + sizeof(struct GNUNET_MessageHeader))
8230 {
8231 GNUNET_break_op (0);
8232 return GNUNET_SYSERR;
8233 }
8234 /* This peer must not be on the path */
8235 for (unsigned int i = 0; i < num_hops; i++)
8236 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8237 {
8238 GNUNET_break_op (0);
8239 return GNUNET_SYSERR;
8240 }
8241 return GNUNET_YES;
8242}
8243
8244
8257static void
8258forward_dv_box (struct Neighbour *next_hop,
8259 struct TransportDVBoxMessage *hdr,
8260 uint16_t total_hops,
8261 uint16_t num_hops,
8262 const struct GNUNET_PeerIdentity *hops,
8263 const void *enc_payload,
8264 uint16_t enc_payload_size)
8265{
8266 struct VirtualLink *vl = next_hop->vl;
8267 struct PendingMessage *pm;
8268 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8269 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8270 + enc_payload_size;
8271 char *buf;
8272 char msg_buf[msg_size] GNUNET_ALIGN;
8273 struct GNUNET_PeerIdentity *dhops;
8274
8275 hdr->num_hops = htons (num_hops);
8276 hdr->total_hops = htons (total_hops);
8277 hdr->header.size = htons (msg_size);
8278 memcpy (msg_buf, hdr, sizeof(*hdr));
8279 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8281 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8282 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8283
8284 if (GNUNET_YES == ntohs (hdr->without_fc))
8285 {
8287 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8288 enc_payload_size,
8289 GNUNET_i2s (&next_hop->pid),
8290 (unsigned int) num_hops,
8291 (unsigned int) total_hops);
8292 route_via_neighbour (next_hop, (const struct
8293 GNUNET_MessageHeader *) msg_buf,
8295 }
8296 else
8297 {
8298 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8300 "2 created pm %p storing vl %p \n",
8301 pm,
8302 vl);
8303 pm->pmt = PMT_DV_BOX;
8304 pm->vl = vl;
8305 pm->target = next_hop->pid;
8307 pm->logging_uuid = logging_uuid_gen++;
8309 pm->bytes_msg = msg_size;
8310 buf = (char *) &pm[1];
8311 memcpy (buf, msg_buf, msg_size);
8312
8314 "Created pending message %" PRIu64
8315 " for DV Box with next hop %s (%u/%u)\n",
8316 pm->logging_uuid,
8317 GNUNET_i2s (&next_hop->pid),
8318 (unsigned int) num_hops,
8319 (unsigned int) total_hops);
8320
8321 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8322 {
8324 vl->pending_msg_head,
8325 vl->pending_msg_tail,
8326 pm);
8327
8329 }
8330 else
8331 {
8333 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8334
8336 {
8338
8339 GNUNET_free (pm_old);
8340 }
8343 {
8346 }
8347 else
8349
8351 "%u items stored in DV ring buffer\n",
8354 }
8355 }
8356}
8357
8358
8364static void
8366{
8367 if (NULL != b->get)
8368 {
8370 b->get = NULL;
8371 GNUNET_assert (NULL != b->cmc);
8373 b->cmc = NULL;
8374 }
8375 if (NULL != b->task)
8376 {
8378 b->task = NULL;
8379 }
8380 if (NULL != b->sc)
8381 {
8383 "store cancel\n");
8385 b->sc = NULL;
8386 }
8388 "Removing backtalker for %s\n",
8389 GNUNET_i2s (&b->pid));
8391 GNUNET_YES ==
8393 GNUNET_free (b);
8394}
8395
8396
8405static int
8407 const struct GNUNET_PeerIdentity *pid,
8408 void *value)
8409{
8410 struct Backtalker *b = value;
8411
8412 (void) cls;
8413 (void) pid;
8414 free_backtalker (b);
8415 return GNUNET_OK;
8416}
8417
8418
8424static void
8426{
8427 struct Backtalker *b = cls;
8428
8430 "backtalker timeout.\n");
8431 b->task = NULL;
8433 {
8435 return;
8436 }
8437 GNUNET_assert (NULL == b->sc);
8438 free_backtalker (b);
8439}
8440
8441
8450static void
8452 const struct GNUNET_PEERSTORE_Record *record,
8453 const char *emsg)
8454{
8455 struct Backtalker *b = cls;
8456 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8457 struct GNUNET_TIME_Absolute mt;
8458
8459 (void) emsg;
8460 if (NULL == record)
8461 {
8462 /* we're done with #backtalker_monotime_cb() invocations,
8463 continue normal processing */
8464 b->get = NULL;
8465 GNUNET_assert (NULL != b->cmc);
8466 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8467 if (0 != b->body_size)
8469 else
8471 b->cmc = NULL;
8472 return;
8473 }
8474 if (sizeof(*mtbe) != record->value_size)
8475 {
8477 GNUNET_break (0);
8478 return;
8479 }
8480 mtbe = record->value;
8481 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8483 {
8485 "Backtalker message from %s dropped, monotime in the past\n",
8486 GNUNET_i2s (&b->pid));
8488 GST_stats,
8489 "# Backchannel messages dropped: monotonic time not increasing",
8490 1,
8491 GNUNET_NO);
8492 b->monotonic_time = mt;
8493 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8494 */
8495 b->body_size = 0;
8496 }
8498}
8499
8500
8508static void
8509backtalker_monotime_store_cb (void *cls, int success)
8510{
8511 struct Backtalker *b = cls;
8512
8513 if (GNUNET_OK != success)
8514 {
8516 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8517 }
8518 b->sc = NULL;
8519 if (NULL != b->task)
8520 {
8522 b->task = NULL;
8523 }
8525}
8526
8527
8533static void
8535{
8536 struct GNUNET_TIME_AbsoluteNBO mtbe;
8537
8538 if (NULL != b->sc)
8539 {
8541 "store cancel before store with sc %p\n",
8542 b->sc);
8543 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8544 b->sc = NULL;*/
8546 "store cancel before store with sc %p is null\n",
8547 b->sc);
8548 }
8549 else
8550 {
8552 b->task = NULL;
8553 }
8555 b->sc =
8557 "transport",
8558 &b->pid,
8560 &mtbe,
8561 sizeof(mtbe),
8565 b);
8566}
8567
8568
8576static void
8577handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8578{
8579 struct CommunicatorMessageContext *cmc = cls;
8580 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
8581 uint16_t num_hops = ntohs (dvb->num_hops);
8582 const struct GNUNET_PeerIdentity *hops =
8583 (const struct GNUNET_PeerIdentity *) &dvb[1];
8584 const char *enc_payload = (const char *) &hops[num_hops];
8585 uint16_t enc_payload_size =
8586 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
8587 struct DVKeyState key;
8588 struct GNUNET_HashCode hmac;
8589 const char *hdr;
8590 size_t hdr_len;
8591
8592 if (GNUNET_EXTRA_LOGGING > 0)
8593 {
8594 char *path;
8595
8597 for (unsigned int i = 0; i < num_hops; i++)
8598 {
8599 char *tmp;
8600
8601 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
8602 GNUNET_free (path);
8603 path = tmp;
8604 }
8606 "Received DVBox with remaining path %s\n",
8607 path);
8608 GNUNET_free (path);
8609 }
8610
8611 if (num_hops > 0)
8612 {
8613 /* We're trying from the end of the hops array, as we may be
8614 able to find a shortcut unknown to the origin that way */
8615 for (int i = num_hops - 1; i >= 0; i--)
8616 {
8617 struct Neighbour *n;
8618
8619 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8620 {
8621 GNUNET_break_op (0);
8622 finish_cmc_handling (cmc);
8623 return;
8624 }
8625 n = lookup_neighbour (&hops[i]);
8626 if (NULL == n)
8627 continue;
8629 "Skipping %u/%u hops ahead while routing DV Box\n",
8630 i,
8631 num_hops);
8632
8633 forward_dv_box (n,
8634 (struct TransportDVBoxMessage *) dvb,
8635 ntohs (dvb->total_hops) + 1,
8636 num_hops - i - 1, /* number of hops left */
8637 &hops[i + 1], /* remaining hops */
8638 enc_payload,
8639 enc_payload_size);
8641 "# DV hops skipped routing boxes",
8642 i,
8643 GNUNET_NO);
8645 "# DV boxes routed (total)",
8646 1,
8647 GNUNET_NO);
8648 finish_cmc_handling (cmc);
8649 return;
8650 }
8651 /* Woopsie, next hop not in neighbours, drop! */
8653 "# DV Boxes dropped: next hop unknown",
8654 1,
8655 GNUNET_NO);
8656 finish_cmc_handling (cmc);
8657 return;
8658 }
8659 /* We are the target. Unbox and handle message. */
8661 "# DV boxes opened (ultimate target)",
8662 1,
8663 GNUNET_NO);
8664 cmc->total_hops = ntohs (dvb->total_hops);
8665
8666 // DH key derivation with received DV, could be garbage.
8667 struct GNUNET_HashCode km;
8668
8670 &dvb->ephemeral_key,
8671 &km))
8672 {
8673 GNUNET_break_op (0);
8674 finish_cmc_handling (cmc);
8675 return;
8676 }
8677 dv_setup_key_state_from_km (&km, &dvb->iv, &key);
8678 hdr = (const char *) &dvb[1];
8679 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8681 * ntohs (dvb->total_hops);
8682
8683 dv_hmac (&key, &hmac, hdr, hdr_len);
8684 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
8685 {
8686 /* HMAC mismatch, discard! */
8687 GNUNET_break_op (0);
8688 finish_cmc_handling (cmc);
8689 return;
8690 }
8691 /* begin actual decryption */
8692 {
8693 struct Backtalker *b;
8694 struct GNUNET_TIME_Absolute monotime;
8695 struct TransportDVBoxPayloadP ppay;
8696 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
8697 const struct GNUNET_MessageHeader *mh;
8698
8699 GNUNET_assert (hdr_len >=
8700 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
8701 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
8702 {
8704 "Error decrypting DV payload header\n");
8705 GNUNET_break_op (0);
8706 finish_cmc_handling (cmc);
8707 return;
8708 }
8709 if (GNUNET_OK != dv_decrypt (&key, body,
8710 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
8711 {
8713 "Error decrypting DV payload\n");
8714 GNUNET_break_op (0);
8715 finish_cmc_handling (cmc);
8716 return;
8717 }
8718 mh = (const struct GNUNET_MessageHeader *) body;
8719 dv_key_clean (&key);
8720 if (ntohs (mh->size) != sizeof(body))
8721 {
8722 GNUNET_break_op (0);
8723 finish_cmc_handling (cmc);
8724 return;
8725 }
8726 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
8727 switch (ntohs (mh->type))
8728 {
8730 GNUNET_break_op (0);
8731 finish_cmc_handling (cmc);
8732 return;
8733
8735 GNUNET_break_op (0);
8736 finish_cmc_handling (cmc);
8737 return;
8738
8739 default:
8740 /* permitted, continue */
8741 break;
8742 }
8743 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
8745 "Decrypted backtalk from %s\n",
8746 GNUNET_i2s (&ppay.sender));
8748 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
8749 {
8751 GST_stats,
8752 "# Backchannel messages dropped: monotonic time not increasing",
8753 1,
8754 GNUNET_NO);
8755 finish_cmc_handling (cmc);
8756 return;
8757 }
8758 if ((NULL == b) ||
8759 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
8760 {
8761 /* Check signature */
8762 struct EphemeralConfirmationPS ec;
8763
8766 ec.ephemeral_key = dvb->ephemeral_key;
8767 ec.purpose.size = htonl (sizeof(ec));
8769 if (
8770 GNUNET_OK !=
8773 &ec,
8774 &ppay.sender_sig,
8775 &ppay.sender.public_key))
8776 {
8777 /* Signature invalid, discard! */
8778 GNUNET_break_op (0);
8779 finish_cmc_handling (cmc);
8780 return;
8781 }
8782 }
8783 /* Update sender, we now know the real origin! */
8785 "DVBox received for me from %s via %s\n",
8786 GNUNET_i2s2 (&ppay.sender),
8787 GNUNET_i2s (&cmc->im.sender));
8788 cmc->im.sender = ppay.sender;
8789
8790 if (NULL != b)
8791 {
8792 /* update key cache and mono time */
8793 b->last_ephemeral = dvb->ephemeral_key;
8794 b->monotonic_time = monotime;
8796 b->timeout =
8798 cmc->mh = mh;
8800 return;
8801 }
8802 /* setup data structure to cache signature AND check
8803 monotonic time with PEERSTORE before forwarding backchannel payload */
8804 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
8805 b->pid = ppay.sender;
8806 b->body_size = sizeof(body);
8807 memcpy (&b[1], body, sizeof(body));
8811 &b->pid,
8812 b,
8814 b->monotonic_time = monotime; /* NOTE: to be checked still! */
8815 b->cmc = cmc;
8816 b->timeout =
8819 b->get =
8821 "transport",
8822 &b->pid,
8825 b);
8826 } /* end actual decryption */
8827}
8828
8829
8837static int
8839 const struct GNUNET_TRANSPORT_IncomingMessage *im)
8840{
8841 struct TransportClient *tc = cls;
8842
8843 if (CT_COMMUNICATOR != tc->type)
8844 {
8845 GNUNET_break (0);
8846 return GNUNET_SYSERR;
8847 }
8849 return GNUNET_OK;
8850}
8851
8852
8857{
8861 const char *address;
8862
8867};
8868
8869
8879static int
8881 const struct GNUNET_PeerIdentity *pid,
8882 void *value)
8883{
8884 struct CheckKnownAddressContext *ckac = cls;
8885 struct ValidationState *vs = value;
8886
8887 (void) pid;
8888 if (0 != strcmp (vs->address, ckac->address))
8889 return GNUNET_OK;
8890 ckac->vs = vs;
8891 return GNUNET_NO;
8892}
8893
8894
8900static void
8901validation_start_cb (void *cls);
8902
8903
8911static void
8913 struct GNUNET_TIME_Absolute new_time)
8914{
8916
8917 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
8918 return; /* be lazy */
8919 vs->next_challenge = new_time;
8920 if (NULL == vs->hn)
8921 vs->hn =
8923 else
8926 (NULL != validation_task))
8927 return;
8928 if (NULL != validation_task)
8930 /* randomize a bit */
8933 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
8934 new_time = GNUNET_TIME_absolute_add (new_time, delta);
8937}
8938
8939
8946static void
8948 const char *address)
8949{
8950 struct GNUNET_TIME_Absolute now;
8951 struct ValidationState *vs;
8952 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
8953
8955 pid,
8957 &ckac);
8958 if (NULL != (vs = ckac.vs))
8959 {
8960 /* if 'vs' is not currently valid, we need to speed up retrying the
8961 * validation */
8962 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
8963 {
8964 /* reduce backoff as we got a fresh advertisement */
8965 vs->challenge_backoff =
8968 vs->challenge_backoff,
8969 2));
8972 vs->challenge_backoff));
8973 }
8974 return;
8975 }
8977 vs = GNUNET_new (struct ValidationState);
8978 vs->pid = *pid;
8979 vs->valid_until =
8981 vs->first_challenge_use = now;
8982 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
8984 &vs->challenge,
8985 sizeof(vs->challenge));
8986 vs->address = GNUNET_strdup (address);
8987 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
8989 "Starting address validation `%s' of peer %s using challenge %s\n",
8990 address,
8991 GNUNET_i2s (pid),
8992 GNUNET_sh2s (&vs->challenge.value));
8996 &vs->pid,
8997 vs,
9000}
9001
9002
9003static struct Queue *
9004find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9005
9006
9007static void
9008suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9009
9010
9011static void
9013 const struct GNUNET_PeerIdentity *pid,
9014 const char *uri)
9015{
9016 (void) cls;
9017 struct Queue *q;
9018 int pfx_len;
9019 const char *eou;
9020 char *address;
9021
9022 eou = strstr (uri,
9023 "://");
9024 pfx_len = eou - uri;
9025 eou += 3;
9027 "%.*s-%s",
9028 pfx_len,
9029 uri,
9030 eou);
9031
9033 "helo for client %s\n",
9034 address);
9035 q = find_queue (pid, address);
9036 if (NULL == q)
9037 {
9039 }
9040 else
9043}
9044
9045
9053static void
9055 const struct GNUNET_PEERSTORE_Record *record,
9056 const char *emsg)
9057{
9058 struct IncomingRequest *ir = cls;
9060 struct GNUNET_MessageHeader *hello;
9061
9062 if (NULL != emsg)
9063 {
9065 "Got failure from PEERSTORE: %s\n",
9066 emsg);
9067 return;
9068 }
9069 hello = record->value;
9070 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
9071 {
9073 return;
9074 }
9078 NULL);
9080}
9081
9082
9083static void
9085{
9087 "Error in PEERSTORE monitoring\n");
9088}
9089
9090
9091static void
9093{
9095 "Done with initial PEERSTORE iteration during monitoring\n");
9096}
9097
9098
9107static void
9109 void *cls,
9110 const struct TransportValidationChallengeMessage *tvc)
9111{
9112 struct CommunicatorMessageContext *cmc = cls;
9114 struct VirtualLink *vl;
9115 struct GNUNET_TIME_RelativeNBO validity_duration;
9116 struct IncomingRequest *ir;
9117 struct Neighbour *n;
9118 struct GNUNET_PeerIdentity sender;
9119
9120 /* DV-routed messages are not allowed for validation challenges */
9121 if (cmc->total_hops > 0)
9122 {
9123 GNUNET_break_op (0);
9124 finish_cmc_handling (cmc);
9125 return;
9126 }
9127 validity_duration = cmc->im.expected_address_validity;
9129 "Received address validation challenge %s\n",
9130 GNUNET_sh2s (&tvc->challenge.value));
9131 /* If we have a virtual link, we use this mechanism to signal the
9132 size of the flow control window, and to allow the sender
9133 to ask for increases. If for us the virtual link is still down,
9134 we will always give a window size of zero. */
9135 tvr.header.type =
9137 tvr.header.size = htons (sizeof(tvr));
9138 tvr.reserved = htonl (0);
9139 tvr.challenge = tvc->challenge;
9140 tvr.origin_time = tvc->sender_time;
9141 tvr.validity_duration = validity_duration;
9142 {
9143 /* create signature */
9144 struct TransportValidationPS tvp = {
9146 .purpose.size = htonl (sizeof(tvp)),
9147 .validity_duration = validity_duration,
9148 .challenge = tvc->challenge
9149 };
9150
9152 &tvp,
9153 &tvr.signature);
9154 }
9155 sender = cmc->im.sender;
9156 vl = lookup_virtual_link (&sender);
9157 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9158 {
9159 // route_control_message_without_fc (&cmc->im.sender,
9161 &tvr.header,
9163 }
9164 else
9165 {
9166 /* Use route via neighbour */
9167 n = lookup_neighbour (&sender);
9168 if (NULL != n)
9169 route_via_neighbour (n, &tvr.header,
9172 }
9173
9174 finish_cmc_handling (cmc);
9175 if (NULL != vl)
9176 return;
9177
9178 /* For us, the link is still down, but we need bi-directional
9179 connections (for flow-control and for this to be useful for
9180 CORE), so we must try to bring the link up! */
9181
9182 /* (1) Check existing queues, if any, we may be lucky! */
9183 n = lookup_neighbour (&sender);
9184 if (NULL != n)
9185 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9186 start_address_validation (&sender, q->address);
9187 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9188 we could use */
9189 for (ir = ir_head; NULL != ir; ir = ir->next)
9190 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9191 return;
9192 /* we are already trying */
9193 ir = GNUNET_new (struct IncomingRequest);
9194 ir->pid = sender;
9196
9198 GNUNET_YES,
9199 "peerstore",
9200 NULL,
9203 NULL,
9205 NULL,
9207 ir);
9208 ir_total++;
9209 /* Bound attempts we do in parallel here, might otherwise get excessive */
9212}
9213
9214
9219{
9224
9229};
9230
9231
9241static int
9243 const struct GNUNET_PeerIdentity *pid,
9244 void *value)
9245{
9246 struct CheckKnownChallengeContext *ckac = cls;
9247 struct ValidationState *vs = value;
9248
9249 (void) pid;
9250 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9251 return GNUNET_OK;
9252 ckac->vs = vs;
9253 return GNUNET_NO;
9254}
9255
9256
9264static void
9265peerstore_store_validation_cb (void *cls, int success)
9266{
9267 struct ValidationState *vs = cls;
9268
9269 vs->sc = NULL;
9270 if (GNUNET_YES == success)
9271 return;
9273 "# Peerstore failed to store foreign address",
9274 1,
9275 GNUNET_NO);
9276}
9277
9278
9286static struct Queue *
9287find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9288{
9289 struct Neighbour *n;
9290
9291 n = lookup_neighbour (pid);
9292 if (NULL == n)
9293 return NULL;
9294 for (struct Queue *pos = n->queue_head; NULL != pos;
9295 pos = pos->next_neighbour)
9296 {
9297 if (0 == strcmp (pos->address, address))
9298 return pos;
9299 }
9300 return NULL;
9301}
9302
9303
9304static void
9306
9307static void
9309{
9310 struct ValidationState *vs = cls;
9311 struct Queue *q;
9312 struct GNUNET_TIME_Absolute now;
9313
9314 vs->revalidation_task = NULL;
9315 q = find_queue (&vs->pid, vs->address);
9316 if (NULL == q)
9317 {
9318 now = GNUNET_TIME_absolute_get ();
9319 vs->awaiting_queue = GNUNET_YES;
9320 suggest_to_connect (&vs->pid, vs->address);
9322 }
9323 else
9325}
9326
9327
9328static enum GNUNET_GenericReturnValue
9330 void *cls,
9331 const struct GNUNET_HashCode *key,
9332 void *value)
9333{
9334 (void) cls;
9336 "Key in revalidate map %s \n",
9337 GNUNET_h2s (key));
9338 return GNUNET_YES;
9339}
9340
9341
9350static void
9352 void *cls,
9353 const struct TransportValidationResponseMessage *tvr)
9354{
9355 struct CommunicatorMessageContext *cmc = cls;
9356 struct ValidationState *vs;
9357 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9358 .vs = NULL};
9359 struct GNUNET_TIME_Absolute origin_time;
9360 struct Queue *q;
9361 struct Neighbour *n;
9362 struct VirtualLink *vl;
9364 GST_cfg);
9365
9366 /* check this is one of our challenges */
9368 &cmc->im.sender,
9370 &ckac);
9371 if (NULL == (vs = ckac.vs))
9372 {
9373 /* This can happen simply if we 'forgot' the challenge by now,
9374 i.e. because we received the validation response twice */
9376 "# Validations dropped, challenge unknown",
9377 1,
9378 GNUNET_NO);
9380 "Validation response %s dropped, challenge unknown\n",
9381 GNUNET_sh2s (&tvr->challenge.value));
9382 finish_cmc_handling (cmc);
9383 return;
9384 }
9385
9386 /* sanity check on origin time */
9387 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9388 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9389 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9390 {
9392 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9393 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9394 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9395 GNUNET_break_op (0);
9396 finish_cmc_handling (cmc);
9397 return;
9398 }
9399
9400 {
9401 /* check signature */
9402 struct TransportValidationPS tvp = {
9404 .purpose.size = htonl (sizeof(tvp)),
9405 .validity_duration = tvr->validity_duration,
9406 .challenge = tvr->challenge
9407 };
9408
9409 if (
9410 GNUNET_OK !=
9412 &tvp,
9413 &tvr->signature,
9414 &cmc->im.sender.public_key))
9415 {
9416 GNUNET_break_op (0);
9417 finish_cmc_handling (cmc);
9418 return;
9419 }
9420 }
9421
9422 /* validity is capped by our willingness to keep track of the
9423 validation entry and the maximum the other peer allows */
9426 tvr->validity_duration),
9428 vs->validated_until =
9432 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9433 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9435 &vs->challenge,
9436 sizeof(vs->challenge));
9437 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9438 vs->validated_until,
9439 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9441 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9442 {
9444 "First challenge use is now %" PRIu64 " %s \n",
9445 vs->first_challenge_use.abs_value_us,
9446 GNUNET_sh2s (&vs->challenge.value));
9447 vs->first_challenge_use = now;
9448 }
9449 else
9451 "First challenge use is later %" PRIu64 " %s \n",
9452 vs->first_challenge_use.abs_value_us,
9453 GNUNET_sh2s (&vs->challenge.value));
9454 vs->last_challenge_use =
9455 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
9456 update_next_challenge_time (vs, vs->first_challenge_use);
9458 "Validation response %s from %s accepted, address valid until %s\n",
9459 GNUNET_sh2s (&tvr->challenge.value),
9460 GNUNET_i2s (&cmc->im.sender),
9462 /*memcpy (&hkey,
9463 &hc,
9464 sizeof (hkey));*/
9466 "Key %s for address %s map size %u contains %u\n",
9467 GNUNET_h2s (&vs->hc),
9468 vs->address,
9471 &vs->hc));
9475 &vs->hc,
9476 vs,
9480 NULL);
9481 vs->revalidation_task =
9486 "transport",
9487 &cmc->im.sender,
9489 vs->address,
9490 strlen (vs->address) + 1,
9491 vs->valid_until,
9494 vs);
9495 finish_cmc_handling (cmc);
9496
9497 /* Finally, we now possibly have a confirmed (!) working queue,
9498 update queue status (if queue still is around) */
9499 q = find_queue (&vs->pid, vs->address);
9500 if (NULL == q)
9501 {
9503 "# Queues lost at time of successful validation",
9504 1,
9505 GNUNET_NO);
9506 return;
9507 }
9508 q->validated_until = vs->validated_until;
9509 q->pd.aged_rtt = vs->validation_rtt;
9510 n = q->neighbour;
9511 vl = lookup_virtual_link (&vs->pid);
9512 if (NULL == vl)
9513 {
9514 vl = GNUNET_new (struct VirtualLink);
9516 "Creating new virtual link %p to %s using direct neighbour!\n",
9517 vl,
9518 GNUNET_i2s (&vs->pid));
9519 vl->confirmed = GNUNET_YES;
9520 vl->message_uuid_ctr =
9522 vl->target = n->pid;
9528 links,
9529 &vl->target,
9530 vl,
9532 vl->n = n;
9533 n->vl = vl;
9534 q->idle = GNUNET_YES;
9535 vl->visibility_task =
9536 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9538 /* We lacked a confirmed connection to the target
9539 before, so tell CORE about it (finally!) */
9542 }
9543 else
9544 {
9545 /* Link was already up, remember n is also now available and we are done */
9546 if (NULL == vl->n)
9547 {
9548 vl->n = n;
9549 n->vl = vl;
9550 if (GNUNET_YES == vl->confirmed)
9552 "Virtual link to %s could now also use direct neighbour!\n",
9553 GNUNET_i2s (&vs->pid));
9554 }
9555 else
9556 {
9557 GNUNET_assert (n == vl->n);
9558 }
9559 if (GNUNET_NO == vl->confirmed)
9560 {
9561 vl->confirmed = GNUNET_YES;
9562 q->idle = GNUNET_YES;
9563 vl->visibility_task =
9564 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9566 /* We lacked a confirmed connection to the target
9567 before, so tell CORE about it (finally!) */
9570 }
9571 }
9572}
9573
9574
9580static void
9582 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9583{
9584 struct TransportClient *tc = cls;
9585 struct CommunicatorMessageContext *cmc =
9587
9588 cmc->tc = tc;
9589 cmc->im = *im;
9591 "Received message with size %u and flow control id %" PRIu64
9592 " via communicator from peer %s\n",
9593 ntohs (im->header.size),
9594 im->fc_id,
9595 GNUNET_i2s (&im->sender));
9596 cmc->im.neighbour_sender = cmc->im.sender;
9597 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
9599}
9600
9609static int
9611{
9612 (void) cls;
9613 struct TransportGlobalNattedAddress *addresses = (struct TransportGlobalNattedAddress *) &fc[1];
9614 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
9615
9617 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %u second struct %u\n",
9618 ntohs (fc->header.size),
9619 ntohl (fc->size_of_addresses),
9620 ntohl (fc->number_of_addresses),
9621 sizeof(struct TransportFlowControlMessage),
9622 sizeof (struct TransportGlobalNattedAddress));
9623
9624 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct TransportFlowControlMessage) + ntohl (fc->number_of_addresses) * sizeof (struct TransportGlobalNattedAddress) + ntohl (fc->size_of_addresses))
9625 return GNUNET_OK;
9626 else
9627 {
9628 GNUNET_break_op (0);
9629 return GNUNET_SYSERR;
9630 }
9631}
9632
9641static void
9643{
9644 struct CommunicatorMessageContext *cmc = cls;
9645 struct VirtualLink *vl;
9646 uint32_t seq;
9647 struct GNUNET_TIME_Absolute st;
9648 uint64_t os;
9649 uint64_t wnd;
9650 uint32_t random;
9651
9653 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
9654 vl = lookup_virtual_link (&cmc->im.sender);
9655 if (NULL == vl)
9656 {
9657 vl = GNUNET_new (struct VirtualLink);
9659 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
9660 vl,
9661 GNUNET_i2s (&cmc->im.sender));
9662 vl->confirmed = GNUNET_NO;
9663 vl->message_uuid_ctr =
9665 vl->target = cmc->im.sender;
9671 links,
9672 &vl->target,
9673 vl,
9675 }
9676 if (0 != ntohl (fc->number_of_addresses))
9677 {
9678 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
9679 const char *tgnas;
9680 unsigned int off = 0;
9681
9682 tgnas = (const char *) &fc[1];
9683
9684 for (int i = 1; i <= number_of_addresses; i++)
9685 {
9686 struct TransportGlobalNattedAddress *tgna = (struct TransportGlobalNattedAddress *) &tgnas[off];
9687 char *addr = (char *) &tgna[1];
9688 unsigned int address_length;
9689
9690 address_length = ntohl (tgna->address_length);
9691 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
9692
9694 "received address %s length %u\n",
9695 addr,
9696 ntohl (tgna->address_length));
9697
9698 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
9699 }
9700 }
9702 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
9703 {
9705 "FC dropped: Message out of order\n");
9706 /* out of order, drop */
9708 "# FC dropped: message out of order",
9709 1,
9710 GNUNET_NO);
9711 finish_cmc_handling (cmc);
9712 return;
9713 }
9714 seq = ntohl (fc->seq);
9715 if (seq < vl->last_fc_seq)
9716 {
9717 /* Wrap-around/reset of other peer; start all counters from zero */
9719 }
9720 vl->last_fc_seq = seq;
9721 vl->last_fc_timestamp = st;
9725 (int64_t) (os - vl->incoming_fc_window_size_used);
9727 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
9728 GNUNET_i2s (&vl->target),
9729 (unsigned int) seq,
9730 (unsigned long long) vl->outbound_fc_window_size,
9731 (long long) vl->incoming_fc_window_size_loss);
9734 UINT32_MAX);
9735 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
9739 != wnd) ||
9740 (0 == random
9742 {
9744 "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",
9745 (unsigned long long) wnd,
9746 (unsigned long long) vl->incoming_fc_window_size,
9747 (unsigned long long) vl->last_outbound_window_size_received,
9750 }
9751 if ((wnd == vl->incoming_fc_window_size
9755 (NULL != vl->fc_retransmit_task))
9756 {
9758 "Stopping FC retransmission to %s: peer is current at window %llu\n",
9759 GNUNET_i2s (&vl->target),
9760 (unsigned long long) wnd);
9762 vl->fc_retransmit_task = NULL;
9763 vl->fc_retransmit_count = 0;
9764 }
9766 /* FC window likely increased, check transmission possibilities! */
9768 finish_cmc_handling (cmc);
9769}
9770
9771
9779static void
9781{
9783 { GNUNET_MQ_hd_var_size (fragment_box,
9786 cmc),
9787 GNUNET_MQ_hd_var_size (reliability_box,
9790 cmc),
9791 GNUNET_MQ_hd_var_size (reliability_ack,
9794 cmc),
9795 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
9798 cmc),
9799 GNUNET_MQ_hd_var_size (dv_learn,
9802 cmc),
9803 GNUNET_MQ_hd_var_size (dv_box,
9805 struct TransportDVBoxMessage,
9806 cmc),
9807 GNUNET_MQ_hd_var_size (flow_control,
9810 cmc),
9812 validation_challenge,
9815 cmc),
9817 validation_response,
9820 cmc),
9822 int ret;
9823 const struct GNUNET_MessageHeader *msg = cmc->mh;
9824
9826 "Handling message of type %u with %u bytes\n",
9827 (unsigned int) ntohs (msg->type),
9828 (unsigned int) ntohs (msg->size));
9830 if (GNUNET_SYSERR == ret)
9831 {
9832 GNUNET_break (0);
9834 GNUNET_free (cmc);
9835 return;
9836 }
9837 if (GNUNET_NO == ret)
9838 {
9839 /* unencapsulated 'raw' message */
9840 handle_raw_message (cmc, msg);
9841 }
9842}
9843
9844
9851static int
9853 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
9854{
9855 struct TransportClient *tc = cls;
9856
9857 if (CT_COMMUNICATOR != tc->type)
9858 {
9859 GNUNET_break (0);
9860 return GNUNET_SYSERR;
9861 }
9863 return GNUNET_OK;
9864}
9865
9866
9872static void
9874{
9875 if (pm->msg_uuid_set)
9876 return;
9877 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
9878 pm->msg_uuid_set = GNUNET_YES;
9879}
9880
9881
9890static struct PendingAcknowledgement *
9892 struct DistanceVectorHop *dvh,
9893 struct PendingMessage *pm)
9894{
9895 struct PendingAcknowledgement *pa;
9896
9897 pa = GNUNET_new (struct PendingAcknowledgement);
9898 pa->queue = queue;
9899 pa->dvh = dvh;
9900 pa->pm = pm;
9901 do
9902 {
9904 &pa->ack_uuid,
9905 sizeof(pa->ack_uuid));
9906 }
9909 &pa->ack_uuid.value,
9910 pa,
9912 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
9913 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
9914 if (NULL != dvh)
9917 pa->message_size = pm->bytes_msg;
9919 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
9921 pm->logging_uuid);
9922 return pa;
9923}
9924
9925
9937static struct PendingMessage *
9939 struct DistanceVectorHop *dvh,
9940 struct PendingMessage *pm)
9941{
9942 struct PendingAcknowledgement *pa;
9943 struct PendingMessage *ff;
9944 uint16_t mtu;
9945 uint16_t msize;
9946
9947 mtu = (UINT16_MAX == queue->mtu)
9948 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
9949 : queue->mtu;
9951 "Fragmenting message <%" PRIu64
9952 "> with size %u to %s for MTU %u\n",
9953 pm->logging_uuid,
9954 pm->bytes_msg,
9955 GNUNET_i2s (&pm->vl->target),
9956 (unsigned int) mtu);
9959 "Fragmenting message %" PRIu64 " <%" PRIu64
9960 "> with size %u to %s for MTU %u\n",
9961 pm->msg_uuid.uuid,
9962 pm->logging_uuid,
9963 pm->bytes_msg,
9964 GNUNET_i2s (&pm->vl->target),
9965 (unsigned int) mtu);
9966
9967 /* This invariant is established in #handle_add_queue_message() */
9968 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
9969
9970 /* select fragment for transmission, descending the tree if it has
9971 been expanded until we are at a leaf or at a fragment that is small
9972 enough
9973 */
9974 ff = pm;
9975 msize = ff->bytes_msg;
9976
9977 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
9978 (ff->frag_off == msize) && (NULL != ff->head_frag))
9979 {
9980 ff = ff->head_frag; /* descent into fragmented fragments */
9981 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
9982 }
9983
9984 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
9985 {
9986 /* Did not yet calculate all fragments, calculate next fragment */
9987 struct PendingMessage *frag;
9988 struct TransportFragmentBoxMessage tfb;
9989 const char *orig;
9990 char *msg;
9991 uint16_t fragmax;
9992 uint16_t fragsize;
9993 uint16_t msize;
9994 uint16_t xoff = 0;
9995 pm->frag_count++;
9996
9997 orig = (const char *) &ff[1];
9998 msize = ff->bytes_msg;
9999 if (pm != ff)
10000 {
10001 const struct TransportFragmentBoxMessage *tfbo;
10002
10003 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10004 orig += sizeof(struct TransportFragmentBoxMessage);
10005 msize -= sizeof(struct TransportFragmentBoxMessage);
10006 xoff = ntohs (tfbo->frag_off);
10007 }
10008 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10009 fragsize = GNUNET_MIN (msize - ff->frag_off, fragmax);
10010 frag =
10011 GNUNET_malloc (sizeof(struct PendingMessage)
10012 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10014 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10015 frag,
10016 ff,
10017 pm->vl,
10018 pm);
10020 frag->vl = pm->vl;
10021 frag->frag_parent = ff;
10022 frag->timeout = pm->timeout;
10023 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10024 frag->pmt = PMT_FRAGMENT_BOX;
10025 msg = (char *) &frag[1];
10027 tfb.header.size =
10028 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10029 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10030 tfb.ack_uuid = pa->ack_uuid;
10031 tfb.msg_uuid = pm->msg_uuid;
10032 tfb.frag_off = htons (ff->frag_off + xoff);
10033 tfb.msg_size = htons (pm->bytes_msg);
10034 memcpy (msg, &tfb, sizeof(tfb));
10035 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10037 ff->tail_frag, frag);
10038 ff->frag_off += fragsize;
10039 ff = frag;
10040 }
10041
10042 /* Move head to the tail and return it */
10046 ff);
10050 ff);
10051
10052 return ff;
10053}
10054
10055
10068static struct PendingMessage *
10070 struct DistanceVectorHop *dvh,
10071 struct PendingMessage *pm)
10072{
10074 struct PendingAcknowledgement *pa;
10075 struct PendingMessage *bpm;
10076 char *msg;
10077
10078 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10079 return pm; /* already fragmented or reliability boxed, or control message:
10080 do nothing */
10081 if (NULL != pm->bpm)
10082 return pm->bpm; /* already computed earlier: do nothing */
10083 // TODO I guess we do not need this assertion. We might have a DLL with
10084 // fragments, because the MTU changed, and we do not need to fragment anymore.
10085 // But we should keep the fragments until message was completed, because
10086 // the MTU might change again.
10087 // GNUNET_assert (NULL == pm->head_frag);
10088 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10089 {
10090 /* failed hard */
10091 GNUNET_break (0);
10093 return NULL;
10094 }
10095
10097
10098 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10099 + pm->bytes_msg);
10101 "4 created pm %p storing vl %p from pm %p\n",
10102 bpm,
10103 pm->vl,
10104 pm);
10106 bpm->vl = pm->vl;
10107 bpm->frag_parent = pm;
10108 // Why was this needed?
10109 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10110 bpm->timeout = pm->timeout;
10112 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10115 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10116 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10117
10118 rbox.ack_uuid = pa->ack_uuid;
10119 msg = (char *) &bpm[1];
10120 memcpy (msg, &rbox, sizeof(rbox));
10121 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10122 pm->bpm = bpm;
10124 "Preparing reliability box for message <%" PRIu64
10125 "> of size %d (%d) to %s on queue %s\n",
10126 pm->logging_uuid,
10127 pm->bytes_msg,
10128 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10129 GNUNET_i2s (&pm->vl->target),
10130 queue->address);
10131 return bpm;
10132}
10133
10134
10135static void
10138{
10139 struct VirtualLink *vl = pm->vl;
10140 struct PendingMessage *pos;
10141
10142 /* re-insert sort in neighbour list */
10146 pm);
10147 pos = vl->pending_msg_tail;
10148 while ((NULL != pos) &&
10150 pos = pos->prev_vl;
10154 pos,
10155 pm);
10156}
10157
10158
10159static unsigned int
10161{
10162 struct PendingMessage *pos;
10164
10165 pos = pm->head_frag;
10166 while (NULL != pos)
10167 {
10168 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10169 GNUNET_NO == check_next_attempt_tree (pos, root))
10171 else
10172 {
10174 break;
10175 }
10176 pos = pos->next_frag;
10177 }
10178
10179 return frags_in_flight;
10180}
10181
10182
10183static void
10185{
10186 struct PendingMessage *pos;
10187
10188 pos = pm->head_frag;
10189 while (NULL != pos)
10190 {
10191 pos->frags_in_flight_round = pm->frags_in_flight_round;
10193 pos = pos->next_frag;
10194 }
10195}
10196
10197
10206static void
10209{
10210 if (NULL == pm->frag_parent)
10211 {
10212 pm->next_attempt = next_attempt;
10214 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
10215 pm->logging_uuid,
10218 }
10219 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
10220 {
10221 struct PendingMessage *root = pm->frag_parent;
10222
10223 while (NULL != root->frag_parent)
10224 root = root->frag_parent;
10226 "Next attempt for root message <%" PRIu64 "> set to %s\n",
10227 root->logging_uuid,
10229 root->next_attempt = next_attempt;
10231 }
10232 else
10233 {
10234 struct PendingMessage *root = pm->frag_parent;
10235
10236 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10237 root = root->frag_parent;
10238
10240 "frag_count next atempt %u\n",
10241 root->frag_count);
10242
10243 if (GNUNET_NO == root->frags_in_flight)
10244 {
10245 root->next_attempt = next_attempt;
10247 root->frags_in_flight_round++;
10249 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
10250 ">)set to %" PRIu64 "\n",
10251 pm->logging_uuid,
10252 root->logging_uuid,
10254 }
10255
10256 pm->next_attempt = root->next_attempt;
10257 pm->frags_in_flight_round = root->frags_in_flight_round;
10259
10260 if (root->bytes_msg == root->frag_off)
10261 root->frags_in_flight = check_next_attempt_tree (root, root);
10262 else
10264
10265 if (GNUNET_NO == root->frags_in_flight)
10266 {
10268 "We have no fragments in flight for message %" PRIu64
10269 ", reorder root! Next attempt is %" PRIu64 "\n",
10270 root->logging_uuid,
10272 if (PMT_DV_BOX == root->pmt)
10273 root = root->frag_parent;
10274 reorder_root_pm (root, root->next_attempt);
10275 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
10276 }
10277 else
10278 {
10279 double factor = ((double) root->frag_count - 1)
10280 / (double) root->frag_count;
10281 struct GNUNET_TIME_Relative s1;
10282 struct GNUNET_TIME_Relative s2;
10283 struct GNUNET_TIME_Relative plus_mean =
10286 next_attempt);
10287
10289 "frag_count %u after factor\n",
10290 root->frag_count);
10292 factor);
10293 s2 = GNUNET_TIME_relative_divide (plus,
10294 root->frag_count);
10295 plus_mean = GNUNET_TIME_relative_add (s1, s2);
10298 "We have fragments in flight for message %" PRIu64
10299 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
10300 root->logging_uuid,
10302 }
10303 }
10304}
10305
10306
10311{
10316
10321
10326
10331
10335 int frag;
10336
10340 int relb;
10341
10346
10350 unsigned int frags_in_flight;
10351
10356};
10357
10358
10370static void
10372 struct Queue *queue,
10373 struct VirtualLink *vl,
10374 struct DistanceVectorHop *dvh,
10375 size_t overhead)
10376{
10377 struct GNUNET_TIME_Absolute now;
10378
10379 now = GNUNET_TIME_absolute_get ();
10380 sc->to_early = GNUNET_NO;
10381 sc->frags_in_flight = GNUNET_NO;
10382 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
10383 pos = pos->next_vl)
10384 {
10385 size_t real_overhead = overhead;
10386 int frag;
10387 int relb;
10388
10389 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
10390 {
10392 "DV messages must not be DV-routed to next hop!\n");
10393 continue; /* DV messages must not be DV-routed to next hop! */
10394 }
10395 if (pos->next_attempt.abs_value_us > now.abs_value_us)
10396 {
10397 if (GNUNET_YES == pos->frags_in_flight)
10398 {
10399 sc->frags_in_flight = GNUNET_YES;
10401 "Fragments in flight for message %" PRIu64 "\n",
10402 pos->logging_uuid);
10403 }
10404 else
10405 {
10407 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
10408 PRIu64 "\n",
10409 pos->logging_uuid);
10410 sc->to_early = GNUNET_YES;
10411 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
10412 pos->next_attempt);
10413 continue;
10414 }
10415 // break; /* too early for all messages, they are sorted by next_attempt */
10416 }
10417 if (NULL != pos->qe)
10418 {
10420 "not eligible\n");
10421 continue; /* not eligible */
10422 }
10423 sc->consideration_counter++;
10424 /* determine if we have to fragment, if so add fragmentation
10425 overhead! */
10427 "check %" PRIu64 " for sc->best\n",
10428 pos->logging_uuid);
10429 frag = GNUNET_NO;
10430 if (((0 != queue->mtu) &&
10431 (pos->bytes_msg + real_overhead > queue->mtu)) ||
10432 (pos->bytes_msg > UINT16_MAX - sizeof(struct
10434 ||
10435 (NULL != pos->head_frag /* fragments already exist, should
10436 respect that even if MTU is UINT16_MAX for
10437 this queue */))
10438 {
10440 "fragment msg with size %u, realoverhead is %lu\n",
10441 pos->bytes_msg,
10442 real_overhead);
10443 frag = GNUNET_YES;
10444 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
10445 {
10446 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
10447 header without the ACK UUID when using a *reliable* channel! */
10448 }
10449 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10450 }
10451 /* determine if we have to reliability-box, if so add reliability box
10452 overhead */
10453 relb = GNUNET_NO;
10454 if ((GNUNET_NO == frag) &&
10455 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
10456 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
10457 {
10458 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
10459
10460 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
10461 {
10462 frag = GNUNET_YES;
10463 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10464 }
10465 else
10466 {
10467 relb = GNUNET_YES;
10468 }
10470 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
10471 pos->bytes_msg,
10472 real_overhead,
10473 queue->mtu,
10474 frag,
10475 relb);
10476 }
10477
10478 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
10479 message would beat it! */
10480 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
10481 {
10482 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
10483 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
10484 experimentally validated. There may be some huge potential for
10485 improvement here. Also, we right now only compare how well the
10486 given message fits _this_ queue, and do not consider how well other
10487 queues might suit the message. Taking other queues into consideration
10488 may further improve the result, but could also be expensive
10489 in terms of CPU time. */
10490 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
10491 long long pm_score = frag * 40 + relb * 20 + real_overhead;
10492 long long time_delta =
10493 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
10494 / 1000LL;
10495
10496 /* "time_delta" considers which message has been 'ready' for transmission
10497 for longer, if a message has a preference for low latency, increase
10498 the weight of the time_delta by 10x if it is favorable for that message */
10499 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10500 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
10501 time_delta *= 10; /* increase weight (always, both are low latency) */
10502 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10503 (time_delta > 0))
10504 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
10505 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10506 (time_delta < 0))
10507 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
10508 if (0 != queue->mtu)
10509 {
10510 /* Grant bonus if we are below MTU, larger bonus the closer we will
10511 be to the MTU */
10512 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
10513 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
10514 if (queue->mtu > real_overhead + pos->bytes_msg)
10515 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
10516 }
10517 if (sc_score + time_delta > pm_score)
10518 {
10520 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
10521 "\n",
10522 pos->logging_uuid,
10523 sc->best->logging_uuid);
10524 continue; /* sc_score larger, keep sc->best */
10525 }
10526 }
10527 sc->best = pos;
10528 sc->dvh = dvh;
10529 sc->frag = frag;
10530 sc->relb = relb;
10531 sc->real_overhead = real_overhead;
10532 }
10533}
10534
10535
10546static void
10548 struct Neighbour *next_hop,
10549 const struct GNUNET_MessageHeader *hdr,
10551{
10552 struct PendingMessageScoreContext *sc = cls;
10553 struct PendingMessage *pm = sc->best;
10554 struct PendingMessage *bpm;
10555 uint16_t bsize = ntohs (hdr->size);
10556
10557 GNUNET_assert (NULL == pm->bpm);
10558 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
10560 "5 created pm %p storing vl %p from pm %p\n",
10561 bpm,
10562 pm->vl,
10563 pm);
10565 bpm->pmt = PMT_DV_BOX;
10566 bpm->vl = pm->vl;
10567 bpm->timeout = pm->timeout;
10568 bpm->bytes_msg = bsize;
10569 bpm->frag_parent = pm;
10572 "Creating DV Box %" PRIu64 " for original message %" PRIu64
10573 " (next hop is %s)\n",
10575 pm->logging_uuid,
10576 GNUNET_i2s (&next_hop->pid));
10577 memcpy (&bpm[1], hdr, bsize);
10578 pm->bpm = bpm;
10579}
10580
10581
10597static void
10599{
10600 struct Queue *queue = cls;
10601 struct Neighbour *n = queue->neighbour;
10603 struct PendingMessage *pm;
10604
10605 queue->transmit_task = NULL;
10606 if (NULL == n->vl)
10607 {
10609 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
10610 GNUNET_i2s (&n->pid),
10611 queue->address);
10612 queue->idle = GNUNET_YES;
10613 return;
10614 }
10615 memset (&sc, 0, sizeof(sc));
10616 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
10617 if (NULL == sc.best)
10618 {
10619 /* Also look at DVH that have the n as first hop! */
10620 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
10621 dvh = dvh->next_neighbour)
10622 {
10624 queue,
10625 dvh->dv->vl,
10626 dvh,
10627 sizeof(struct GNUNET_PeerIdentity)
10628 * (1 + dvh->distance)
10629 + sizeof(struct TransportDVBoxMessage)
10630 + sizeof(struct TransportDVBoxPayloadP));
10631 }
10632 }
10633 if (NULL == sc.best)
10634 {
10635 /* no message pending, nothing to do here! */
10637 "No pending messages, queue `%s' to %s now idle\n",
10638 queue->address,
10639 GNUNET_i2s (&n->pid));
10640 if (GNUNET_YES == sc.to_early)
10641 schedule_transmit_on_queue (sc.to_early_retry_delay,
10642 queue,
10644 queue->idle = GNUNET_YES;
10645 return;
10646 }
10647 /* There is a message pending, we are certainly not idle */
10648 queue->idle = GNUNET_NO;
10649
10650 /* Given selection in `sc`, do transmission */
10651 pm = sc.best;
10653 "Selected message <%" PRIu64 ">\n",
10654 pm->logging_uuid);
10655 if (NULL != sc.dvh)
10656 {
10658 "Is this %u a DV box?\n",
10659 pm->pmt);
10660 GNUNET_assert (PMT_DV_BOX != pm->pmt);
10661 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
10662 {
10664 "Discard old box, because we have a new DV path.\n");
10665 free_pending_message (sc.best->bpm);
10666 sc.best->bpm = NULL;
10667 }
10668
10669 if (NULL == sc.best->bpm)
10670 {
10672 "encapsulate_for_dv 2\n");
10673 encapsulate_for_dv (sc.dvh->dv,
10674 1,
10675 &sc.dvh,
10676 (const struct GNUNET_MessageHeader *) &sc.best[1],
10678 &sc,
10679 RMO_NONE,
10680 GNUNET_NO);
10681 GNUNET_assert (NULL != sc.best->bpm);
10683 "%lu %lu %lu %lu %u\n",
10684 sizeof(struct GNUNET_PeerIdentity),
10685 sizeof(struct TransportDVBoxMessage),
10686 sizeof(struct TransportDVBoxPayloadP),
10687 sizeof(struct TransportFragmentBoxMessage),
10688 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
10689 sc.best->bpm->used_dvh = sc.dvh;
10690 }
10691 pm = sc.best->bpm;
10692 }
10693 if (GNUNET_YES == sc.frag)
10694 {
10695 pm = fragment_message (queue, sc.dvh, pm);
10696 if (NULL == pm)
10697 {
10699 "Fragmentation failed queue %s to %s for <%" PRIu64
10700 ">, trying again\n",
10701 queue->address,
10702 GNUNET_i2s (&n->pid),
10703 sc.best->logging_uuid);
10705 queue,
10707 return;
10708 }
10709 }
10710 else if (GNUNET_YES == sc.relb)
10711 {
10713 if (NULL == pm)
10714 {
10715 /* Reliability boxing failed, try next message... */
10716 GNUNET_log (
10718 "Reliability boxing failed queue %s to %s for <%" PRIu64
10719 ">, trying again\n",
10720 queue->address,
10721 GNUNET_i2s (&n->pid),
10722 sc.best->logging_uuid);
10724 queue,
10726 return;
10727 }
10728 }
10729
10730 /* Pass 'pm' for transission to the communicator */
10731 GNUNET_log (
10733 "Passing message <%" PRIu64
10734 "> to queue %s for peer %s (considered %u others)\n",
10735 pm->logging_uuid,
10736 queue->address,
10737 GNUNET_i2s (&n->pid),
10738 sc.consideration_counter);
10739
10740 /* Flow control: increment amount of traffic sent; if we are routing
10741 via DV (and thus the ultimate target of the pending message is for
10742 a different virtual link than the one of the queue), then we need
10743 to use up not only the window of the direct link but also the
10744 flow control window for the DV link! */
10745 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
10746
10747 if (pm->vl != queue->neighbour->vl)
10748 {
10749 /* If the virtual link of the queue differs, this better be distance
10750 vector routing! */
10751 GNUNET_assert (NULL != sc.dvh);
10752 /* If we do distance vector routing, we better not do this for a
10753 message that was itself DV-routed */
10754 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
10755 /* We use the size of the unboxed message here, to avoid counting
10756 the DV-Box header which is eaten up on the way by intermediaries */
10757 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
10758 }
10759 else
10760 {
10761 GNUNET_assert (NULL == sc.dvh);
10762 }
10763
10764 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
10765
10766 /* Check if this transmission somehow conclusively finished handing 'pm'
10767 even without any explicit ACKs */
10768 if ((PMT_CORE == pm->pmt) ||
10769 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
10770 {
10772 }
10773 else
10774 {
10775 struct GNUNET_TIME_Relative wait_duration;
10776 unsigned int wait_multiplier;
10777
10778 if (PMT_FRAGMENT_BOX == pm->pmt)
10779 {
10780 struct PendingMessage *root;
10781
10782 root = pm->frag_parent;
10783 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10784 root = root->frag_parent;
10785
10786 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
10787 / ((double) root->frag_off
10788 / (double) root->frag_count))
10789 * 4;
10790 }
10791 else
10792 {
10793 // No fragments, we use 4 RTT before retransmitting.
10794 wait_multiplier = 4;
10795 }
10796
10797 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
10798 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
10799
10801 "Wait multiplier %u\n",
10802 wait_multiplier);
10803
10804 /* Message not finished, waiting for acknowledgement.
10805 Update time by which we might retransmit 's' based on queue
10806 characteristics (i.e. RTT); it takes one RTT for the message to
10807 arrive and the ACK to come back in the best case; but the other
10808 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
10809 retransmitting.
10810
10811 OPTIMIZE: Note that in the future this heuristic should likely
10812 be improved further (measure RTT stability, consider message
10813 urgency and size when delaying ACKs, etc.) */
10814
10815 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
10816 queue->pd.aged_rtt.rel_value_us)
10817 wait_duration = queue->pd.aged_rtt;
10818 else
10819 {
10820 wait_duration = DEFAULT_ACK_WAIT_DURATION;
10821 wait_multiplier = 4;
10822 }
10825 wait_duration, wait_multiplier));
10827 wait_duration, wait_multiplier);
10829 "Waiting %s for ACK until %s\n",
10834 GNUNET_TIME_relative_multiply (wait_duration,
10835 wait_multiplier)));
10836 }
10837 /* finally, re-schedule queue transmission task itself */
10839 queue,
10841}
10842
10843
10850static void
10852 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
10853{
10854 struct TransportClient *tc = cls;
10855
10856 if (CT_COMMUNICATOR != tc->type)
10857 {
10858 GNUNET_break (0);
10860 return;
10861 }
10862 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
10863 queue = queue->next_client)
10864 {
10865 struct Neighbour *neighbour = queue->neighbour;
10866
10867 if ((ntohl (dqm->qid) != queue->qid) ||
10868 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
10869 continue;
10871 "Dropped queue %s to peer %s\n",
10872 queue->address,
10873 GNUNET_i2s (&neighbour->pid));
10874 free_queue (queue);
10876 return;
10877 }
10878 GNUNET_break (0);
10880}
10881
10882
10883static void
10885 struct TransportClient *tc)
10886{
10887 struct PendingMessage *pm;
10888
10889 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
10890 qe->queue->queue_tail,
10891 qe);
10892 qe->queue->queue_length--;
10893 tc->details.communicator.total_queue_length--;
10895 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
10896 qe->queue->address,
10897 qe->queue->qid,
10898 GNUNET_i2s (&qe->queue->neighbour->pid),
10899 qe->queue->queue_length,
10900 tc->details.communicator.total_queue_length);
10901
10902 /* if applicable, resume transmissions that waited on ACK */
10904 tc->details.communicator.total_queue_length)
10905 {
10906 /* Communicator dropped below threshold, resume all queues
10907 incident with this client! */
10909 GST_stats,
10910 "# Transmission throttled due to communicator queue limit",
10911 -1,
10912 GNUNET_NO);
10913 for (struct Queue *queue = tc->details.communicator.queue_head;
10914 NULL != queue;
10915 queue = queue->next_client)
10916 {
10918 queue,
10920 }
10921 }
10922 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
10923 {
10924 /* queue dropped below threshold; only resume this one queue */
10926 "# Transmission throttled due to queue queue limit",
10927 -1,
10928 GNUNET_NO);
10930 qe->queue,
10932 }
10933 else if (1 == qe->queue->q_capacity)
10934 {
10935 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
10937 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
10938 PRIu64 ".\n",
10939 qe->queue->qid,
10940 qe->queue->q_capacity);
10941 /* message queue has capacity; only resume this one queue */
10942 /* queue dropped below threshold; only resume this one queue */
10944 "# Transmission throttled due to message queue capacity",
10945 -1,
10946 GNUNET_NO);
10948 qe->queue,
10950 }
10951
10952 if (NULL != (pm = qe->pm))
10953 {
10954 struct VirtualLink *vl;
10955
10956 // GNUNET_assert (qe == pm->qe);
10957 pm->qe = NULL;
10958 /* If waiting for this communicator may have blocked transmission
10959 of pm on other queues for this neighbour, force schedule
10960 transmit on queue for queues of the neighbour */
10961 if (NULL == pm->frag_parent)
10962 {
10963 vl = pm->vl;
10964 if ((NULL != vl) &&
10965 (NULL != vl->pending_msg_head) &&
10966 (vl->pending_msg_head == pm))
10968 }
10969 }
10970 GNUNET_free (qe);
10971}
10972
10973
10980static void
10982 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
10983{
10984 struct TransportClient *tc = cls;
10985 struct QueueEntry *qe;
10986
10987 if (CT_COMMUNICATOR != tc->type)
10988 {
10989 GNUNET_break (0);
10991 return;
10992 }
10993
10994 /* find our queue entry matching the ACK */
10995 qe = NULL;
10997 "Looking for queue for PID %s\n",
10998 GNUNET_i2s (&sma->receiver));
10999 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11000 queue = queue->next_client)
11001 {
11002 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11003 continue;
11005 "Found PID %s\n",
11006 GNUNET_i2s (&queue->neighbour->pid));
11007
11008
11009 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11010 qep = qep->next)
11011 {
11012 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11013 sma->qid))
11014 continue;
11016 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11017 PRIu64 " Ack QID %u\n",
11018 qep->mid,
11019 queue->qid,
11020 GNUNET_ntohll (sma->mid),
11021 ntohl (sma->qid));
11022 qe = qep;
11023 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11025 "For pending message %" PRIu64 " we had retransmissions.\n",
11026 qe->pm->logging_uuid);
11027 break;
11028 }
11029 }
11030 if (NULL == qe)
11031 {
11033 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11034 GNUNET_ntohll (sma->mid),
11035 ntohl (sma->qid));
11036 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11037 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11038 /* this should never happen */
11039 // GNUNET_break (0);
11040 // GNUNET_SERVICE_client_drop (tc->client);
11042 return;
11043 }
11046}
11047
11048
11058static int
11060 const struct GNUNET_PeerIdentity *pid,
11061 void *value)
11062{
11063 struct TransportClient *tc = cls;
11064 struct Neighbour *neighbour = value;
11065
11066 GNUNET_assert (CT_MONITOR == tc->type);
11067 for (struct Queue *q = neighbour->queue_head; NULL != q;
11068 q = q->next_neighbour)
11069 {
11070 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11071 .cs = q->cs,
11072 .num_msg_pending = q->num_msg_pending,
11073 .num_bytes_pending = q->num_bytes_pending };
11074
11075 notify_monitor (tc, pid, q->address, q->nt, &me);
11076 }
11077 return GNUNET_OK;
11078}
11079
11080
11087static void
11090{
11091 struct TransportClient *tc = cls;
11092
11093 if (CT_NONE != tc->type)
11094 {
11095 GNUNET_break (0);
11097 return;
11098 }
11099 tc->type = CT_MONITOR;
11100 tc->details.monitor.peer = start->peer;
11101 tc->details.monitor.one_shot = ntohl (start->one_shot);
11105}
11106
11107
11115static struct TransportClient *
11117{
11118 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11119 {
11120 if (CT_COMMUNICATOR != tc->type)
11121 continue;
11122 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11123 return tc;
11124 }
11125 GNUNET_log (
11127 "Somone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11128 prefix);
11129 return NULL;
11130}
11131
11132
11140static void
11142{
11143 static uint32_t idgen;
11144 struct TransportClient *tc;
11145 char *prefix;
11146 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11147 struct GNUNET_MQ_Envelope *env;
11148 size_t alen;
11149
11151 if (NULL == prefix)
11152 {
11153 GNUNET_break (0); /* We got an invalid address!? */
11154 return;
11155 }
11157 if (NULL == tc)
11158 {
11160 "# Suggestions ignored due to missing communicator",
11161 1,
11162 GNUNET_NO);
11164 "Cannot connect to %s at `%s', no matching communicator present\n",
11165 GNUNET_i2s (pid),
11166 address);
11168 return;
11169 }
11170 /* forward suggestion for queue creation to communicator */
11172 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11173 (unsigned int) idgen,
11174 prefix,
11175 GNUNET_i2s (pid),
11176 address);
11178 alen = strlen (address) + 1;
11179 env =
11181 cqm->request_id = htonl (idgen++);
11182 cqm->receiver = *pid;
11183 memcpy (&cqm[1], address, alen);
11184 GNUNET_MQ_send (tc->mq, env);
11185}
11186
11187
11195static void
11197{
11199 struct GNUNET_TIME_Absolute monotonic_time;
11200
11201 if (NULL != vs->revalidation_task)
11202 {
11203 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
11204 vs->revalidation_task = NULL;
11205 }
11206 /*memcpy (&hkey,
11207 &hc,
11208 sizeof (hkey));*/
11210 "Remove key %s for address %s map size %u contains %u\n",
11211 GNUNET_h2s (&vs->hc),
11212 vs->address,
11215 &vs->hc));
11217
11219 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
11220 vs->last_challenge_use.abs_value_us)
11221 {
11222 vs->first_challenge_use = monotonic_time;
11223 }
11224 vs->last_challenge_use = monotonic_time;
11225 tvc.header.type =
11227 tvc.header.size = htons (sizeof(tvc));
11228 tvc.reserved = htonl (0);
11229 tvc.challenge = vs->challenge;
11230 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
11232 "Sending address validation challenge %s to %s\n",
11234 GNUNET_i2s (&q->neighbour->pid));
11235 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
11236}
11237
11238
11244static void
11246{
11247 struct ValidationState *vs;
11248 struct Queue *q;
11250 GST_cfg);
11251
11252 (void) cls;
11253 validation_task = NULL;
11255 /* drop validations past their expiration */
11256 while (
11257 (NULL != vs) &&
11259 {
11261 "Validation response %s cleaned up\n",
11262 GNUNET_sh2s (&vs->challenge.value));
11265 }
11266 if (NULL == vs)
11267 {
11269 "Address validation task not scheduled anymore, nothing to do\n");
11270 return; /* woopsie, no more addresses known, should only
11271 happen if we're really a lonely peer */
11272 }
11273 q = find_queue (&vs->pid, vs->address);
11274 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
11275 {
11277 "To early to start next address validation for challenge %s\n",
11278 GNUNET_sh2s (&vs->challenge.value));
11279 return;
11280 }
11281 if (NULL == q)
11282 {
11283 vs->awaiting_queue = GNUNET_YES;
11284 suggest_to_connect (&vs->pid, vs->address);
11285 }
11286 else
11288 /* Finally, reschedule next attempt */
11289 vs->challenge_backoff =
11290 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
11293 "Address validation task will run again in %s\n",
11294 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
11295 GNUNET_YES));
11298 vs->challenge_backoff));
11299}
11300
11301
11306{
11310 struct Queue *q;
11311
11315 unsigned int quality_count;
11316
11320 unsigned int num_queues;
11321
11326 unsigned int k;
11327};
11328
11329
11341static int
11343 const struct GNUNET_PeerIdentity *pid,
11344 void *value)
11345{
11346 struct QueueQualityContext *ctx = cls;
11347 struct Neighbour *n = value;
11348 int do_inc;
11349
11350 (void) pid;
11351 do_inc = GNUNET_NO;
11352 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
11353 {
11354 ctx->num_queues++;
11355 if (0 == ctx->k--)
11356 ctx->q = q;
11357 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
11358 statistics and consider those as well here? */
11359 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
11360 do_inc = GNUNET_YES;
11361 }
11362 if (GNUNET_YES == do_inc)
11363 ctx->quality_count++;
11364 return GNUNET_OK;
11365}
11366
11367
11379static void
11381{
11382 struct LearnLaunchEntry *lle;
11383 struct QueueQualityContext qqc;
11384 struct TransportDVLearnMessage dvl;
11385
11386 (void) cls;
11387 dvlearn_task = NULL;
11389 return; /* lost all connectivity, cannot do learning */
11390 qqc.quality_count = 0;
11391 qqc.num_queues = 0;
11395 &qqc);
11397 {
11398 struct GNUNET_TIME_Relative delay;
11399 unsigned int factor;
11400
11401 /* scale our retries by how far we are above the threshold */
11405 "At connection quality %u, will launch DV learn in %s\n",
11406 qqc.quality_count,
11409 return;
11410 }
11411 /* remove old entries in #dvlearn_map if it has grown too big */
11412 while (MAX_DV_LEARN_PENDING <=
11414 {
11415 lle = lle_tail;
11418 &lle->challenge.value,
11419 lle));
11421 GNUNET_free (lle);
11422 }
11423 /* setup data structure for learning */
11424 lle = GNUNET_new (struct LearnLaunchEntry);
11426 &lle->challenge,
11427 sizeof(lle->challenge));
11429 "Starting launch DV learn with challenge %s\n",
11430 GNUNET_sh2s (&lle->challenge.value));
11435 &lle->challenge.value,
11436 lle,
11439 dvl.header.size = htons (sizeof(dvl));
11440 dvl.num_hops = htons (0);
11441 dvl.bidirectional = htons (0);
11443 dvl.monotonic_time =
11445 {
11446 struct DvInitPS dvip = {
11447 .purpose.purpose = htonl (
11449 .purpose.size = htonl (sizeof(dvip)),
11450 .monotonic_time = dvl.monotonic_time,
11451 .challenge = lle->challenge
11452 };
11453
11455 &dvip,
11456 &dvl.init_sig);
11457 }
11459 dvl.challenge = lle->challenge;
11460
11461 qqc.quality_count = 0;
11463 qqc.num_queues = 0;
11464 qqc.q = NULL;
11467 &qqc);
11468 GNUNET_assert (NULL != qqc.q);
11469
11470 /* Do this as close to transmission time as possible! */
11472
11473 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
11474 /* reschedule this job, randomizing the time it runs (but no
11475 actual backoff!) */
11479 NULL);
11480}
11481
11482
11490static char *
11492{
11493 const char *colon;
11494 char *colon_rest;
11495 size_t colon_rest_length;
11496 char *address_without_port;
11497
11498 colon = strchr (address,':');
11499 colon_rest = GNUNET_strndup (address, colon - address);
11500 colon_rest_length = strlen (colon_rest);
11501 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
11502 GNUNET_free (colon_rest);
11503
11504 return address_without_port;
11505}
11506
11507
11517static int
11519 const struct GNUNET_PeerIdentity *pid,
11520 void *value)
11521{
11522 struct Queue *q = cls;
11523 struct ValidationState *vs = value;
11524 char *address_without_port_vs;
11525 char *address_without_port_q;
11526 int success = GNUNET_YES;
11527
11528 //TODO Check if this is really necessary.
11529 address_without_port_vs = get_address_without_port (vs->address);
11530 address_without_port_q = get_address_without_port (q->address);
11531
11533 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
11534 GNUNET_i2s (pid),
11535 address_without_port_vs,
11536 address_without_port_q);
11537 (void) pid;
11538 if ((GNUNET_YES == vs->awaiting_queue) &&
11539 (0 == strcmp (address_without_port_vs, address_without_port_q)))
11540 {
11541
11542 vs->awaiting_queue = GNUNET_NO;
11544 success = GNUNET_NO;
11545 }
11546
11547 GNUNET_free (address_without_port_vs);
11548 GNUNET_free (address_without_port_q);
11549 return success;
11550}
11551
11552
11561static void
11563 const struct GNUNET_PEERSTORE_Record *record,
11564 const char *emsg)
11565{
11566 struct Neighbour *n = cls;
11567 struct GNUNET_TIME_AbsoluteNBO *mtbe;
11568
11569 (void) emsg;
11570 if (NULL == record)
11571 {
11572 /* we're done with #neighbour_dv_monotime_cb() invocations,
11573 continue normal processing */
11574 n->get = NULL;
11576 return;
11577 }
11578 if (0 == record->value_size)
11579 {
11581 GNUNET_break (0);
11582 return;
11583 }
11584 mtbe = record->value;
11589}
11590
11591
11592static void
11594 const struct GNUNET_PeerIdentity *pid,
11595 const char *uri)
11596{
11597 struct Queue *queue = cls;
11598 struct Neighbour *neighbour = queue->neighbour;
11599 const char *dash;
11600 const char *slash;
11601 char *address_uri;
11602 char *prefix;
11603 char *uri_without_port;
11604 char *address_uri_without_port = get_address_without_port (queue->address);
11605
11606 slash = strrchr (uri, '/');
11607 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
11608 GNUNET_assert (NULL != slash);
11609 slash++;
11610 GNUNET_asprintf (&address_uri,
11611 "%s-%s",
11612 prefix,
11613 slash);
11614
11615 address_uri_without_port = get_address_without_port (queue->address);
11616 uri_without_port = get_address_without_port (address_uri);
11617 if (0 == strcmp (uri_without_port, address_uri_without_port))
11618 {
11619 queue->is_global_natted = GNUNET_NO;
11620 }
11621
11623 "not global natted %u %s %s %s %s %s %u\n",
11624 queue->is_global_natted,
11625 uri,
11626 queue->address,
11627 uri_without_port,
11628 address_uri_without_port,
11629 prefix,
11630 GNUNET_NO);
11632 GNUNET_free (address_uri);
11633 GNUNET_free (address_uri_without_port);
11634 GNUNET_free (uri_without_port);
11635}
11636
11637
11638static void
11640{
11642 "Error in PEERSTORE monitoring for checking global natted\n");
11643}
11644
11645
11646static void
11648{
11650 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
11651}
11652
11653
11655{
11659 char *addr;
11660
11665};
11666
11667
11668static enum GNUNET_GenericReturnValue
11670 const struct GNUNET_PeerIdentity *pid,
11671 void *value)
11672{
11673 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
11674 struct TransportGlobalNattedAddress *tgna = value;
11675 char *addr = (char *) &tgna[1];
11676
11677 if (0 == GNUNET_memcmp (addr, tgna_cls->addr))
11678 {
11679 tgna_cls->tgna = tgna;
11680 return GNUNET_NO;
11681 }
11682 return GNUNET_YES;
11683}
11684
11685
11686static void
11688 const struct GNUNET_PEERSTORE_Record *record,
11689 const char *emsg)
11690{
11691 struct Queue *queue = cls;
11692 struct Neighbour *neighbour = queue->neighbour;
11694 struct GNUNET_MessageHeader *hello;
11696 size_t address_len_without_port;
11697
11698 if (NULL != emsg)
11699 {
11701 "Got failure from PEERSTORE: %s\n",
11702 emsg);
11703 return;
11704 }
11705 if (NULL == record)
11706 {
11707 queue->mo = NULL;
11708 return;
11709 }
11710 if (0 == record->value_size)
11711 {
11713 GNUNET_break (0);
11714 return;
11715 }
11716 queue->is_global_natted = GNUNET_YES;
11717 hello = record->value;
11720 "before not global natted %u\n",
11721 queue->is_global_natted);
11724 queue);
11726 "after not global natted %u\n",
11727 queue->is_global_natted);
11729
11730 tgna_cls.addr = get_address_without_port (queue->address);
11731 address_len_without_port = strlen (tgna_cls.addr);
11733 &neighbour->pid,
11735 &tgna_cls);
11737 " tgna_cls.tgna tgna %p %u %u %u\n",
11738 tgna_cls.tgna,
11739 neighbour->size_of_global_addresses,
11740 tgna_cls.tgna->address_length,
11741 neighbour->number_of_addresses);
11742 if (0 == tgna_cls.tgna->address_length && GNUNET_YES == queue->is_global_natted)
11743 {
11744 struct TransportGlobalNattedAddress *tgna;
11745
11746 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress) + address_len_without_port);
11747 tgna->address_length = htonl (address_len_without_port);
11748 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
11750 &neighbour->pid,
11751 tgna,
11753 neighbour->number_of_addresses++;
11754 neighbour->size_of_global_addresses += address_len_without_port;
11756 "Created tgna %p\n",
11757 tgna);
11758 }
11759 else if (0 != tgna_cls.tgna->address_length && GNUNET_NO == queue->is_global_natted)
11760 {
11762 &neighbour->pid,
11763 tgna_cls.tgna);
11764 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->address_length));
11765 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length);
11766 GNUNET_assert (0 < neighbour->number_of_addresses);
11767 neighbour->number_of_addresses--;
11769 "removed tgna %p\n",
11770 tgna_cls.tgna);
11771 GNUNET_free (tgna_cls.tgna);
11772 }
11773 GNUNET_free (tgna_cls.addr);
11775}
11776
11777
11784static void
11786 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
11787{
11788 struct TransportClient *tc = cls;
11789 struct Queue *queue;
11790 struct Neighbour *neighbour;
11791 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
11792 const char *addr;
11793 uint16_t addr_len;
11794
11795 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
11796 {
11797 /* MTU so small as to be useless for transmissions,
11798 required for #fragment_message()! */
11799 GNUNET_break_op (0);
11801 return;
11802 }
11803 /* This may simply be a queue update */
11804 for (queue = tc->details.communicator.queue_head;
11805 NULL != queue;
11806 queue = queue->next_client)
11807 {
11808 validated_until = queue->validated_until;
11809 if (queue->qid != ntohl (aqm->qid))
11810 continue;
11811 break;
11812 }
11813
11814 if (NULL != queue)
11815 {
11816 neighbour = queue->neighbour;
11817 }
11818 else
11819 {
11820 neighbour = lookup_neighbour (&aqm->receiver);
11821 if (NULL == neighbour)
11822 {
11823 neighbour = GNUNET_new (struct Neighbour);
11825 neighbour->pid = aqm->receiver;
11828 neighbours,
11829 &neighbour->pid,
11830 neighbour,
11832 neighbour->get =
11834 "transport",
11835 &neighbour->pid,
11838 neighbour);
11839 }
11840 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
11841 addr = (const char *) &aqm[1];
11843 "New queue %s to %s available with QID %u and q_len %" PRIu64
11844 " and mtu %u\n",
11845 addr,
11846 GNUNET_i2s (&aqm->receiver),
11847 ntohl (aqm->qid),
11848 GNUNET_ntohll (aqm->q_len),
11849 ntohl (aqm->mtu));
11850 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
11851 queue->tc = tc;
11852 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us != validated_until.abs_value_us)
11853 {
11855 "New queue with QID %u inherit validated until\n",
11856 ntohl (aqm->qid));
11857 queue->validated_until = validated_until;
11858 }
11859 queue->address = (const char *) &queue[1];
11860 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
11861 queue->qid = ntohl (aqm->qid);
11862 queue->neighbour = neighbour;
11864 queue->unlimited_length = GNUNET_YES;
11865 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
11866 memcpy (&queue[1], addr, addr_len);
11867 /* notify monitors about new queue */
11868 {
11869 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
11870
11871 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
11872 }
11874 neighbour->queue_head,
11875 neighbour->queue_tail,
11876 queue);
11878 tc->details.communicator.queue_head,
11879 tc->details.communicator.queue_tail,
11880 queue);
11881
11882 }
11883 queue->mtu = ntohl (aqm->mtu);
11884 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
11885 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
11886 queue->idle = GNUNET_YES;
11888 GNUNET_YES,
11889 "peerstore",
11890 &neighbour->pid,
11893 NULL,
11895 NULL,
11897 queue);
11898 /* check if valdiations are waiting for the queue */
11900 &aqm->receiver))
11901 {
11904 &aqm->
11905 receiver,
11906 &
11908 queue))
11909 start_address_validation (&aqm->receiver, queue->address);
11910 }
11911 else
11912 start_address_validation (&aqm->receiver, queue->address);
11913 /* look for traffic for this queue */
11914 // TODO Check whether this makes any sense at all.
11915 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
11916 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
11917 /* might be our first queue, try launching DV learning */
11918 if (NULL == dvlearn_task)
11921}
11922
11923
11930static void
11932 const struct
11934{
11935 struct TransportClient *tc = cls;
11936 struct Queue *target_queue = NULL;
11937
11939 "Received queue update message for %u with q_len %llu and mtu %u\n",
11940 ntohl (msg->qid),
11941 (unsigned long long) GNUNET_ntohll (msg->q_len),
11942 ntohl (msg->mtu));
11943 for (target_queue = tc->details.communicator.queue_head;
11944 NULL != target_queue;
11945 target_queue = target_queue->next_client)
11946 {
11947 if (ntohl (msg->qid) == target_queue->qid)
11948 break;
11949 }
11950 if (NULL == target_queue)
11951 {
11953 "Queue to update no longer exists! Discarding update.\n");
11954 return;
11955 }
11956
11957 target_queue->nt = msg->nt;
11958 target_queue->mtu = ntohl (msg->mtu);
11959 target_queue->cs = msg->cs;
11960 target_queue->priority = ntohl (msg->priority);
11961 /* The update message indicates how many messages
11962 * the queue should be able to handle.
11963 */
11965 target_queue->unlimited_length = GNUNET_YES;
11966 else
11967 target_queue->unlimited_length = GNUNET_NO;
11968 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
11969 if (0 < target_queue->q_capacity)
11971 target_queue,
11974}
11975
11976
11984static void
11986 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
11987{
11988 struct TransportClient *tc = cls;
11989
11990 if (CT_COMMUNICATOR != tc->type)
11991 {
11992 GNUNET_break (0);
11994 return;
11995 }
11997 "# Suggestions succeeded at communicator",
11998 1,
11999 GNUNET_NO);
12001 "Request #%u for communicator to create queue succeeded\n",
12002 (unsigned int) ntohs (cqr->request_id));
12004}
12005
12006
12015static void
12017 void *cls,
12018 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12019{
12020 struct TransportClient *tc = cls;
12021
12022 if (CT_COMMUNICATOR != tc->type)
12023 {
12024 GNUNET_break (0);
12026 return;
12027 }
12029 "Request #%u for communicator to create queue failed\n",
12030 (unsigned int) ntohs (cqr->request_id));
12032 "# Suggestions failed in queue creation at communicator",
12033 1,
12034 GNUNET_NO);
12036}
12037
12038
12046static void
12048{
12049 struct TransportClient *tc = cls;
12050 struct PeerRequest *pr;
12051
12052 if (CT_APPLICATION != tc->type)
12053 {
12054 GNUNET_break (0);
12056 return;
12057 }
12058 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
12059 &msg->peer);
12060 if (NULL == pr)
12061 {
12062 GNUNET_break (0);
12064 return;
12065 }
12066 (void) stop_peer_request (tc, &pr->pid, pr);
12068}
12069
12070
12071static void
12073 const struct GNUNET_PeerIdentity *pid,
12074 const char *uri)
12075{
12076 (void) cls;
12077 struct Queue *q;
12078 int pfx_len;
12079 const char *eou;
12080 char *address;
12081
12082 eou = strstr (uri,
12083 "://");
12084 pfx_len = eou - uri;
12085 eou += 3;
12087 "%.*s-%s",
12088 pfx_len,
12089 uri,
12090 eou);
12091
12093 "hello for client %s\n",
12094 address);
12095
12096 q = find_queue (pid, address);
12097 if (NULL == q)
12098 {
12100 }
12101 else
12104}
12105
12106
12114static void
12116 const struct GNUNET_PEERSTORE_Record *record,
12117 const char *emsg)
12118{
12119 struct PeerRequest *pr = cls;
12121 struct GNUNET_MessageHeader *hello;
12122
12123 if (NULL != emsg)
12124 {
12126 "Got failure from PEERSTORE: %s\n",
12127 emsg);
12128 return;
12129 }
12130 hello = record->value;
12131 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
12132 {
12134 return;
12135 }
12139 NULL);
12141}
12142
12143
12144static void
12146{
12148 "Error in PEERSTORE monitoring\n");
12149}
12150
12151
12152static void
12154{
12156 "Done with initial PEERSTORE iteration during monitoring\n");
12157}
12158
12159
12167static void
12169{
12170 struct TransportClient *tc = cls;
12171 struct PeerRequest *pr;
12172
12173 if (CT_NONE == tc->type)
12174 {
12175 tc->type = CT_APPLICATION;
12176 tc->details.application.requests =
12178 }
12179 if (CT_APPLICATION != tc->type)
12180 {
12181 GNUNET_break (0);
12183 return;
12184 }
12186 "Client suggested we talk to %s with preference %d at rate %u\n",
12187 GNUNET_i2s (&msg->peer),
12188 (int) ntohl (msg->pk),
12189 (int) ntohl (msg->bw.value__));
12190 pr = GNUNET_new (struct PeerRequest);
12191 pr->tc = tc;
12192 pr->pid = msg->peer;
12193 pr->bw = msg->bw;
12194 pr->pk = (enum GNUNET_MQ_PriorityPreferences) ntohl (msg->pk);
12196 tc->details.application.requests,
12197 &pr->pid,
12198 pr,
12200 {
12201 GNUNET_break (0);
12202 GNUNET_free (pr);
12204 return;
12205 }
12206 pr->nc =
12208 GNUNET_YES,
12209 "peerstore",
12210 NULL,
12213 NULL,
12215 NULL,
12217 pr);
12219}
12220
12221
12230static int
12232 const struct RequestHelloValidationMessage *m)
12233{
12234 (void) cls;
12236 return GNUNET_OK;
12237}
12238
12239
12247static void
12249 const struct RequestHelloValidationMessage *m)
12250{
12251 struct TransportClient *tc = cls;
12252 struct Queue *q;
12253
12254 q = find_queue (&m->peer, (const char *) &m[1]);
12255 if (NULL == q)
12256 {
12257 suggest_to_connect (&m->peer, (const char *) &m[1]);
12258 }
12259 else
12260 start_address_validation (&m->peer, (const char *) &m[1]);
12262}
12263
12264
12273static int
12275 const struct GNUNET_PeerIdentity *pid,
12276 void *value)
12277{
12278 struct Neighbour *neighbour = value;
12279
12280 (void) cls;
12281 (void) pid;
12282 GNUNET_break (0); // should this ever happen?
12283 free_neighbour (neighbour);
12284
12285 return GNUNET_OK;
12286}
12287
12288
12297static int
12299 const struct GNUNET_PeerIdentity *pid,
12300 void *value)
12301{
12302 struct DistanceVector *dv = value;
12303
12304 (void) cls;
12305 (void) pid;
12306 free_dv_route (dv);
12307
12308 return GNUNET_OK;
12309}
12310
12311
12320static int
12322 const struct GNUNET_PeerIdentity *pid,
12323 void *value)
12324{
12325 struct ValidationState *vs = value;
12326
12327 (void) cls;
12328 (void) pid;
12330 return GNUNET_OK;
12331}
12332
12333
12342static int
12343free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
12344{
12345 struct PendingAcknowledgement *pa = value;
12346
12347 (void) cls;
12348 (void) key;
12350 return GNUNET_OK;
12351}
12352
12353
12362static int
12364 const struct GNUNET_PeerIdentity *pid,
12365 void *value)
12366{
12367 struct AcknowledgementCummulator *ac = value;
12368
12369 (void) cls;
12370 (void) pid;
12372 GNUNET_free (ac);
12373 return GNUNET_OK;
12374}
12375
12376
12383static void
12384do_shutdown (void *cls)
12385{
12386 struct LearnLaunchEntry *lle;
12387 (void) cls;
12388
12390 "shutdown logic\n");
12393 &free_neighbour_cb, NULL);
12394 if (NULL != validation_task)
12395 {
12397 validation_task = NULL;
12398 }
12399 if (NULL != dvlearn_task)
12400 {
12402 dvlearn_task = NULL;
12403 }
12404 if (NULL != GST_stats)
12405 {
12407 GST_stats = NULL;
12408 }
12409 if (NULL != GST_my_hello)
12410 {
12412 GST_my_hello = NULL;
12413 }
12414 if (NULL != GST_my_private_key)
12415 {
12417 GST_my_private_key = NULL;
12418 }
12421 NULL);
12423 ack_cummulators = NULL;
12426 NULL);
12428 pending_acks = NULL;
12431 neighbours = NULL;
12434 links = NULL;
12437 NULL);
12439 backtalkers = NULL;
12442 NULL);
12444 validation_map = NULL;
12446 revalidation_map = NULL;
12447 while (NULL != ir_head)
12449 GNUNET_assert (0 == ir_total);
12450 while (NULL != (lle = lle_head))
12451 {
12453 GNUNET_free (lle);
12454 }
12455 if (NULL != peerstore)
12456 {
12458 "Disconnecting from PEERSTORE service\n");
12460 peerstore = NULL;
12461 }
12463 dvlearn_map = NULL;
12465 validation_heap = NULL;
12468 dv_routes = NULL;
12470}
12471
12472
12473static void
12474shutdown_task (void *cls)
12475{
12477
12479 "Shutdown task executed\n");
12480 if (NULL != clients_head)
12481 {
12482 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
12483 {
12485 "client still connected: %u\n",
12486 tc->type);
12487 }
12488 }
12489 else
12490 do_shutdown (cls);
12491
12492}
12493
12494
12502static void
12503run (void *cls,
12504 const struct GNUNET_CONFIGURATION_Handle *c,
12506{
12507 (void) cls;
12508 (void) service;
12509 /* setup globals */
12512 GST_cfg = c;
12520 GNUNET_YES);
12527 if (NULL == GST_my_private_key)
12528 {
12529 GNUNET_log (
12531 _ (
12532 "Transport service is lacking key configuration settings. Exiting.\n"));
12534 return;
12535 }
12539 "My identity is `%s'\n",
12546 "transport",
12547 0,
12548 0,
12549 NULL,
12550 0,
12551 NULL,
12552 NULL,
12553 NULL);
12554 if (NULL == peerstore)
12555 {
12556 GNUNET_break (0);
12558 return;
12559 }
12560}
12561
12562
12567 "transport",
12569 &run,
12572 NULL,
12573 /* communication with applications */
12574 GNUNET_MQ_hd_fixed_size (suggest,
12577 NULL),
12578 GNUNET_MQ_hd_fixed_size (suggest_cancel,
12581 NULL),
12582 GNUNET_MQ_hd_var_size (request_hello_validation,
12585 NULL),
12586 /* communication with core */
12587 GNUNET_MQ_hd_fixed_size (client_start,
12589 struct StartMessage,
12590 NULL),
12591 GNUNET_MQ_hd_var_size (client_send,
12593 struct OutboundMessage,
12594 NULL),
12595 GNUNET_MQ_hd_fixed_size (client_recv_ok,
12597 struct RecvOkMessage,
12598 NULL),
12599 /* communication with communicators */
12600 GNUNET_MQ_hd_var_size (communicator_available,
12603 NULL),
12604 GNUNET_MQ_hd_var_size (communicator_backchannel,
12607 NULL),
12608 GNUNET_MQ_hd_var_size (add_address,
12611 NULL),
12612 GNUNET_MQ_hd_fixed_size (del_address,
12615 NULL),
12616 GNUNET_MQ_hd_var_size (incoming_msg,
12619 NULL),
12620 GNUNET_MQ_hd_fixed_size (queue_create_ok,
12623 NULL),
12624 GNUNET_MQ_hd_fixed_size (queue_create_fail,
12627 NULL),
12628 GNUNET_MQ_hd_var_size (add_queue_message,
12631 NULL),
12632 GNUNET_MQ_hd_fixed_size (update_queue_message,
12635 NULL),
12636 GNUNET_MQ_hd_fixed_size (del_queue_message,
12639 NULL),
12640 GNUNET_MQ_hd_fixed_size (send_message_ack,
12643 NULL),
12644 /* communication with monitors */
12645 GNUNET_MQ_hd_fixed_size (monitor_start,
12648 NULL),
12650
12651
12652/* 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
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:59
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 dv_setup_key_state_from_km(const struct GNUNET_HashCode *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 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 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 meessage.
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.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *c, struct GNUNET_HashCode *key_material)
Decapsulate a key for a private EdDSA key.
Definition: crypto_ecc.c:749
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:198
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_EcdhePublicKey *c, struct GNUNET_HashCode *key_material)
Encapsulate key material for a EdDSA public key.
Definition: crypto_ecc.c:794
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#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_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:70
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.
#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)
#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:304
#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:638
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition: mq.c:879
#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:727
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:484
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:2572
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2489
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2408
@ 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_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.
struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral
Last (valid) ephemeral key received from this sender.
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_PeerIdentity target
To which peer is this a route?
struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key
Our ephemeral key.
struct GNUNET_HashCode * km
Master secret for the setup of the Key material for the backchannel.
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 initator 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_CRYPTO_EcdhePublicKey ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
struct GNUNET_PeerIdentity target
Target's peer identity.
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...
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
Private ECC key encoded for transmission.
an ECC signature using EdDSA.
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.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Handle for active NAT registrations.
Definition: nat_api.c:72
Handle to the PEERSTORE service.
Definition: peerstore_api.c:46
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:252
Handle to a service.
Definition: service.c:118
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 avaliable.
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.
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 ...
struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
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.
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