GNUnet 0.22.2
gnunet-service-transport.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018, 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
75#include "platform.h"
76#include "gnunet_util_lib.h"
80#include "gnunet_nat_service.h"
82#include "gnunet_signatures.h"
83#include "transport.h"
84
88#define RING_BUFFER_SIZE 16
89
93#define MAX_FC_RETRANSMIT_COUNT 1000
94
99#define MAX_CUMMULATIVE_ACKS 64
100
113#define FC_NO_CHANGE_REPLY_PROBABILITY 8
114
119#define IN_PACKET_SIZE_WITHOUT_MTU 128
120
125#define GOODPUT_AGING_SLOTS 4
126
131#define DEFAULT_WINDOW_SIZE (128 * 1024)
132
141#define MAX_INCOMING_REQUEST 16
142
147#define MAX_DV_DISCOVERY_SELECTION 16
148
157#define RECV_WINDOW_SIZE 4
158
166#define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
167
171#define MAX_DV_HOPS_ALLOWED 16
172
177#define MAX_DV_LEARN_PENDING 64
178
182#define MAX_DV_PATHS_TO_TARGET 3
183
189#define DELAY_WARN_THRESHOLD \
190 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
191
196#define DV_FORWARD_TIMEOUT \
197 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
198
202#define DEFAULT_ACK_WAIT_DURATION \
203 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
204
210#define DV_QUALITY_RTT_THRESHOLD \
211 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
212
217#define DV_PATH_VALIDITY_TIMEOUT \
218 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
219
224#define BACKCHANNEL_INACTIVITY_TIMEOUT \
225 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
226
231#define DV_PATH_DISCOVERY_FREQUENCY \
232 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
233
237#define EPHEMERAL_VALIDITY \
238 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
239
243#define REASSEMBLY_EXPIRATION \
244 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
245
250#define FAST_VALIDATION_CHALLENGE_FREQ \
251 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
252
256#define MAX_VALIDATION_CHALLENGE_FREQ \
257 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
258
264#define ACK_CUMMULATOR_TIMEOUT \
265 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
266
271#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
272
277#define DV_LEARN_QUALITY_THRESHOLD 100
278
282#define MAX_ADDRESS_VALID_UNTIL \
283 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
284
288#define ADDRESS_VALIDATION_LIFETIME \
289 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
290
297#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
298
305#define VALIDATION_RTT_BUFFER_FACTOR 3
306
313#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
314
320#define QUEUE_LENGTH_LIMIT 32
321
325#define QUEUE_ENTRY_TIMEOUT \
326 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
327
332#define RTT_DIFF \
333 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
334
336
341{
347};
348
349
354{
359};
360
365{
370
371 /* Followed by *another* message header which is the message to
372 the communicator */
373
374 /* Followed by a 0-terminated name of the communicator */
375};
376
377
382{
387
403
408
414};
415
416
422{
427
433
445
446 /* Followed by a `struct GNUNET_MessageHeader` with a message
447 for the target peer */
448};
449
450
456{
461
469
476};
477
478
483{
491
496};
497
498
507{
512
518
519 /* followed by any number of `struct TransportCummulativeAckPayloadP`
520 messages providing ACKs */
521};
522
523
528{
533
538
543
552
558};
559
560
579{
584
598
603};
604
605
623{
628
633
638
643};
644
645
651{
656
662};
663
664
679{
684
690
700
707
721
727
732
737
738 /* Followed by @e num_hops `struct DVPathEntryP` values,
739 excluding the initiator of the DV trace; the last entry is the
740 current sender; the current peer must not be included. */
741};
742
743
767{
772
776 unsigned int without_fc;
777
785
792
798
805
812
819
820 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
821 excluding the @e origin and the current peer, the last must be
822 the ultimate target; if @e num_hops is zero, the receiver of this
823 message is the ultimate target. */
824
825 /* Followed by encrypted, variable-size payload, which
826 must begin with a `struct TransportDVBoxPayloadP` */
827
828 /* Followed by the actual message, which itself must not be a
829 a DV_LEARN or DV_BOX message! */
830};
831
832
838{
843
848
853
859};
860
861
867{
872
878
883};
884
885
891{
896
901
907
912
917 struct GNUNET_TIME_AbsoluteNBO origin_time;
918
923 struct GNUNET_TIME_RelativeNBO validity_duration;
924};
925
927{
931 unsigned int address_length;
932
933 /* Followed by @e address_length bytes of the address. */
934};
935
945{
950
959
965
972
982
992
997
1001 unsigned int sync_ready;
1002
1007
1012
1013 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1014};
1015
1017
1018
1023{
1028
1033
1038
1043
1047 CT_APPLICATION = 4
1049
1050
1056{
1061
1066
1071
1076
1082 RMO_REDUNDANT = 4
1084
1085
1090{
1095
1100
1105
1111};
1112
1113
1119{
1123 uint64_t bytes_sent;
1124
1130};
1131
1132
1137{
1142
1148
1153 unsigned int last_age;
1154};
1155
1156
1160struct TransportClient;
1161
1165struct Neighbour;
1166
1171struct DistanceVector;
1172
1177struct Queue;
1178
1182struct PendingMessage;
1183
1187struct DistanceVectorHop;
1188
1197struct VirtualLink;
1198
1199
1205{
1211
1217
1222
1227
1232
1237 uint16_t total_hops;
1238
1242 unsigned int continue_send;
1243};
1244
1245
1250{
1255
1260};
1261
1262
1267{
1272
1277
1282
1286 uint16_t size;
1287
1294 uint16_t isize;
1295};
1296
1297
1302{
1308
1313
1318
1326 uint8_t *bitfield;
1327
1332
1338
1342 uint16_t msg_size;
1343
1348 uint16_t msg_missing;
1349
1350 /* Followed by @e msg_size bytes of the (partially) defragmented original
1351 * message */
1352
1353 /* Followed by @e bitfield data */
1354};
1355
1356
1366{
1371
1378
1385
1390
1396
1402
1407
1412
1417
1422
1430
1436
1441
1446
1451
1456 unsigned int confirmed;
1457
1461 struct Neighbour *n;
1462
1467
1474
1481
1490
1496
1502
1507
1513
1522
1530
1537
1546
1559
1565
1572
1583
1588 uint32_t fc_seq_gen;
1589
1595 uint32_t last_fc_seq;
1596
1609
1614};
1615
1616
1621{
1627
1633
1640
1647
1654
1661
1668
1675
1680
1686
1692
1697 struct Queue *queue;
1698
1703
1708
1712 unsigned int num_send;
1713};
1714
1715
1720{
1725
1730
1735
1740
1745
1750
1755
1760
1767
1773
1782
1787
1793 unsigned int distance;
1794};
1795
1796
1802{
1807
1812
1817
1822
1828
1834
1839
1844
1849
1854};
1855
1856
1867{
1872
1877
1881 struct Queue *queue;
1882
1887
1891 uint64_t mid;
1892
1897};
1898
1899
1904struct Queue
1905{
1910
1915
1920
1925
1930
1935
1940
1945
1950
1955
1959 const char *address;
1960
1964 unsigned int unlimited_length;
1965
1971
1980
1985
1991
1996 uint64_t mid_gen;
1997
2001 uint32_t qid;
2002
2006 uint32_t mtu;
2007
2012
2017
2021 unsigned int queue_length;
2022
2026 uint64_t q_capacity;
2027
2031 uint32_t priority;
2032
2037
2042
2047 int idle;
2048
2053};
2054
2055
2060{
2065
2071
2077
2082
2087
2093
2099
2105
2111
2117
2122
2127
2132
2137};
2138
2139
2145{
2150
2155
2160
2165};
2166
2167
2171struct PeerRequest
2172{
2177
2182
2187
2194
2199};
2200
2201
2206{
2211
2216
2221
2225 PMT_DV_BOX = 3
2227
2228
2255struct PendingMessage
2256{
2261
2266
2271
2276
2282
2288
2293
2298
2304
2310
2315
2325
2330
2335
2340
2345
2350
2355
2361
2367
2372
2378
2383
2387 uint16_t bytes_msg;
2388
2392 uint16_t frag_off;
2393
2398
2403
2407 uint16_t frag_count;
2408
2413
2414 /* Followed by @e bytes_msg to transmit */
2415};
2416
2417
2422{
2428
2433};
2434
2435
2441{
2446
2451
2458
2463
2469 uint32_t ack_counter;
2470
2474 unsigned int num_acks;
2475};
2476
2477
2482{
2487
2492
2497
2502
2506 const char *address;
2507
2512
2517
2522
2527
2533
2537 uint32_t aid;
2538
2543};
2544
2545
2550{
2555
2560
2565
2570
2575
2576 union
2577 {
2581 struct
2582 {
2588
2594
2598 struct
2599 {
2606
2612
2613
2617 struct
2618 {
2624
2629
2634
2640
2646
2653
2658
2663
2668
2670
2674 struct
2675 {
2683};
2684
2685
2691{
2697
2705
2711
2718 struct GNUNET_TIME_Absolute first_challenge_use;
2719
2726 struct GNUNET_TIME_Absolute last_challenge_use;
2727
2735 struct GNUNET_TIME_Absolute next_challenge;
2736
2745 struct GNUNET_TIME_Relative challenge_backoff;
2746
2751 struct GNUNET_TIME_Relative validation_rtt;
2752
2760 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2761
2765 struct GNUNET_HashCode hc;
2766
2770 struct GNUNET_SCHEDULER_Task *revalidation_task;
2771
2775 char *address;
2776
2782 struct GNUNET_CONTAINER_HeapNode *hn;
2783
2789
2795 uint32_t last_window_consum_limit;
2796
2801 int awaiting_queue;
2802};
2803
2804
2812{
2817
2822
2827
2832
2838
2843
2849
2855
2861};
2862
2867
2871static unsigned int ring_buffer_head;
2872
2876static unsigned int is_ring_buffer_full;
2877
2882
2886static unsigned int ring_buffer_dv_head;
2887
2891static unsigned int is_ring_buffer_dv_full;
2892
2897
2902
2907
2912
2917
2922
2927
2933
2939
2945
2951
2957
2963
2969
2975
2980
2984static struct LearnLaunchEntry *lle_head = NULL;
2985
2989static struct LearnLaunchEntry *lle_tail = NULL;
2990
2997
3002
3007
3012
3017
3024
3029
3033static unsigned int ir_total;
3034
3038static unsigned long long logging_uuid_gen;
3039
3044
3054
3059static int in_shutdown;
3060
3065
3067
3069
3080static unsigned int
3082{
3083 struct GNUNET_TIME_Absolute now;
3084
3085 now = GNUNET_TIME_absolute_get ();
3086 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3087}
3088
3089
3095static void
3097{
3099 GNUNET_assert (ir_total > 0);
3100 ir_total--;
3101 if (NULL != ir->nc)
3103 ir->nc = NULL;
3104 GNUNET_free (ir);
3105}
3106
3107
3113static void
3115{
3116 struct Queue *q = pa->queue;
3117 struct PendingMessage *pm = pa->pm;
3118 struct DistanceVectorHop *dvh = pa->dvh;
3119
3121 "free_pending_acknowledgement\n");
3122 if (NULL != q)
3123 {
3124 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3125 pa->queue = NULL;
3126 }
3127 if (NULL != pm)
3128 {
3130 "remove pa from message\n");
3132 "remove pa from message %" PRIu64 "\n",
3133 pm->logging_uuid);
3135 "remove pa from message %u\n",
3136 pm->pmt);
3138 "remove pa from message %s\n",
3140 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3141 pa->pm = NULL;
3142 }
3143 if (NULL != dvh)
3144 {
3145 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3146 pa->queue = NULL;
3147 }
3150 &pa->ack_uuid.value,
3151 pa));
3152 GNUNET_free (pa);
3153}
3154
3155
3164static void
3166{
3167 struct PendingMessage *frag;
3168
3169 while (NULL != (frag = root->head_frag))
3170 {
3171 struct PendingAcknowledgement *pa;
3172
3173 free_fragment_tree (frag);
3174 while (NULL != (pa = frag->pa_head))
3175 {
3176 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3177 pa->pm = NULL;
3178 }
3179 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3180 if (NULL != frag->qe)
3181 {
3182 GNUNET_assert (frag == frag->qe->pm);
3183 frag->qe->pm = NULL;
3184 }
3186 "Free frag %p\n",
3187 frag);
3188 GNUNET_free (frag);
3189 }
3190}
3191
3192
3200static void
3202{
3203 struct TransportClient *tc = pm->client;
3204 struct VirtualLink *vl = pm->vl;
3205 struct PendingAcknowledgement *pa;
3206
3208 "Freeing pm %p\n",
3209 pm);
3210 if (NULL != tc)
3211 {
3213 tc->details.core.pending_msg_head,
3214 tc->details.core.pending_msg_tail,
3215 pm);
3216 }
3217 if ((NULL != vl) && (NULL == pm->frag_parent))
3218 {
3220 "Removing pm %" PRIu64 "\n",
3221 pm->logging_uuid);
3223 vl->pending_msg_head,
3224 vl->pending_msg_tail,
3225 pm);
3226 }
3227 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3228 {
3229 struct PendingMessage *root = pm->frag_parent;
3230
3231 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3232 root = root->frag_parent;
3233
3234 root->frag_count--;
3235 }
3236 while (NULL != (pa = pm->pa_head))
3237 {
3238 if (NULL == pa)
3240 "free pending pa null\n");
3241 if (NULL == pm->pa_tail)
3243 "free pending pa_tail null\n");
3244 if (NULL == pa->prev_pa)
3246 "free pending pa prev null\n");
3247 if (NULL == pa->next_pa)
3249 "free pending pa next null\n");
3250 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3251 pa->pm = NULL;
3252 }
3253
3255 if (NULL != pm->qe)
3256 {
3257 GNUNET_assert (pm == pm->qe->pm);
3258 pm->qe->pm = NULL;
3259 }
3260 if (NULL != pm->bpm)
3261 {
3262 free_fragment_tree (pm->bpm);
3263 if (NULL != pm->bpm->qe)
3264 {
3265 struct QueueEntry *qe = pm->bpm->qe;
3266
3267 qe->pm = NULL;
3268 }
3269 GNUNET_free (pm->bpm);
3270 }
3271
3272 GNUNET_free (pm);
3274 "Freeing pm done\n");
3275}
3276
3277
3283static void
3285{
3286 struct VirtualLink *vl = rc->virtual_link;
3287
3291 rc->msg_uuid.uuid,
3292 rc));
3293 GNUNET_free (rc);
3294}
3295
3296
3302static void
3304{
3305 struct VirtualLink *vl = cls;
3306 struct ReassemblyContext *rc;
3307
3308 vl->reassembly_timeout_task = NULL;
3309 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3310 {
3312 .rel_value_us)
3313 {
3315 continue;
3316 }
3321 vl);
3322 return;
3323 }
3324}
3325
3326
3335static int
3336free_reassembly_cb (void *cls, uint32_t key, void *value)
3337{
3338 struct ReassemblyContext *rc = value;
3339
3340 (void) cls;
3341 (void) key;
3343 return GNUNET_OK;
3344}
3345
3346
3352static void
3354{
3355 struct PendingMessage *pm;
3356 struct CoreSentContext *csc;
3357
3359 "free virtual link %p\n",
3360 vl);
3361
3362 if (NULL != vl->reassembly_map)
3363 {
3366 NULL);
3368 vl->reassembly_map = NULL;
3370 vl->reassembly_heap = NULL;
3371 }
3372 if (NULL != vl->reassembly_timeout_task)
3373 {
3376 }
3377 while (NULL != (pm = vl->pending_msg_head))
3381 if (NULL != vl->visibility_task)
3382 {
3384 vl->visibility_task = NULL;
3385 }
3386 if (NULL != vl->fc_retransmit_task)
3387 {
3389 vl->fc_retransmit_task = NULL;
3390 }
3391 while (NULL != (csc = vl->csc_head))
3392 {
3394 GNUNET_assert (vl == csc->vl);
3395 csc->vl = NULL;
3396 }
3397 GNUNET_break (NULL == vl->n);
3398 GNUNET_break (NULL == vl->dv);
3399 GNUNET_free (vl);
3400}
3401
3402
3408static void
3410{
3411 if (NULL != vs->revalidation_task)
3412 {
3413 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3414 vs->revalidation_task = NULL;
3415 }
3416 /*memcpy (&hkey,
3417 &hc,
3418 sizeof (hkey));*/
3420 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3421 GNUNET_h2s (&vs->hc),
3422 vs->address,
3425 &vs->hc));
3428 GNUNET_YES ==
3431 vs->hn = NULL;
3432 if (NULL != vs->sc)
3433 {
3435 "store cancel\n");
3437 vs->sc = NULL;
3438 }
3439 GNUNET_free (vs->address);
3440 GNUNET_free (vs);
3441}
3442
3443
3450static struct Neighbour *
3452{
3454}
3455
3456
3463static struct VirtualLink *
3465{
3467}
3468
3469
3474{
3481
3486
3491
3496
3501};
3502
3503
3512static void
3514{
3515 struct Neighbour *n = dvh->next_hop;
3516 struct DistanceVector *dv = dvh->dv;
3517 struct PendingAcknowledgement *pa;
3518
3519 while (NULL != (pa = dvh->pa_head))
3520 {
3522 pa->dvh = NULL;
3523 }
3524 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3526 GNUNET_free (dvh);
3527}
3528
3529
3536static void
3537check_link_down (void *cls);
3538
3539
3545static void
3547{
3549 "Informing CORE clients about disconnect from %s\n",
3550 GNUNET_i2s (pid));
3551 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3552 {
3553 struct GNUNET_MQ_Envelope *env;
3554 struct DisconnectInfoMessage *dim;
3555
3556 if (CT_CORE != tc->type)
3557 continue;
3559 dim->peer = *pid;
3560 GNUNET_MQ_send (tc->mq, env);
3561 }
3562}
3563
3564
3571static void
3573{
3574 struct DistanceVectorHop *dvh;
3575 struct VirtualLink *vl;
3576
3577 while (NULL != (dvh = dv->dv_head))
3579
3581 GNUNET_YES ==
3583 if (NULL != (vl = dv->vl))
3584 {
3585 GNUNET_assert (dv == vl->dv);
3586 vl->dv = NULL;
3587 if (NULL == vl->n)
3588 {
3590 free_virtual_link (vl);
3591 }
3592 else
3593 {
3596 }
3597 dv->vl = NULL;
3598 }
3599
3600 if (NULL != dv->timeout_task)
3601 {
3603 dv->timeout_task = NULL;
3604 }
3605 GNUNET_free (dv->km);
3606 GNUNET_free (dv);
3607}
3608
3609
3623static void
3625 const struct GNUNET_PeerIdentity *peer,
3626 const char *address,
3628 const struct MonitorEvent *me)
3629{
3630 struct GNUNET_MQ_Envelope *env;
3632 size_t addr_len = strlen (address) + 1;
3633
3635 addr_len,
3637 md->nt = htonl ((uint32_t) nt);
3638 md->peer = *peer;
3639 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3640 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3641 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3642 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3643 md->cs = htonl ((uint32_t) me->cs);
3644 md->num_msg_pending = htonl (me->num_msg_pending);
3645 md->num_bytes_pending = htonl (me->num_bytes_pending);
3646 memcpy (&md[1], address, addr_len);
3647 GNUNET_MQ_send (tc->mq, env);
3648}
3649
3650
3660static void
3662 const char *address,
3664 const struct MonitorEvent *me)
3665{
3666 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3667 {
3668 if (CT_MONITOR != tc->type)
3669 continue;
3670 if (tc->details.monitor.one_shot)
3671 continue;
3672 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3673 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3674 continue;
3676 }
3677}
3678
3679
3689static void *
3691 struct GNUNET_SERVICE_Client *client,
3692 struct GNUNET_MQ_Handle *mq)
3693{
3694 struct TransportClient *tc;
3695
3696 (void) cls;
3697 tc = GNUNET_new (struct TransportClient);
3698 tc->client = client;
3699 tc->mq = mq;
3702 "Client %p of type %u connected\n",
3703 tc,
3704 tc->type);
3705 return tc;
3706}
3707
3708
3709static enum GNUNET_GenericReturnValue
3711 const struct GNUNET_PeerIdentity *pid,
3712 void *value)
3713{
3714 struct TransportGlobalNattedAddress *tgna = value;
3715 (void) cls;
3716
3717 GNUNET_free (tgna);
3718
3719 return GNUNET_OK;
3720}
3721
3722
3729static void
3730free_neighbour (struct Neighbour *neighbour,
3731 enum GNUNET_GenericReturnValue drop_link)
3732{
3733 struct DistanceVectorHop *dvh;
3734 struct VirtualLink *vl;
3735
3736 GNUNET_assert (NULL == neighbour->queue_head);
3739 &neighbour->pid,
3740 neighbour));
3742 "Freeing neighbour\n");
3745 NULL);
3747 while (NULL != (dvh = neighbour->dv_head))
3748 {
3749 struct DistanceVector *dv = dvh->dv;
3750
3752 if (NULL == dv->dv_head)
3753 free_dv_route (dv);
3754 }
3755 if (NULL != neighbour->get)
3756 {
3758 neighbour->get = NULL;
3759 }
3760 if (NULL != neighbour->sc)
3761 {
3763 "store cancel\n");
3764 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3765 neighbour->sc = NULL;
3766 }
3767 if (NULL != (vl = neighbour->vl))
3768 {
3769 GNUNET_assert (neighbour == vl->n);
3770 vl->n = NULL;
3771 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3772 {
3775 }
3776 else
3777 {
3780 }
3781 neighbour->vl = NULL;
3782 }
3783 GNUNET_free (neighbour);
3784}
3785
3786
3793static void
3795 const struct GNUNET_PeerIdentity *pid)
3796{
3797 struct GNUNET_MQ_Envelope *env;
3798 struct ConnectInfoMessage *cim;
3799
3800 GNUNET_assert (CT_CORE == tc->type);
3802 cim->id = *pid;
3803 GNUNET_MQ_send (tc->mq, env);
3804}
3805
3806
3812static void
3814{
3816 "Informing CORE clients about connection to %s\n",
3817 GNUNET_i2s (pid));
3818 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3819 {
3820 if (CT_CORE != tc->type)
3821 continue;
3823 }
3824}
3825
3826
3834static void
3835transmit_on_queue (void *cls);
3836
3837
3841static unsigned int
3843{
3844 for (struct Queue *s = queue_head; NULL != s;
3845 s = s->next_client)
3846 {
3847 if (s->tc->details.communicator.address_prefix !=
3848 queue->tc->details.communicator.address_prefix)
3849 {
3851 "queue address %s qid %u compare with queue: address %s qid %u\n",
3852 queue->address,
3853 queue->qid,
3854 s->address,
3855 s->qid);
3856 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3857 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3858 return GNUNET_YES;
3860 "Lower prio\n");
3861 }
3862 }
3863 return GNUNET_NO;
3864}
3865
3866
3874static void
3876 struct Queue *queue,
3878{
3880
3881 if (queue->validated_until.abs_value_us < now.abs_value_us)
3882 return;
3884 queue->tc->details.communicator.
3885 queue_head))
3886 return;
3887
3888 if (queue->tc->details.communicator.total_queue_length >=
3890 {
3892 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3893 queue->address,
3894 queue->qid);
3896 GST_stats,
3897 "# Transmission throttled due to communicator queue limit",
3898 1,
3899 GNUNET_NO);
3900 queue->idle = GNUNET_NO;
3901 return;
3902 }
3903 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3904 {
3906 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3907 queue->address,
3908 queue->qid);
3910 "# Transmission throttled due to queue queue limit",
3911 1,
3912 GNUNET_NO);
3913 queue->idle = GNUNET_NO;
3914 return;
3915 }
3916 if (0 == queue->q_capacity)
3917 {
3919 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3920 PRIu64 ".\n",
3921 queue->address,
3922 queue->qid,
3923 queue->q_capacity);
3925 "# Transmission throttled due to message queue capacity",
3926 1,
3927 GNUNET_NO);
3928 queue->idle = GNUNET_NO;
3929 return;
3930 }
3931 /* queue might indeed be ready, schedule it */
3932 if (NULL != queue->transmit_task)
3933 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3934 queue->transmit_task =
3936 queue);
3938 "Considering transmission on queue `%s' QID %llu to %s\n",
3939 queue->address,
3940 (unsigned long long) queue->qid,
3941 GNUNET_i2s (&queue->neighbour->pid));
3942}
3943
3944
3951static void
3953{
3954 struct VirtualLink *vl = cls;
3955 struct DistanceVector *dv = vl->dv;
3956 struct Neighbour *n = vl->n;
3957 struct GNUNET_TIME_Absolute dvh_timeout;
3958 struct GNUNET_TIME_Absolute q_timeout;
3959
3961 "Checking if link is down\n");
3962 vl->visibility_task = NULL;
3963 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3964 if (NULL != dv)
3965 {
3966 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3967 pos = pos->next_dv)
3968 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
3969 pos->path_valid_until);
3970 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3971 {
3972 vl->dv->vl = NULL;
3973 vl->dv = NULL;
3974 }
3975 }
3976 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3977 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3978 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3979 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3980 {
3981 vl->n->vl = NULL;
3982 vl->n = NULL;
3983 }
3984 if ((NULL == vl->n) && (NULL == vl->dv))
3985 {
3987 free_virtual_link (vl);
3988 return;
3989 }
3990 vl->visibility_task =
3991 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3993 vl);
3994}
3995
3996
4002static void
4004{
4005 struct Neighbour *neighbour = queue->neighbour;
4006 struct TransportClient *tc = queue->tc;
4007 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4009 struct QueueEntry *qe;
4010 int maxxed;
4011 struct PendingAcknowledgement *pa;
4012 struct VirtualLink *vl;
4013
4015 "Cleaning up queue %u\n", queue->qid);
4016 if (NULL != queue->mo)
4017 {
4019 queue->mo = NULL;
4020 }
4021 if (NULL != queue->transmit_task)
4022 {
4023 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4024 queue->transmit_task = NULL;
4025 }
4026 while (NULL != (pa = queue->pa_head))
4027 {
4028 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4029 pa->queue = NULL;
4030 }
4031
4033 neighbour->queue_head,
4034 neighbour->queue_tail,
4035 queue);
4037 tc->details.communicator.queue_head,
4038 tc->details.communicator.queue_tail,
4039 queue);
4041 tc->details.communicator.total_queue_length);
4043 "Cleaning up queue with length %u\n",
4044 queue->queue_length);
4045 while (NULL != (qe = queue->queue_head))
4046 {
4047 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4048 queue->queue_length--;
4049 tc->details.communicator.total_queue_length--;
4050 if (NULL != qe->pm)
4051 {
4052 GNUNET_assert (qe == qe->pm->qe);
4053 qe->pm->qe = NULL;
4054 }
4055 GNUNET_free (qe);
4056 }
4057 GNUNET_assert (0 == queue->queue_length);
4058 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4059 tc->details.communicator.total_queue_length))
4060 {
4061 /* Communicator dropped below threshold, resume all _other_ queues */
4063 GST_stats,
4064 "# Transmission throttled due to communicator queue limit",
4065 -1,
4066 GNUNET_NO);
4067 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4068 s = s->next_client)
4070 s,
4072 }
4073 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4075
4076 vl = lookup_virtual_link (&neighbour->pid);
4077 if ((NULL != vl) && (neighbour == vl->n))
4078 {
4080 check_link_down (vl);
4081 }
4082 if (NULL == neighbour->queue_head)
4083 {
4084 free_neighbour (neighbour, GNUNET_NO);
4085 }
4086}
4087
4088
4094static void
4096{
4097 struct TransportClient *tc = ale->tc;
4098
4099 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4100 tc->details.communicator.addr_tail,
4101 ale);
4102 if (NULL != ale->sc)
4103 {
4105 "store cancel\n");
4107 ale->sc = NULL;
4108 }
4109 if (NULL != ale->st)
4110 {
4112 ale->st = NULL;
4113 }
4114 if (NULL != ale->signed_address)
4116 GNUNET_free (ale);
4117}
4118
4119
4128static int
4130 const struct GNUNET_PeerIdentity *pid,
4131 void *value)
4132{
4133 struct TransportClient *tc = cls;
4134 struct PeerRequest *pr = value;
4135
4136 if (NULL != pr->nc)
4138 pr->nc = NULL;
4140 GNUNET_YES ==
4141 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4142 pid,
4143 pr));
4144 GNUNET_free (pr);
4145
4146 return GNUNET_OK;
4147}
4148
4149
4150static void
4151do_shutdown (void *cls);
4152
4161static void
4163 struct GNUNET_SERVICE_Client *client,
4164 void *app_ctx)
4165{
4166 struct TransportClient *tc = app_ctx;
4167
4168 (void) cls;
4169 (void) client;
4171 switch (tc->type)
4172 {
4173 case CT_NONE:
4175 "Unknown Client %p disconnected, cleaning up.\n",
4176 tc);
4177 break;
4178
4179 case CT_CORE: {
4180 struct PendingMessage *pm;
4182 "CORE Client %p disconnected, cleaning up.\n",
4183 tc);
4184
4185
4186 while (NULL != (pm = tc->details.core.pending_msg_head))
4187 {
4189 tc->details.core.pending_msg_head,
4190 tc->details.core.pending_msg_tail,
4191 pm);
4192 pm->client = NULL;
4193 }
4194 }
4195 break;
4196
4197 case CT_MONITOR:
4199 "MONITOR Client %p disconnected, cleaning up.\n",
4200 tc);
4201
4202 break;
4203
4204 case CT_COMMUNICATOR: {
4205 struct Queue *q;
4206 struct AddressListEntry *ale;
4207
4209 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4210 tc);
4211
4212 if (NULL != tc->details.communicator.free_queue_entry_task)
4214 tc->details.communicator.free_queue_entry_task);
4215 while (NULL != (q = tc->details.communicator.queue_head))
4216 free_queue (q);
4217 while (NULL != (ale = tc->details.communicator.addr_head))
4219 GNUNET_free (tc->details.communicator.address_prefix);
4220 }
4221 break;
4222
4223 case CT_APPLICATION:
4225 "APPLICATION Client %p disconnected, cleaning up.\n",
4226 tc);
4227
4228 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4230 tc);
4231 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4232 break;
4233 }
4234 GNUNET_free (tc);
4235 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4236 {
4238 "Our last client disconnected\n");
4239 do_shutdown (cls);
4240 }
4241}
4242
4243
4253static int
4255 const struct GNUNET_PeerIdentity *pid,
4256 void *value)
4257{
4258 struct TransportClient *tc = cls;
4259 struct VirtualLink *vl = value;
4260
4261 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4262 return GNUNET_OK;
4263
4265 "Telling new CORE client about existing connection to %s\n",
4266 GNUNET_i2s (pid));
4268 return GNUNET_OK;
4269}
4270
4271
4277static void
4279 unsigned
4280 int free_cmc);
4281
4282static enum GNUNET_GenericReturnValue
4284 const struct GNUNET_PeerIdentity *pid,
4285 void *value)
4286{
4287 struct VirtualLink *vl = value;
4288 struct CommunicatorMessageContext *cmc;
4289
4290 /* resume communicators */
4291 while (NULL != (cmc = vl->cmc_tail))
4292 {
4294 if (GNUNET_NO == cmc->continue_send)
4296 }
4297 return GNUNET_OK;
4298}
4299
4300
4309static void
4310handle_client_start (void *cls, const struct StartMessage *start)
4311{
4312 struct TransportClient *tc = cls;
4313 uint32_t options;
4314
4315 options = ntohl (start->options);
4316 if ((0 != (1 & options)) &&
4317 (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4318 {
4319 /* client thinks this is a different peer, reject */
4320 GNUNET_break (0);
4322 return;
4323 }
4324 if (CT_NONE != tc->type)
4325 {
4326 GNUNET_break (0);
4328 return;
4329 }
4330 tc->type = CT_CORE;
4332 "New CORE client with PID %s registered\n",
4333 GNUNET_i2s (&start->self));
4336 tc);
4339 NULL);
4341}
4342
4343
4350static int
4351check_client_send (void *cls, const struct OutboundMessage *obm)
4352{
4353 struct TransportClient *tc = cls;
4354 uint16_t size;
4355 const struct GNUNET_MessageHeader *obmm;
4356
4357 if (CT_CORE != tc->type)
4358 {
4359 GNUNET_break (0);
4360 return GNUNET_SYSERR;
4361 }
4362 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4363 if (size < sizeof(struct GNUNET_MessageHeader))
4364 {
4365 GNUNET_break (0);
4366 return GNUNET_SYSERR;
4367 }
4368 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4369 if (size != ntohs (obmm->size))
4370 {
4371 GNUNET_break (0);
4372 return GNUNET_SYSERR;
4373 }
4374 return GNUNET_OK;
4375}
4376
4377
4385static void
4387{
4388 struct TransportClient *tc = pm->client;
4389 struct VirtualLink *vl = pm->vl;
4390
4392 "client send response\n");
4393 if (NULL != tc)
4394 {
4395 struct GNUNET_MQ_Envelope *env;
4396 struct SendOkMessage *so_msg;
4397
4399 so_msg->peer = vl->target;
4401 "Confirming transmission of <%" PRIu64 "> to %s\n",
4402 pm->logging_uuid,
4403 GNUNET_i2s (&vl->target));
4404 GNUNET_MQ_send (tc->mq, env);
4405 }
4407}
4408
4409
4419static unsigned int
4422 struct DistanceVectorHop **hops_array,
4423 unsigned int hops_array_length)
4424{
4425 uint64_t choices[hops_array_length];
4426 uint64_t num_dv;
4427 unsigned int dv_count;
4428
4429 /* Pick random vectors, but weighted by distance, giving more weight
4430 to shorter vectors */
4431 num_dv = 0;
4432 dv_count = 0;
4433 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4434 pos = pos->next_dv)
4435 {
4436 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4437 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4438 .rel_value_us == 0))
4439 continue; /* pos unconfirmed and confirmed required */
4440 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4441 dv_count++;
4442 }
4443 if (0 == dv_count)
4444 return 0;
4445 if (dv_count <= hops_array_length)
4446 {
4447 dv_count = 0;
4448 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4449 pos = pos->next_dv)
4450 hops_array[dv_count++] = pos;
4451 return dv_count;
4452 }
4453 for (unsigned int i = 0; i < hops_array_length; i++)
4454 {
4455 int ok = GNUNET_NO;
4456 while (GNUNET_NO == ok)
4457 {
4458 choices[i] =
4460 ok = GNUNET_YES;
4461 for (unsigned int j = 0; j < i; j++)
4462 if (choices[i] == choices[j])
4463 {
4464 ok = GNUNET_NO;
4465 break;
4466 }
4467 }
4468 }
4469 dv_count = 0;
4470 num_dv = 0;
4471 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4472 pos = pos->next_dv)
4473 {
4474 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4475
4476 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4477 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4478 .rel_value_us == 0))
4479 continue; /* pos unconfirmed and confirmed required */
4480 for (unsigned int i = 0; i < hops_array_length; i++)
4481 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4482 hops_array[dv_count++] = pos;
4483 num_dv += delta;
4484 }
4485 return dv_count;
4486}
4487
4488
4495static int
4497 void *cls,
4499{
4500 struct TransportClient *tc = cls;
4501 uint16_t size;
4502
4503 if (CT_NONE != tc->type)
4504 {
4505 GNUNET_break (0);
4506 return GNUNET_SYSERR;
4507 }
4508 tc->type = CT_COMMUNICATOR;
4509 size = ntohs (cam->header.size) - sizeof(*cam);
4510 if (0 == size)
4511 return GNUNET_OK; /* receive-only communicator */
4513 return GNUNET_OK;
4514}
4515
4516
4522static void
4524 unsigned
4525 int free_cmc)
4526{
4527 if (0 != ntohl (cmc->im.fc_on))
4528 {
4529 /* send ACK when done to communicator for flow control! */
4530 struct GNUNET_MQ_Envelope *env;
4532
4534 "Acknowledge message with flow control id %" PRIu64 "\n",
4535 cmc->im.fc_id);
4537 ack->reserved = htonl (0);
4538 ack->fc_id = cmc->im.fc_id;
4539 ack->sender = cmc->im.neighbour_sender;
4540 GNUNET_MQ_send (cmc->tc->mq, env);
4541 }
4542
4544
4545 if (GNUNET_YES == free_cmc)
4546 {
4547 GNUNET_free (cmc);
4548 }
4549}
4550
4551
4552static void
4554{
4556}
4557
4558
4568static void
4569handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4570{
4571 struct TransportClient *tc = cls;
4572 struct VirtualLink *vl;
4573 uint32_t delta;
4574 struct CommunicatorMessageContext *cmc;
4575
4576 if (CT_CORE != tc->type)
4577 {
4578 GNUNET_break (0);
4580 return;
4581 }
4582 vl = lookup_virtual_link (&rom->peer);
4583 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4584 {
4586 "# RECV_OK dropped: virtual link unknown",
4587 1,
4588 GNUNET_NO);
4590 return;
4591 }
4592 delta = ntohl (rom->increase_window_delta);
4593 vl->core_recv_window += delta;
4595 "CORE ack receiving message, increased CORE recv window to %d\n",
4596 vl->core_recv_window);
4598 if (vl->core_recv_window <= 0)
4599 return;
4600 /* resume communicators */
4601 while (NULL != (cmc = vl->cmc_tail))
4602 {
4604 if (GNUNET_NO == cmc->continue_send)
4606 }
4607}
4608
4609
4616static void
4618 void *cls,
4620{
4621 struct TransportClient *tc = cls;
4622 uint16_t size;
4623
4624 size = ntohs (cam->header.size) - sizeof(*cam);
4625 if (0 == size)
4626 {
4628 "Receive-only communicator connected\n");
4629 return; /* receive-only communicator */
4630 }
4631 tc->details.communicator.address_prefix =
4632 GNUNET_strdup ((const char *) &cam[1]);
4633 tc->details.communicator.cc = ntohl (cam->cc);
4634 tc->details.communicator.can_burst = ntohl (cam->can_burst);
4636 "Communicator for peer %s with prefix '%s' connected %s\n",
4638 tc->details.communicator.address_prefix,
4639 tc->details.communicator.can_burst ? "can burst" :
4640 "can not burst");
4642}
4643
4644
4652static int
4654 void *cls,
4656{
4657 const struct GNUNET_MessageHeader *inbox;
4658 const char *is;
4659 uint16_t msize;
4660 uint16_t isize;
4661
4662 (void) cls;
4663 msize = ntohs (cb->header.size) - sizeof(*cb);
4664 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4665 isize = ntohs (inbox->size);
4666 if (isize >= msize)
4667 {
4668 GNUNET_break (0);
4669 return GNUNET_SYSERR;
4670 }
4671 is = (const char *) inbox;
4672 is += isize;
4673 msize -= isize;
4674 GNUNET_assert (0 < msize);
4675 if ('\0' != is[msize - 1])
4676 {
4677 GNUNET_break (0);
4678 return GNUNET_SYSERR;
4679 }
4680 return GNUNET_OK;
4681}
4682
4683
4689static void
4691{
4692 struct EphemeralConfirmationPS ec;
4693
4695 dv->ephemeral_validity =
4698 ec.target = dv->target;
4701 ec.purpose.size = htonl (sizeof(ec));
4703 &ec,
4704 &dv->sender_sig);
4705}
4706
4707
4708static void
4710 struct TransportClient *tc);
4711
4712
4713static void
4715{
4716 struct TransportClient *tc = cls;
4718
4720 "freeing timedout queue entries\n");
4721
4722 tc->details.communicator.free_queue_entry_task = NULL;
4723 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4724 queue = queue->next_client)
4725 {
4726 struct QueueEntry *qep = queue->queue_head;
4727
4729 "checking QID %u for timedout queue entries\n",
4730 queue->qid);
4731 while (NULL != qep)
4732 {
4733 struct QueueEntry *pos = qep;
4735 pos->creation_timestamp, now);
4736 qep = qep->next;
4737
4739 "diff to now %s \n",
4742 {
4744 "Freeing timed out QueueEntry with MID %" PRIu64
4745 " and QID %u\n",
4746 pos->mid,
4747 queue->qid);
4748 free_queue_entry (pos, tc);
4749 }
4750 }
4751 }
4752}
4753
4754
4764static void
4766 struct PendingMessage *pm,
4767 const void *payload,
4768 size_t payload_size)
4769{
4770 struct Neighbour *n = queue->neighbour;
4772 struct GNUNET_MQ_Envelope *env;
4773 struct PendingAcknowledgement *pa;
4774
4775 GNUNET_log (
4777 "Queueing %u bytes of payload for transmission <%" PRIu64
4778 "> on queue %llu to %s\n",
4779 (unsigned int) payload_size,
4780 (NULL == pm) ? 0 : pm->logging_uuid,
4781 (unsigned long long) queue->qid,
4782 GNUNET_i2s (&queue->neighbour->pid));
4783 env = GNUNET_MQ_msg_extra (smt,
4784 payload_size,
4786 smt->qid = htonl (queue->qid);
4787 smt->mid = GNUNET_htonll (queue->mid_gen);
4788 smt->receiver = n->pid;
4789 memcpy (&smt[1], payload, payload_size);
4790 {
4791 /* Pass the env to the communicator of queue for transmission. */
4792 struct QueueEntry *qe;
4793
4794 qe = GNUNET_new (struct QueueEntry);
4795 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4796 qe->mid = queue->mid_gen;
4798 "Create QueueEntry with MID %" PRIu64
4799 " and QID %u and prefix %s\n",
4800 qe->mid,
4801 queue->qid,
4802 queue->tc->details.communicator.address_prefix);
4803 queue->mid_gen++;
4804 qe->queue = queue;
4805 if (NULL != pm)
4806 {
4807 qe->pm = pm;
4808 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4809 // GNUNET_assert (NULL == pm->qe);
4810 if (NULL != pm->qe)
4811 {
4813 "Retransmitting message <%" PRIu64
4814 "> remove pm from qe with MID: %llu \n",
4815 pm->logging_uuid,
4816 (unsigned long long) pm->qe->mid);
4817 pm->qe->pm = NULL;
4818 }
4819 pm->qe = qe;
4820 }
4821 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4822 if (0 == queue->q_capacity)
4823 {
4824 // Messages without FC or fragments can get here.
4825 if (NULL != pm)
4826 {
4828 "Message %" PRIu64
4829 " (pm type %u) was not send because queue has no capacity.\n",
4830 pm->logging_uuid,
4831 pm->pmt);
4832 pm->qe = NULL;
4833 }
4834 GNUNET_free (env);
4835 GNUNET_free (qe);
4836 return;
4837 }
4838 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4839 queue->queue_length++;
4840 queue->tc->details.communicator.total_queue_length++;
4841 if (GNUNET_NO == queue->unlimited_length)
4842 queue->q_capacity--;
4844 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4845 queue->address,
4846 queue->qid,
4847 queue->q_capacity);
4849 queue->tc->details.communicator.total_queue_length)
4850 queue->idle = GNUNET_NO;
4851 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4852 queue->idle = GNUNET_NO;
4853 if (0 == queue->q_capacity)
4854 queue->idle = GNUNET_NO;
4855
4856 if (GNUNET_NO == queue->idle)
4857 {
4858 struct TransportClient *tc = queue->tc;
4859
4860 if (NULL == tc->details.communicator.free_queue_entry_task)
4861 tc->details.communicator.free_queue_entry_task =
4863 &
4865 tc);
4866 }
4867 if (NULL != pm && NULL != (pa = pm->pa_head))
4868 {
4869 while (pm != pa->pm)
4870 pa = pa->next_pa;
4871 pa->num_send++;
4872 }
4873 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4875 "Sending message MID %" PRIu64
4876 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4877 PRIu64 "\n",
4878 GNUNET_ntohll (smt->mid),
4879 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4880 ntohs (smt->header.size),
4881 (unsigned long) payload_size,
4882 queue->tc->mq,
4883 queue->address,
4884 queue->qid,
4885 (NULL == pm) ? 0 : pm->logging_uuid);
4886 GNUNET_MQ_send (queue->tc->mq, env);
4887 }
4888}
4889
4890
4901static struct GNUNET_TIME_Relative
4903 const struct GNUNET_MessageHeader *hdr,
4905{
4906 struct GNUNET_TIME_Absolute now;
4907 unsigned int candidates;
4908 unsigned int sel1;
4909 unsigned int sel2;
4910 struct GNUNET_TIME_Relative rtt;
4911
4912 /* Pick one or two 'random' queues from n (under constraints of options) */
4913 now = GNUNET_TIME_absolute_get ();
4914 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4915 weight in the future; weight could be assigned by observed
4916 bandwidth (note: not sure if we should do this for this type
4917 of control traffic though). */
4918 candidates = 0;
4919 for (struct Queue *pos = n->queue_head; NULL != pos;
4920 pos = pos->next_neighbour)
4921 {
4922 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4923 (pos->validated_until.abs_value_us > now.abs_value_us))
4924 candidates++;
4925 }
4926 if (0 == candidates)
4927 {
4928 /* This can happen rarely if the last confirmed queue timed
4929 out just as we were beginning to process this message. */
4931 "Could not route message of type %u to %s: no valid queue\n",
4932 ntohs (hdr->type),
4933 GNUNET_i2s (&n->pid));
4935 "# route selection failed (all no valid queue)",
4936 1,
4937 GNUNET_NO);
4939 }
4940
4943 if (0 == (options & RMO_REDUNDANT))
4944 sel2 = candidates; /* picks none! */
4945 else
4947 candidates = 0;
4948 for (struct Queue *pos = n->queue_head; NULL != pos;
4949 pos = pos->next_neighbour)
4950 {
4951 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4952 (pos->validated_until.abs_value_us > now.abs_value_us))
4953 {
4954 if ((sel1 == candidates) || (sel2 == candidates))
4955 {
4957 "Routing message of type %u to %s using %s (#%u)\n",
4958 ntohs (hdr->type),
4959 GNUNET_i2s (&n->pid),
4960 pos->address,
4961 (sel1 == candidates) ? 1 : 2);
4962 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4963 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4964 }
4965 candidates++;
4966 }
4967 }
4968 return rtt;
4969}
4970
4971
4976{
4980 gcry_cipher_hd_t cipher;
4981
4985 struct
4986 {
4991
4995 char aes_key[256 / 8];
4996
5000 char aes_ctr[128 / 8];
5002};
5003
5004
5013static void
5015 const struct GNUNET_ShortHashCode *iv,
5016 struct DVKeyState *key)
5017{
5018 /* must match what we defive from decapsulated key */
5020 GNUNET_CRYPTO_hkdf_expand (&key->material,
5021 sizeof(key->material),
5022 km,
5023 "gnunet-transport-dv-key",
5024 strlen ("gnunet-transport-dv-key")
5025 ,
5026 km,
5027 sizeof(*km),
5028 iv,
5029 sizeof(*iv),
5030 NULL));
5032 "Deriving backchannel key based on KM %s and IV %s\n",
5033 GNUNET_sh2s (km),
5034 GNUNET_sh2s (iv));
5035 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5036 GCRY_CIPHER_AES256 /* low level: go for speed */
5037 ,
5038 GCRY_CIPHER_MODE_CTR,
5039 0 /* flags */));
5040 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5041 &key->material.aes_key,
5042 sizeof(key->material.aes_key)));
5043 gcry_cipher_setctr (key->cipher,
5044 &key->material.aes_ctr,
5045 sizeof(key->material.aes_ctr));
5046}
5047
5048
5058static void
5059dv_hmac (const struct DVKeyState *key,
5060 struct GNUNET_HashCode *hmac,
5061 const void *data,
5062 size_t data_size)
5063{
5064 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5065}
5066
5067
5077static void
5078dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5079{
5080 GNUNET_assert (0 ==
5081 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5082}
5083
5084
5095static enum GNUNET_GenericReturnValue
5097 void *out,
5098 const void *ciph,
5099 size_t out_size)
5100{
5101 return (0 ==
5102 gcry_cipher_decrypt (key->cipher,
5103 out, out_size,
5104 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5105}
5106
5107
5113static void
5115{
5116 gcry_cipher_close (key->cipher);
5117 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5118}
5119
5120
5131typedef void (*DVMessageHandler) (void *cls,
5132 struct Neighbour *next_hop,
5133 const struct GNUNET_MessageHeader *hdr,
5135
5150static struct GNUNET_TIME_Relative
5152 unsigned int num_dvhs,
5153 struct DistanceVectorHop **dvhs,
5154 const struct GNUNET_MessageHeader *hdr,
5155 DVMessageHandler use,
5156 void *use_cls,
5158 enum GNUNET_GenericReturnValue without_fc)
5159{
5160 struct TransportDVBoxMessage box_hdr;
5161 struct TransportDVBoxPayloadP payload_hdr;
5162 uint16_t enc_body_size = ntohs (hdr->size);
5163 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5164 struct DVKeyState *key;
5165 struct GNUNET_TIME_Relative rtt;
5166 struct GNUNET_ShortHashCode km;
5167
5168 key = GNUNET_new (struct DVKeyState);
5169 /* Encrypt payload */
5171 box_hdr.total_hops = htons (0);
5172 box_hdr.without_fc = htons (without_fc);
5173 // update_ephemeral (dv);
5174 if (0 ==
5175 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5176 {
5177 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5178 &dv->ephemeral_key,
5179 &km);
5180 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5181 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5182 sign_ephemeral (dv);
5183 }
5184 box_hdr.ephemeral_key = dv->ephemeral_key;
5185 payload_hdr.sender_sig = dv->sender_sig;
5186
5188 &box_hdr.iv,
5189 sizeof(box_hdr.iv));
5190 // We are creating this key, so this must work.
5191 // FIXME: Possibly also add return values here. We are processing
5192 // Input from other peers...
5193 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5194 payload_hdr.sender = GST_my_identity;
5195 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5196 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5197 dv_encrypt (key,
5198 hdr,
5199 &enc[sizeof(struct TransportDVBoxPayloadP)],
5200 enc_body_size);
5201 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5202 dv_key_clean (key);
5204 /* For each selected path, take the pre-computed header and body
5205 and add the path in the middle of the message; then send it. */
5206 for (unsigned int i = 0; i < num_dvhs; i++)
5207 {
5208 struct DistanceVectorHop *dvh = dvhs[i];
5209 unsigned int num_hops = dvh->distance + 1;
5210 char buf[sizeof(struct TransportDVBoxMessage)
5211 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5212 + sizeof(struct TransportDVBoxPayloadP)
5213 + enc_body_size] GNUNET_ALIGN;
5214 struct GNUNET_PeerIdentity *dhops;
5215
5216 box_hdr.header.size = htons (sizeof(buf));
5217 box_hdr.orig_size = htons (sizeof(buf));
5218 box_hdr.num_hops = htons (num_hops);
5219 memcpy (buf, &box_hdr, sizeof(box_hdr));
5220 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5221 memcpy (dhops,
5222 dvh->path,
5223 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5224 dhops[dvh->distance] = dv->target;
5225 if (GNUNET_EXTRA_LOGGING > 0)
5226 {
5227 char *path;
5228
5230 for (unsigned int j = 0; j < num_hops; j++)
5231 {
5232 char *tmp;
5233
5234 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5235 GNUNET_free (path);
5236 path = tmp;
5237 }
5239 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5240 ntohs (hdr->type),
5241 GNUNET_i2s (&dv->target),
5242 i + 1,
5243 num_dvhs,
5244 path);
5245 GNUNET_free (path);
5246 }
5247 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5248 memcpy (&dhops[num_hops], enc, sizeof(enc));
5249 use (use_cls,
5250 dvh->next_hop,
5251 (const struct GNUNET_MessageHeader *) buf,
5252 options);
5253 GNUNET_free (key);
5254 }
5255 return rtt;
5256}
5257
5258
5268static void
5270 struct Neighbour *next_hop,
5271 const struct GNUNET_MessageHeader *hdr,
5273{
5274 (void) cls;
5275 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5276}
5277
5278
5290static struct GNUNET_TIME_Relative
5292// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5293 const struct GNUNET_MessageHeader *hdr,
5295{
5296 // struct VirtualLink *vl;
5297 struct Neighbour *n;
5298 struct DistanceVector *dv;
5299 struct GNUNET_TIME_Relative rtt1;
5300 struct GNUNET_TIME_Relative rtt2;
5301 const struct GNUNET_PeerIdentity *target = &vl->target;
5302
5304 "Trying to route message of type %u to %s without fc\n",
5305 ntohs (hdr->type),
5306 GNUNET_i2s (target));
5307
5308 // TODO Do this elsewhere. vl should be given as parameter to method.
5309 // vl = lookup_virtual_link (target);
5310 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5311 if (NULL == vl)
5313 n = vl->n;
5314 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5315 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5316 {
5317 /* if confirmed is required, and we do not have anything
5318 confirmed, drop respective options */
5319 if (NULL == n)
5320 n = lookup_neighbour (target);
5321 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5323 }
5324 if ((NULL == n) && (NULL == dv))
5325 {
5327 "Cannot route message of type %u to %s: no route\n",
5328 ntohs (hdr->type),
5329 GNUNET_i2s (target));
5331 "# Messages dropped in routing: no acceptable method",
5332 1,
5333 GNUNET_NO);
5335 }
5337 "Routing message of type %u to %s with options %X\n",
5338 ntohs (hdr->type),
5339 GNUNET_i2s (target),
5340 (unsigned int) options);
5341 /* If both dv and n are possible and we must choose:
5342 flip a coin for the choice between the two; for now 50/50 */
5343 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5344 {
5346 n = NULL;
5347 else
5348 dv = NULL;
5349 }
5350 if ((NULL != n) && (NULL != dv))
5351 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5352 enough for redundancy, so clear the flag. */
5355 if (NULL != n)
5356 {
5358 "Try to route message of type %u to %s without fc via neighbour\n",
5359 ntohs (hdr->type),
5360 GNUNET_i2s (target));
5361 rtt1 = route_via_neighbour (n, hdr, options);
5362 }
5363 if (NULL != dv)
5364 {
5365 struct DistanceVectorHop *hops[2];
5366 unsigned int res;
5367
5369 options,
5370 hops,
5371 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5372 if (0 == res)
5373 {
5375 "Failed to route message, could not determine DV path\n");
5376 return rtt1;
5377 }
5379 "encapsulate_for_dv 1\n");
5380 rtt2 = encapsulate_for_dv (dv,
5381 res,
5382 hops,
5383 hdr,
5385 NULL,
5387 GNUNET_YES);
5388 }
5389 return GNUNET_TIME_relative_min (rtt1, rtt2);
5390}
5391
5392
5393static void
5394consider_sending_fc (void *cls);
5395
5402static void
5404{
5405 struct VirtualLink *vl = cls;
5406 vl->fc_retransmit_task = NULL;
5407 consider_sending_fc (cls);
5408}
5409
5410
5411static char *
5412get_address_without_port (const char *address);
5413
5414
5416{
5417 size_t off;
5418 char *tgnas;
5419};
5420
5421
5422static enum GNUNET_GenericReturnValue
5424 const struct GNUNET_PeerIdentity *pid,
5425 void *value)
5426{
5427 struct AddGlobalAddressesContext *ctx = cls;
5428 struct TransportGlobalNattedAddress *tgna = value;
5429 char *addr = (char *) &tgna[1];
5430
5432 "sending address %s length %u\n",
5433 addr,
5434 ntohl (tgna->address_length));
5435 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5437 + ntohl (tgna->address_length));
5438 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5440
5441 return GNUNET_OK;
5442}
5443
5444
5445static struct GNUNET_TIME_Relative
5446calculate_rtt (struct DistanceVector *dv);
5447
5448
5455static void
5457{
5458 struct VirtualLink *vl = cls;
5459 struct GNUNET_TIME_Absolute monotime;
5460 struct TransportFlowControlMessage *fc;
5462 struct GNUNET_TIME_Relative rtt;
5463 struct GNUNET_TIME_Relative rtt_average;
5464 struct Neighbour *n = vl->n;
5465
5466 if (NULL != n && 0 < n->number_of_addresses)
5467 {
5468 size_t addresses_size =
5469 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5470 ->size_of_global_addresses;
5471 char *tgnas = GNUNET_malloc (addresses_size);
5473 ctx.off = 0;
5474 ctx.tgnas = tgnas;
5475
5476 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage)
5477 + addresses_size);
5478 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5479 + addresses_size);
5480 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5481 fc->number_of_addresses = htonl (n->number_of_addresses);
5482 GNUNET_CONTAINER_multipeermap_iterate (n->natted_addresses,
5484 &ctx);
5485 GNUNET_memcpy (&fc[1], tgnas, addresses_size);
5487 }
5488 else
5489 {
5490 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5491 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5492 }
5493
5495 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5496 it always! */
5497 /* For example, we should probably ONLY do this if a bit more than
5498 an RTT has passed, or if the window changed "significantly" since
5499 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5500 need an estimate for the bandwidth-delay-product for the entire
5501 VL, as that determines "significantly". We have the delay, but
5502 the bandwidth statistics need to be added for the VL!*/(void) duration;
5503
5504 if (NULL != vl->dv)
5505 rtt_average = calculate_rtt (vl->dv);
5506 else
5507 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5508 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5510 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5511 (unsigned int) vl->fc_seq_gen,
5512 GNUNET_i2s (&vl->target),
5513 (unsigned long long) vl->incoming_fc_window_size,
5514 (unsigned long) rtt_average.rel_value_us,
5515 vl->sync_ready);
5517 vl->last_fc_transmission = monotime;
5518 fc->sync_ready = vl->sync_ready;
5520 fc->seq = htonl (vl->fc_seq_gen++);
5526 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5528 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5529 {
5532 "FC retransmission to %s failed, will retry in %s\n",
5533 GNUNET_i2s (&vl->target),
5536 }
5537 else
5538 {
5539 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5540 vl->last_fc_rtt = rtt;
5541 }
5542 if (NULL != vl->fc_retransmit_task)
5545 {
5547 vl->fc_retransmit_count = 0;
5548 }
5549 vl->fc_retransmit_task =
5551 vl->fc_retransmit_count++;
5552 GNUNET_free (fc);
5553}
5554
5555
5572static void
5574{
5575 struct Neighbour *n = vl->n;
5576 struct DistanceVector *dv = vl->dv;
5577 struct GNUNET_TIME_Absolute now;
5578 struct VirtualLink *vl_next_hop;
5579 int elig;
5580
5582 "check_vl_transmission to target %s\n",
5583 GNUNET_i2s (&vl->target));
5584 /* Check that we have an eligible pending message!
5585 (cheaper than having #transmit_on_queue() find out!) */
5586 elig = GNUNET_NO;
5587 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5588 pm = pm->next_vl)
5589 {
5591 "check_vl_transmission loop\n");
5592 if (NULL != pm->qe)
5593 continue; /* not eligible, is in a queue! */
5594 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5596 {
5598 "Stalled message %" PRIu64
5599 " transmission on VL %s due to flow control: %llu < %llu\n",
5600 pm->logging_uuid,
5601 GNUNET_i2s (&vl->target),
5602 (unsigned long long) vl->outbound_fc_window_size,
5603 (unsigned long long) (pm->bytes_msg
5606 return; /* We have a message, but flow control says "nope" */
5607 }
5609 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5610 GNUNET_i2s (&vl->target));
5611 /* Notify queues at direct neighbours that we are interested */
5612 now = GNUNET_TIME_absolute_get ();
5613 if (NULL != n)
5614 {
5615 for (struct Queue *queue = n->queue_head; NULL != queue;
5616 queue = queue->next_neighbour)
5617 {
5618 if ((GNUNET_YES == queue->idle) &&
5619 (queue->validated_until.abs_value_us > now.abs_value_us))
5620 {
5622 "Direct neighbour %s not stalled\n",
5623 GNUNET_i2s (&n->pid));
5625 queue,
5627 elig = GNUNET_YES;
5628 }
5629 else
5631 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5632 queue->qid,
5633 queue->idle);
5634 }
5635 }
5636 /* Notify queues via DV that we are interested */
5637 if (NULL != dv)
5638 {
5639 /* Do DV with lower scheduler priority, which effectively means that
5640 IF a neighbour exists and is available, we prefer it. */
5641 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5642 pos = pos->next_dv)
5643 {
5644 struct Neighbour *nh_iter = pos->next_hop;
5645
5646
5647 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5648 continue; /* skip this one: path not validated */
5649 else
5650 {
5651 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5652 GNUNET_assert (NULL != vl_next_hop);
5653 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5654 vl_next_hop->outbound_fc_window_size)
5655 {
5657 "Stalled message %" PRIu64
5658 " transmission on next hop %s due to flow control: %llu < %llu\n",
5659 pm->logging_uuid,
5660 GNUNET_i2s (&vl_next_hop->target),
5661 (unsigned long
5662 long) vl_next_hop->outbound_fc_window_size,
5663 (unsigned long long) (pm->bytes_msg
5664 + vl_next_hop->
5665 outbound_fc_window_size_used));
5666 consider_sending_fc (vl_next_hop);
5667 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5668 }
5669 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5670 queue = queue->next_neighbour)
5671 if ((GNUNET_YES == queue->idle) &&
5672 (queue->validated_until.abs_value_us > now.abs_value_us))
5673 {
5675 "Next hop neighbour %s not stalled\n",
5676 GNUNET_i2s (&nh_iter->pid));
5678 queue,
5680 elig = GNUNET_YES;
5681 }
5682 else
5684 "DV Queue QID: %u (%u) busy or invalid\n",
5685 queue->qid,
5686 queue->idle);
5687 }
5688 }
5689 }
5690 if (GNUNET_YES == elig)
5692 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5693 pm->logging_uuid,
5694 pm->bytes_msg,
5695 GNUNET_i2s (&vl->target),
5696 (unsigned long long) vl->outbound_fc_window_size,
5697 (unsigned long long) (pm->bytes_msg
5699 break;
5700 }
5701}
5702
5703
5710static void
5711handle_client_send (void *cls, const struct OutboundMessage *obm)
5712{
5713 struct TransportClient *tc = cls;
5714 struct PendingMessage *pm;
5715 const struct GNUNET_MessageHeader *obmm;
5716 uint32_t bytes_msg;
5717 struct VirtualLink *vl;
5719
5720 GNUNET_assert (CT_CORE == tc->type);
5721 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5722 bytes_msg = ntohs (obmm->size);
5723 pp = ntohl (obm->priority);
5724 vl = lookup_virtual_link (&obm->peer);
5725 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5726 {
5728 "Don't have %s as a neighbour (anymore).\n",
5729 GNUNET_i2s (&obm->peer));
5730 /* Failure: don't have this peer as a neighbour (anymore).
5731 Might have gone down asynchronously, so this is NOT
5732 a protocol violation by CORE. Still count the event,
5733 as this should be rare. */
5736 "# messages dropped (neighbour unknown)",
5737 1,
5738 GNUNET_NO);
5739 return;
5740 }
5741
5742 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5744 "1 created pm %p storing vl %p\n",
5745 pm,
5746 vl);
5747 pm->logging_uuid = logging_uuid_gen++;
5748 pm->prefs = pp;
5749 pm->client = tc;
5750 pm->vl = vl;
5751 pm->bytes_msg = bytes_msg;
5752 memcpy (&pm[1], obmm, bytes_msg);
5754 "Sending message of type %u with %u bytes as <%" PRIu64
5755 "> to %s\n",
5756 ntohs (obmm->type),
5757 bytes_msg,
5758 pm->logging_uuid,
5759 GNUNET_i2s (&obm->peer));
5761 tc->details.core.pending_msg_head,
5762 tc->details.core.pending_msg_tail,
5763 pm);
5765 vl->pending_msg_head,
5766 vl->pending_msg_tail,
5767 pm);
5770}
5771
5772
5782static void
5784 void *cls,
5786{
5787 struct Neighbour *n;
5788 struct VirtualLink *vl;
5789 struct TransportClient *tc = cls;
5790 const struct GNUNET_MessageHeader *inbox =
5791 (const struct GNUNET_MessageHeader *) &cb[1];
5792 uint16_t isize = ntohs (inbox->size);
5793 const char *is = ((const char *) &cb[1]) + isize;
5794 size_t slen = strlen (is) + 1;
5795 char
5796 mbuf[slen + isize
5797 + sizeof(struct
5801
5802 /* 0-termination of 'is' was checked already in
5803 #check_communicator_backchannel() */
5805 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5806 GNUNET_i2s (&cb->pid),
5807 is,
5808 ntohs (inbox->type),
5809 ntohs (inbox->size));
5810 /* encapsulate and encrypt message */
5811 be->header.type =
5813 be->header.size = htons (sizeof(mbuf));
5814 memcpy (&be[1], inbox, isize);
5815 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5816 + isize],
5817 is,
5818 strlen (is) + 1);
5819 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5820 vl = lookup_virtual_link (&cb->pid);
5821 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5822 {
5824 }
5825 else
5826 {
5827 /* Use route via neighbour */
5828 n = lookup_neighbour (&cb->pid);
5829 if (NULL != n)
5831 n,
5832 &be->header,
5833 RMO_NONE);
5834 }
5836}
5837
5838
5846static int
5848 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5849{
5850 struct TransportClient *tc = cls;
5851
5852 if (CT_COMMUNICATOR != tc->type)
5853 {
5854 GNUNET_break (0);
5855 return GNUNET_SYSERR;
5856 }
5858 return GNUNET_OK;
5859}
5860
5861
5867static void
5868store_pi (void *cls);
5869
5870
5877static void
5878peerstore_store_own_cb (void *cls, int success)
5879{
5880 struct AddressListEntry *ale = cls;
5881
5882 ale->sc = NULL;
5883 if (GNUNET_YES != success)
5885 "Failed to store our own address `%s' in peerstore!\n",
5886 ale->address);
5887 else
5889 "Successfully stored our own address `%s' in peerstore!\n",
5890 ale->address);
5891 /* refresh period is 1/4 of expiration time, that should be plenty
5892 without being excessive. */
5893 ale->st =
5895 4ULL),
5896 &store_pi,
5897 ale);
5898}
5899
5900
5901static void
5902shc_cont (void *cls, int success)
5903{
5904 struct AddressListEntry *ale = cls;
5906
5909 "transport",
5912 ale->signed_address,
5913 ale->signed_address_len,
5914 expiration,
5917 ale);
5918 if (NULL == ale->sc)
5919 {
5921 "Failed to store our address `%s' with peerstore\n",
5922 ale->address);
5924 &store_pi,
5925 ale);
5926 }
5927}
5928
5929
5935static void
5936store_pi (void *cls)
5937{
5938 struct AddressListEntry *ale = cls;
5939 struct GNUNET_MQ_Envelope *env;
5940 const struct GNUNET_MessageHeader *msg;
5941 const char *dash;
5942 char *address_uri;
5944 unsigned int add_success;
5945
5946 dash = strchr (ale->address, '-');
5947 GNUNET_assert (NULL != dash);
5948 dash++;
5949 GNUNET_asprintf (&address_uri,
5950 "%s://%s",
5951 prefix,
5952 dash);
5954 ale->st = NULL;
5956 "Storing our address `%s' in peerstore until %s!\n",
5957 ale->address,
5960 address_uri);
5961 if (GNUNET_OK != add_success)
5962 {
5964 "Storing our address `%s' %s\n",
5965 address_uri,
5966 GNUNET_NO == add_success ? "not done" : "failed");
5967 GNUNET_free (address_uri);
5968 return;
5969 }
5970 else
5971 {
5972
5974 "Storing our address `%s'\n",
5975 address_uri);
5976 }
5977 // FIXME hello_mono_time used here?? What about expiration in ale?
5979 ale->nt,
5982 &ale->signed_address,
5983 &ale->signed_address_len);
5984 GNUNET_free (address_uri);
5990 "store_pi 1\n");
5992 msg,
5993 shc_cont,
5994 ale);
5995 GNUNET_free (env);
5996}
5997
5998
5999static struct AddressListEntry *
6003 const char *address,
6004 uint32_t aid,
6005 size_t slen)
6006{
6007 struct AddressListEntry *ale;
6008 char *address_without_port;
6009
6010 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6011 ale->tc = tc;
6012 ale->address = (const char *) &ale[1];
6013 ale->expiration = expiration;
6014 ale->aid = aid;
6015 ale->nt = nt;
6016 memcpy (&ale[1], address, slen);
6017 address_without_port = get_address_without_port (ale->address);
6019 "Is this %s a local address (%s)\n",
6020 address_without_port,
6021 ale->address);
6022 if (0 != strcmp ("127.0.0.1", address_without_port))
6023 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6024 GNUNET_free (address_without_port);
6025
6026 return ale;
6027}
6028
6029
6036static void
6038 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6039{
6040 struct TransportClient *tc = cls;
6041 struct AddressListEntry *ale;
6042 size_t slen;
6043 char *address;
6044
6045 /* 0-termination of &aam[1] was checked in #check_add_address */
6047 "Communicator added address `%s'!\n",
6048 (const char *) &aam[1]);
6049 slen = ntohs (aam->header.size) - sizeof(*aam);
6050 address = GNUNET_malloc (slen);
6051 memcpy (address, &aam[1], slen);
6052 ale = create_address_entry (tc,
6054 ntohl (aam->nt),
6055 address,
6056 aam->aid,
6057 slen);
6058 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6059 tc->details.communicator.addr_tail,
6060 ale);
6063}
6064
6065
6072static void
6074 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6075{
6076 struct TransportClient *tc = cls;
6077 struct AddressListEntry *alen;
6078
6079 if (CT_COMMUNICATOR != tc->type)
6080 {
6081 GNUNET_break (0);
6083 return;
6084 }
6085 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6086 NULL != ale;
6087 ale = alen)
6088 {
6089 alen = ale->next;
6090 if (dam->aid != ale->aid)
6091 continue;
6092 GNUNET_assert (ale->tc == tc);
6094 "Communicator deleted address `%s'!\n",
6095 ale->address);
6098 return;
6099 }
6101 "Communicator removed address we did not even have.\n");
6103 // GNUNET_SERVICE_client_drop (tc->client);
6104}
6105
6106
6114static void
6116
6117
6125static void
6127{
6128 struct CoreSentContext *ctx = cls;
6129 struct VirtualLink *vl = ctx->vl;
6130
6131 if (NULL == vl)
6132 {
6133 /* lost the link in the meantime, ignore */
6134 GNUNET_free (ctx);
6135 return;
6136 }
6139 vl->incoming_fc_window_size_ram -= ctx->size;
6140 vl->incoming_fc_window_size_used += ctx->isize;
6142 GNUNET_free (ctx);
6143}
6144
6145
6146static void
6148 const struct GNUNET_MessageHeader *mh,
6149 struct CommunicatorMessageContext *cmc,
6150 unsigned int free_cmc)
6151{
6152 uint16_t size = ntohs (mh->size);
6153 int have_core;
6154
6155 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6156 {
6158 "# CORE messages dropped (FC arithmetic overflow)",
6159 1,
6160 GNUNET_NO);
6162 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6163 (unsigned int) ntohs (mh->type),
6164 (unsigned int) ntohs (mh->size));
6165 if (GNUNET_YES == free_cmc)
6167 return;
6168 }
6170 {
6172 "# CORE messages dropped (FC window overflow)",
6173 1,
6174 GNUNET_NO);
6176 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6177 (unsigned int) ntohs (mh->type),
6178 (unsigned int) ntohs (mh->size));
6179 if (GNUNET_YES == free_cmc)
6181 return;
6182 }
6183
6184 /* Forward to all CORE clients */
6185 have_core = GNUNET_NO;
6186 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6187 {
6188 struct GNUNET_MQ_Envelope *env;
6189 struct InboundMessage *im;
6190 struct CoreSentContext *ctx;
6191
6192 if (CT_CORE != tc->type)
6193 continue;
6196 ctx = GNUNET_new (struct CoreSentContext);
6197 ctx->vl = vl;
6198 ctx->size = size;
6199 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6200 have_core = GNUNET_YES;
6203 im->peer = cmc->im.sender;
6204 memcpy (&im[1], mh, size);
6205 GNUNET_MQ_send (tc->mq, env);
6207 }
6208 if (GNUNET_NO == have_core)
6209 {
6211 "Dropped message to CORE: no CORE client connected!\n");
6212 /* Nevertheless, count window as used, as it is from the
6213 perspective of the other peer! */
6215 /* TODO-M1 */
6217 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6218 (unsigned int) ntohs (mh->type),
6219 (unsigned int) ntohs (mh->size));
6220 if (GNUNET_YES == free_cmc)
6222 return;
6223 }
6225 "Delivered message from %s of type %u to CORE recv window %d\n",
6226 GNUNET_i2s (&cmc->im.sender),
6227 ntohs (mh->type),
6229 if (vl->core_recv_window > 0)
6230 {
6231 if (GNUNET_YES == free_cmc)
6233 return;
6234 }
6235 /* Wait with calling #finish_cmc_handling(cmc) until the message
6236 was processed by CORE MQs (for CORE flow control)! */
6237 if (GNUNET_YES == free_cmc)
6239}
6240
6241
6250static void
6252{
6253 struct CommunicatorMessageContext *cmc = cls;
6254 // struct CommunicatorMessageContext *cmc_copy =
6255 // GNUNET_new (struct CommunicatorMessageContext);
6256 struct GNUNET_MessageHeader *mh_copy;
6257 struct RingBufferEntry *rbe;
6258 struct VirtualLink *vl;
6259 uint16_t size = ntohs (mh->size);
6260
6262 "Handling raw message of type %u with %u bytes\n",
6263 (unsigned int) ntohs (mh->type),
6264 (unsigned int) ntohs (mh->size));
6265
6266 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6267 (size < sizeof(struct GNUNET_MessageHeader)))
6268 {
6269 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6270
6271 GNUNET_break (0);
6272 finish_cmc_handling (cmc);
6274 return;
6275 }
6276 vl = lookup_virtual_link (&cmc->im.sender);
6277 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6278 {
6279 /* FIXME: sender is giving us messages for CORE but we don't have
6280 the link up yet! I *suspect* this can happen right now (i.e.
6281 sender has verified us, but we didn't verify sender), but if
6282 we pass this on, CORE would be confused (link down, messages
6283 arrive). We should investigate more if this happens often,
6284 or in a persistent manner, and possibly do "something" about
6285 it. Thus logging as error for now. */
6286
6287 mh_copy = GNUNET_malloc (size);
6288 rbe = GNUNET_new (struct RingBufferEntry);
6289 rbe->cmc = cmc;
6290 /*cmc_copy->tc = cmc->tc;
6291 cmc_copy->im = cmc->im;*/
6292 GNUNET_memcpy (mh_copy, mh, size);
6293
6294 rbe->mh = mh_copy;
6295
6297 {
6298 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6299 GNUNET_free (rbe_old->cmc);
6300 GNUNET_free (rbe_old->mh);
6301 GNUNET_free (rbe_old);
6302 }
6303 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6304 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6305 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6307 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6308 GNUNET_i2s (&cmc->im.sender),
6309 (unsigned int) ntohs (mh->type),
6310 (unsigned int) ntohs (mh_copy->type),
6314 {
6315 ring_buffer_head = 0;
6317 }
6318 else
6320
6322 "%u items stored in ring buffer\n",
6325
6326 /*GNUNET_break_op (0);
6327 GNUNET_STATISTICS_update (GST_stats,
6328 "# CORE messages dropped (virtual link still down)",
6329 1,
6330 GNUNET_NO);
6331
6332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6333 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6334 (unsigned int) ntohs (mh->type),
6335 (unsigned int) ntohs (mh->size));
6336 finish_cmc_handling (cmc);*/
6339 // GNUNET_free (cmc);
6340 return;
6341 }
6343}
6344
6345
6353static int
6355{
6356 uint16_t size = ntohs (fb->header.size);
6357 uint16_t bsize = size - sizeof(*fb);
6358
6359 (void) cls;
6360 if (0 == bsize)
6361 {
6362 GNUNET_break_op (0);
6363 return GNUNET_SYSERR;
6364 }
6365 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6366 {
6367 GNUNET_break_op (0);
6368 return GNUNET_SYSERR;
6369 }
6370 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6371 {
6372 GNUNET_break_op (0);
6373 return GNUNET_SYSERR;
6374 }
6375 return GNUNET_YES;
6376}
6377
6378
6384static void
6386{
6387 struct AcknowledgementCummulator *ac = cls;
6388
6389 ac->task = NULL;
6390 GNUNET_assert (0 == ac->num_acks);
6392 GNUNET_YES ==
6394 GNUNET_free (ac);
6395}
6396
6397
6403static void
6405{
6406 struct Neighbour *n;
6407 struct VirtualLink *vl;
6408 struct AcknowledgementCummulator *ac = cls;
6409 char buf[sizeof(struct TransportReliabilityAckMessage)
6410 + ac->num_acks
6412 struct TransportReliabilityAckMessage *ack =
6413 (struct TransportReliabilityAckMessage *) buf;
6415
6416 ac->task = NULL;
6418 "Sending ACK with %u components to %s\n",
6419 ac->num_acks,
6420 GNUNET_i2s (&ac->target));
6421 GNUNET_assert (0 < ac->num_acks);
6423 ack->header.size =
6424 htons (sizeof(*ack)
6425 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6426 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6427 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6428 for (unsigned int i = 0; i < ac->num_acks; i++)
6429 {
6430 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6433 }
6434 /*route_control_message_without_fc (
6435 &ac->target,
6436 &ack->header,
6437 RMO_DV_ALLOWED);*/
6438 vl = lookup_virtual_link (&ac->target);
6439 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6440 {
6442 vl,
6443 &ack->header,
6445 }
6446 else
6447 {
6448 /* Use route via neighbour */
6449 n = lookup_neighbour (&ac->target);
6450 if (NULL != n)
6452 n,
6453 &ack->header,
6454 RMO_NONE);
6455 }
6456 ac->num_acks = 0;
6459 ac);
6460}
6461
6462
6471static void
6473 const struct AcknowledgementUUIDP *ack_uuid,
6474 struct GNUNET_TIME_Absolute max_delay)
6475{
6476 struct AcknowledgementCummulator *ac;
6477
6479 "Scheduling ACK %s for transmission to %s\n",
6480 GNUNET_uuid2s (&ack_uuid->value),
6481 GNUNET_i2s (pid));
6483 if (NULL == ac)
6484 {
6486 ac->target = *pid;
6487 ac->min_transmission_time = max_delay;
6491 &ac->target,
6492 ac,
6494 }
6495 else
6496 {
6497 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6498 {
6499 /* must run immediately, ack buffer full! */
6501 }
6505 }
6508 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6509 ac->num_acks++;
6512 ac);
6513}
6514
6515
6520{
6525
6530};
6531
6532
6542static int
6543find_by_message_uuid (void *cls, uint32_t key, void *value)
6544{
6545 struct FindByMessageUuidContext *fc = cls;
6546 struct ReassemblyContext *rc = value;
6547
6548 (void) key;
6549 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6550 {
6551 fc->rc = rc;
6552 return GNUNET_NO;
6553 }
6554 return GNUNET_YES;
6555}
6556
6557
6565static void
6567{
6568 struct CommunicatorMessageContext *cmc = cls;
6569 struct VirtualLink *vl;
6570 struct ReassemblyContext *rc;
6571 const struct GNUNET_MessageHeader *msg;
6572 uint16_t msize;
6573 uint16_t fsize;
6574 uint16_t frag_off;
6575 char *target;
6576 struct GNUNET_TIME_Relative cdelay;
6577 struct FindByMessageUuidContext fc;
6578
6579 vl = lookup_virtual_link (&cmc->im.sender);
6580 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6581 {
6582 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6583
6585 "No virtual link for %s to handle fragment\n",
6586 GNUNET_i2s (&cmc->im.sender));
6587 GNUNET_break (0);
6588 finish_cmc_handling (cmc);
6590 return;
6591 }
6592 if (NULL == vl->reassembly_map)
6593 {
6595 vl->reassembly_heap =
6600 vl);
6601 }
6602 msize = ntohs (fb->msg_size);
6603 fc.message_uuid = fb->msg_uuid;
6604 fc.rc = NULL;
6606 fb->msg_uuid.uuid,
6608 &fc);
6609 fsize = ntohs (fb->header.size) - sizeof(*fb);
6610 if (NULL == (rc = fc.rc))
6611 {
6612 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6613 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6614 rc->msg_uuid = fb->msg_uuid;
6615 rc->virtual_link = vl;
6616 rc->msg_size = msize;
6617 rc->reassembly_timeout =
6621 rc,
6625 vl->reassembly_map,
6626 rc->msg_uuid.uuid,
6627 rc,
6629 target = (char *) &rc[1];
6630 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6631 if (fsize != rc->msg_size)
6632 rc->msg_missing = rc->msg_size;
6633 else
6634 rc->msg_missing = 0;
6636 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6637 PRIu64 "\n",
6638 fsize,
6639 ntohs (fb->frag_off),
6640 msize,
6641 rc->msg_missing,
6642 GNUNET_i2s (&cmc->im.sender),
6643 fb->msg_uuid.uuid);
6644 }
6645 else
6646 {
6647 target = (char *) &rc[1];
6649 "Received fragment at offset %u/%u from %s for message %u\n",
6650 ntohs (fb->frag_off),
6651 msize,
6652 GNUNET_i2s (&cmc->im.sender),
6653 (unsigned int) fb->msg_uuid.uuid);
6654 }
6655 if (msize != rc->msg_size)
6656 {
6657 GNUNET_break (0);
6658 finish_cmc_handling (cmc);
6659 return;
6660 }
6661
6662 /* reassemble */
6663 if (0 == fsize)
6664 {
6665 GNUNET_break (0);
6666 finish_cmc_handling (cmc);
6667 return;
6668 }
6669 frag_off = ntohs (fb->frag_off);
6670 if (frag_off + fsize > msize)
6671 {
6672 /* Fragment (plus fragment size) exceeds message size! */
6673 GNUNET_break_op (0);
6674 finish_cmc_handling (cmc);
6675 return;
6676 }
6677 memcpy (&target[frag_off], &fb[1], fsize);
6678 /* update bitfield and msg_missing */
6679 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6680 {
6681 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6682 {
6683 rc->bitfield[i / 8] |= (1 << (i % 8));
6684 rc->msg_missing--;
6685 }
6686 }
6687
6688 /* Compute cumulative ACK */
6690 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6691 if (0 == rc->msg_missing)
6692 cdelay = GNUNET_TIME_UNIT_ZERO;
6693 cummulative_ack (&cmc->im.sender,
6694 &fb->ack_uuid,
6697 /* is reassembly complete? */
6698 if (0 != rc->msg_missing)
6699 {
6700 finish_cmc_handling (cmc);
6701 return;
6702 }
6703 /* reassembly is complete, verify result */
6704 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6705 if (ntohs (msg->size) != rc->msg_size)
6706 {
6707 GNUNET_break (0);
6709 finish_cmc_handling (cmc);
6710 return;
6711 }
6712 /* successful reassembly */
6714 "Fragment reassembly complete for message %u\n",
6715 (unsigned int) fb->msg_uuid.uuid);
6716 /* FIXME: check that the resulting msg is NOT a
6717 DV Box or Reliability Box, as that is NOT allowed! */
6718 cmc->mh = msg;
6720 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6721 en-route and we forget that we finished this reassembly immediately!
6722 -> keep around until timeout?
6723 -> shorten timeout based on ACK? */
6725}
6726
6727
6735static int
6737 const struct TransportReliabilityBoxMessage *rb)
6738{
6739 const struct GNUNET_MessageHeader *box = (const struct
6740 GNUNET_MessageHeader *) &rb[1];
6741 (void) cls;
6742
6744 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6745 ntohs (rb->header.size),
6746 ntohs (box->type),
6747 ntohs (box->size),
6748 sizeof (struct TransportReliabilityBoxMessage),
6749 sizeof (struct GNUNET_MessageHeader));
6751 return GNUNET_YES;
6752}
6753
6754
6762static void
6764 const struct TransportReliabilityBoxMessage *rb)
6765{
6766 struct CommunicatorMessageContext *cmc = cls;
6767 const struct GNUNET_MessageHeader *inbox =
6768 (const struct GNUNET_MessageHeader *) &rb[1];
6769 struct GNUNET_TIME_Relative rtt;
6770
6772 "Received reliability box from %s with UUID %s of type %u\n",
6773 GNUNET_i2s (&cmc->im.sender),
6775 (unsigned int) ntohs (inbox->type));
6776 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6777 do not really have an RTT for the
6778 * incoming* queue (should we have
6779 the sender add it to the rb message?) */
6781 &cmc->im.sender,
6782 &rb->ack_uuid,
6783 (0 == ntohl (rb->ack_countdown))
6786 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6787 /* continue with inner message */
6788 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6789 reliability box (not allowed!) */
6790 cmc->mh = inbox;
6792}
6793
6794
6803static void
6804update_pd_age (struct PerformanceData *pd, unsigned int age)
6805{
6806 unsigned int sage;
6807
6808 if (age == pd->last_age)
6809 return; /* nothing to do */
6810 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6811 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6812 {
6813 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6814
6815 the->bytes_sent = 0;
6816 the->bytes_received = 0;
6817 }
6818 pd->last_age = age;
6819}
6820
6821
6830static void
6832 struct GNUNET_TIME_Relative rtt,
6833 uint16_t bytes_transmitted_ok)
6834{
6835 uint64_t nval = rtt.rel_value_us;
6836 uint64_t oval = pd->aged_rtt.rel_value_us;
6837 unsigned int age = get_age ();
6838 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
6839
6840 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
6841 pd->aged_rtt = rtt;
6842 else
6843 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
6844 update_pd_age (pd, age);
6845 the->bytes_received += bytes_transmitted_ok;
6846}
6847
6848
6856static void
6858 struct GNUNET_TIME_Relative rtt,
6859 uint16_t bytes_transmitted_ok)
6860{
6861 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
6862}
6863
6864
6872static void
6874 struct GNUNET_TIME_Relative rtt,
6875 uint16_t bytes_transmitted_ok)
6876{
6877 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
6878}
6879
6880
6888static void
6890{
6891 struct PendingMessage *pos;
6892
6894 "Complete transmission of message %" PRIu64 " %u\n",
6895 pm->logging_uuid,
6896 pm->pmt);
6897 switch (pm->pmt)
6898 {
6899 case PMT_CORE:
6901 /* Full message sent, we are done */
6903 return;
6904
6905 case PMT_FRAGMENT_BOX:
6906 /* Fragment sent over reliable channel */
6907 pos = pm->frag_parent;
6911 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
6912 (unsigned long) pos->frag_off,
6913 (unsigned long) pos->bytes_msg,
6914 pos->pmt,
6915 NULL == pos->frag_parent ? 1 : 0);
6916 /* check if subtree is done */
6917 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
6918 - sizeof(struct
6920 &&
6921 (NULL != pos->frag_parent))
6922 {
6923 pm = pos;
6924 pos = pm->frag_parent;
6925 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
6926 {
6928 return;
6929 }
6930 else if (PMT_DV_BOX == pm->pmt)
6931 {
6933 return;
6934 }
6937 }
6938
6939 /* Was this the last applicable fragment? */
6940 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
6941 pos->pmt) &&
6942 (pos->frag_off == pos->bytes_msg))
6944 return;
6945
6946 case PMT_DV_BOX:
6948 "Completed transmission of message %" PRIu64 " (DV Box)\n",
6949 pm->logging_uuid);
6950 if (NULL != pm->frag_parent)
6951 {
6952 pos = pm->frag_parent;
6954 pos->bpm = NULL;
6956 }
6957 else
6959 return;
6960 }
6961}
6962
6963
6971static void
6973 struct GNUNET_TIME_Relative ack_delay)
6974{
6975 struct GNUNET_TIME_Relative delay;
6976
6978 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
6979 if (NULL != pa->queue && 1 == pa->num_send)
6981 if (NULL != pa->dvh && 1 == pa->num_send)
6982 update_dvh_performance (pa->dvh, delay, pa->message_size);
6983 if (NULL != pa->pm)
6986}
6987
6988
6996static int
6998 const struct TransportReliabilityAckMessage *ra)
6999{
7000 unsigned int n_acks;
7001
7002 (void) cls;
7003 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7004 / sizeof(struct TransportCummulativeAckPayloadP);
7005 if (0 == n_acks)
7006 {
7007 GNUNET_break_op (0);
7008 return GNUNET_SYSERR;
7009 }
7010 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7011 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7012 {
7013 GNUNET_break_op (0);
7014 return GNUNET_SYSERR;
7015 }
7016 return GNUNET_OK;
7017}
7018
7019
7027static void
7029 const struct TransportReliabilityAckMessage *ra)
7030{
7031 struct CommunicatorMessageContext *cmc = cls;
7032 const struct TransportCummulativeAckPayloadP *ack;
7033 unsigned int n_acks;
7034 uint32_t ack_counter;
7035
7036 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7037 / sizeof(struct TransportCummulativeAckPayloadP);
7038 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7039 for (unsigned int i = 0; i < n_acks; i++)
7040 {
7041 struct PendingAcknowledgement *pa =
7043 if (NULL == pa)
7044 {
7046 "Received ACK from %s with UUID %s which is unknown to us!\n",
7047 GNUNET_i2s (&cmc->im.sender),
7048 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7050 GST_stats,
7051 "# FRAGMENT_ACKS dropped, no matching pending message",
7052 1,
7053 GNUNET_NO);
7054 continue;
7055 }
7057 "Received ACK from %s with UUID %s\n",
7058 GNUNET_i2s (&cmc->im.sender),
7059 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7060 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7061 }
7062
7063 ack_counter = htonl (ra->ack_counter);
7064 (void) ack_counter; /* silence compiler warning for now */
7065 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7066 // (DV and/or Neighbour?)
7067 finish_cmc_handling (cmc);
7068}
7069
7070
7078static int
7080 void *cls,
7082{
7083 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7084 const struct GNUNET_MessageHeader *inbox =
7085 (const struct GNUNET_MessageHeader *) &be[1];
7086 const char *is;
7087 uint16_t isize;
7088
7089 (void) cls;
7090 if (ntohs (inbox->size) >= size)
7091 {
7092 GNUNET_break_op (0);
7093 return GNUNET_SYSERR;
7094 }
7095 isize = ntohs (inbox->size);
7096 is = ((const char *) inbox) + isize;
7097 size -= isize;
7098 if ('\0' != is[size - 1])
7099 {
7100 GNUNET_break_op (0);
7101 return GNUNET_SYSERR;
7102 }
7103 return GNUNET_YES;
7104}
7105
7106
7115static void
7117 void *cls,
7119{
7120 struct CommunicatorMessageContext *cmc = cls;
7122 struct GNUNET_MQ_Envelope *env;
7123 struct TransportClient *tc;
7124 const struct GNUNET_MessageHeader *inbox =
7125 (const struct GNUNET_MessageHeader *) &be[1];
7126 uint16_t isize = ntohs (inbox->size);
7127 const char *target_communicator = ((const char *) inbox) + isize;
7128 char *sender;
7129 char *self;
7130
7131 GNUNET_asprintf (&sender,
7132 "%s",
7133 GNUNET_i2s (&cmc->im.sender));
7134 GNUNET_asprintf (&self,
7135 "%s",
7137
7138 /* Find client providing this communicator */
7139 for (tc = clients_head; NULL != tc; tc = tc->next)
7140 if ((CT_COMMUNICATOR == tc->type) &&
7141 (0 ==
7142 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7143 break;
7144 if (NULL == tc)
7145 {
7146 char *stastr;
7147
7149 &stastr,
7150 "# Backchannel message dropped: target communicator `%s' unknown",
7151 target_communicator);
7153 GNUNET_free (stastr);
7154 finish_cmc_handling (cmc);
7155 return;
7156 }
7157 /* Finally, deliver backchannel message to communicator */
7159 "Delivering backchannel message from %s to %s of type %u to %s\n",
7160 sender,
7161 self,
7162 ntohs (inbox->type),
7163 target_communicator);
7165 cbi,
7166 isize,
7168 cbi->pid = cmc->im.sender;
7169 memcpy (&cbi[1], inbox, isize);
7170 GNUNET_MQ_send (tc->mq, env);
7171 finish_cmc_handling (cmc);
7172}
7173
7174
7184static void
7186{
7187 struct DistanceVector *dv = cls;
7188 struct DistanceVectorHop *pos;
7189
7190 dv->timeout_task = NULL;
7191 while (NULL != (pos = dv->dv_head))
7192 {
7193 GNUNET_assert (dv == pos->dv);
7195 break;
7197 }
7198 if (NULL == pos)
7199 {
7200 free_dv_route (dv);
7201 return;
7202 }
7203 dv->timeout_task =
7205}
7206
7207
7208static void
7210{
7211
7212 const struct GNUNET_PeerIdentity target = vl->target;
7213
7214
7216 {
7217 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7218 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7219 0;
7220 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7223 struct CommunicatorMessageContext *cmc;
7224 struct RingBufferEntry *rbe;
7225 struct GNUNET_MessageHeader *mh;
7226
7228 "Sending from ring buffer, which has %u items\n",
7229 head);
7230
7231 ring_buffer_head = 0;
7232 for (unsigned int i = 0; i < head; i++)
7233 {
7234 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7235 cmc = rbe->cmc;
7236 mh = rbe->mh;
7237
7238 im = cmc->im;
7239 // mh = cmc->mh;
7241 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7242 mh->type,
7243 GNUNET_i2s (&im.sender),
7244 GNUNET_i2s2 (&target),
7245 (i + tail) % RING_BUFFER_SIZE);
7246 if (0 == GNUNET_memcmp (&target, &im.sender))
7247 {
7249 "Finish handling message of type %u and size %u\n",
7250 (unsigned int) ntohs (mh->type),
7251 (unsigned int) ntohs (mh->size));
7253 GNUNET_free (mh);
7254 GNUNET_free (rbe->cmc);
7255 GNUNET_free (rbe);
7256 }
7257 else
7258 {
7259 ring_buffer_copy[ring_buffer_head] = rbe;
7261 }
7262 }
7263
7266 {
7268 }
7269
7270 for (unsigned int i = 0; i < ring_buffer_head; i++)
7271 {
7272 ring_buffer[i] = ring_buffer_copy[i];
7274 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7275 i,
7276 ring_buffer_copy[i]->mh->type);
7278 "ring_buffer[i]->mh->type for i %u %u\n",
7279 i,
7280 ring_buffer[i]->mh->type);
7281 }
7282
7284 "%u items still in ring buffer\n",
7286 }
7287
7289 {
7290 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7291 struct PendingMessage *pm;
7292 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7294 0;
7295 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7298
7300 "Sending from ring buffer dv, which has %u items\n",
7301 head);
7302
7304 for (unsigned int i = 0; i < head; i++)
7305 {
7306 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7307
7309 "Sending to ring buffer target %s using vl target %s\n",
7310 GNUNET_i2s (&pm->target),
7311 GNUNET_i2s2 (&target));
7312 if (0 == GNUNET_memcmp (&target, &pm->target))
7313 {
7315 "Adding PendingMessage to vl, checking transmission.\n");
7316 pm->vl = vl;
7320 pm);
7321
7323 }
7324 else
7325 {
7326 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7328 }
7329 }
7330
7332 {
7334 }
7335
7336 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7337 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7338
7340 "%u items still in ring buffer dv.\n",
7342
7343 }
7344}
7345
7346
7354static void
7356{
7357 struct DistanceVector *dv = hop->dv;
7358 struct VirtualLink *vl;
7359
7360 vl = lookup_virtual_link (&dv->target);
7361 if (NULL == vl)
7362 {
7363
7364 vl = GNUNET_new (struct VirtualLink);
7366 "Creating new virtual link %p to %s using DV!\n",
7367 vl,
7368 GNUNET_i2s (&dv->target));
7369 vl->burst_addr = NULL;
7370 vl->confirmed = GNUNET_YES;
7371 vl->message_uuid_ctr =
7373 vl->target = dv->target;
7379 links,
7380 &vl->target,
7381 vl,
7383 vl->dv = dv;
7384 dv->vl = vl;
7385 vl->visibility_task =
7388 /* We lacked a confirmed connection to the target
7389 before, so tell CORE about it (finally!) */
7392 }
7393 else
7394 {
7395 /* Link was already up, remember dv is also now available and we are done */
7396 vl->dv = dv;
7397 dv->vl = vl;
7398 if (GNUNET_NO == vl->confirmed)
7399 {
7400 vl->confirmed = GNUNET_YES;
7401 vl->visibility_task =
7404 /* We lacked a confirmed connection to the target
7405 before, so tell CORE about it (finally!) */
7408 }
7409 else
7411 "Virtual link to %s could now also use DV!\n",
7412 GNUNET_i2s (&dv->target));
7413 }
7414}
7415
7416
7442static int
7444 unsigned int path_len,
7445 struct GNUNET_TIME_Relative network_latency,
7446 struct GNUNET_TIME_Absolute path_valid_until)
7447{
7448 struct DistanceVectorHop *hop;
7449 struct DistanceVector *dv;
7450 struct Neighbour *next_hop;
7451 unsigned int shorter_distance;
7452
7453 if (path_len < 3)
7454 {
7455 /* what a boring path! not allowed! */
7456 GNUNET_break (0);
7457 return GNUNET_SYSERR;
7458 }
7459 GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
7460 next_hop = lookup_neighbour (&path[1]);
7461 if (NULL == next_hop)
7462 {
7463 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7464 GNUNET_break (0);
7465 return GNUNET_SYSERR;
7466 }
7467 for (unsigned int i = 2; i < path_len; i++)
7468 {
7469 struct Neighbour *n = lookup_neighbour (&path[i]);
7470 struct GNUNET_TIME_Absolute q_timeout;
7471
7472 if (NULL != n)
7473 {
7474 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7475 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7476 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7478 "remaining %lu to %s\n",
7479 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7480 .rel_value_us,
7481 GNUNET_i2s (&n->pid));
7482 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7483 {
7484 /* Useless path: we have a direct active connection to some hop
7485 in the middle of the path, so this one is not even
7486 terribly useful for redundancy */
7488 "Path of %u hops useless: directly link to hop %u (%s)\n",
7489 path_len,
7490 i,
7491 GNUNET_i2s (&path[i]));
7493 "# Useless DV path ignored: hop is neighbour",
7494 1,
7495 GNUNET_NO);
7496 return GNUNET_SYSERR;
7497 }
7498 }
7499 }
7500 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7501 if (NULL == dv)
7502 {
7503 dv = GNUNET_new (struct DistanceVector);
7504 dv->target = path[path_len - 1];
7507 dv);
7510 dv_routes,
7511 &dv->target,
7512 dv,
7514 }
7515 /* Check if we have this path already! */
7516 shorter_distance = 0;
7517 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7518 pos = pos->next_dv)
7519 {
7520 if (pos->distance < path_len - 3)
7521 shorter_distance++;
7522 /* Note that the distances in 'pos' excludes us (path[0]),
7523 the next_hop (path[1]) and the target so we need to subtract three
7524 and check next_hop explicitly */
7525 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7526 {
7527 int match = GNUNET_YES;
7528
7529 for (unsigned int i = 0; i < pos->distance; i++)
7530 {
7531 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7532 {
7533 match = GNUNET_NO;
7534 break;
7535 }
7536 }
7537 if (GNUNET_YES == match)
7538 {
7539 struct GNUNET_TIME_Relative last_timeout;
7540
7541 /* Re-discovered known path, update timeout */
7543 "# Known DV path refreshed",
7544 1,
7545 GNUNET_NO);
7546 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7547 pos->timeout =
7549 pos->path_valid_until =
7550 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7551 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7552 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7553 if (0 <
7556 if (last_timeout.rel_value_us <
7559 .rel_value_us)
7560 {
7561 /* Some peer send DV learn messages too often, we are learning
7562 the same path faster than it would be useful; do not forward! */
7564 "Rediscovered path too quickly, not forwarding further\n")
7565 ;
7566 return GNUNET_NO;
7567 }
7569 "Refreshed known path to %s valid until %s, forwarding further\n",
7570 GNUNET_i2s (&dv->target),
7572 pos->path_valid_until));
7573 return GNUNET_YES;
7574 }
7575 }
7576 }
7577 /* Count how many shorter paths we have (incl. direct
7578 neighbours) before simply giving up on this one! */
7579 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7580 {
7581 /* We have a shorter path already! */
7583 "Have many shorter DV paths %s, not forwarding further\n",
7584 GNUNET_i2s (&dv->target));
7585 return GNUNET_NO;
7586 }
7587 /* create new DV path entry */
7589 "Discovered new DV path to %s valid until %s\n",
7590 GNUNET_i2s (&dv->target),
7591 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7592 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7593 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7594 hop->next_hop = next_hop;
7595 hop->dv = dv;
7596 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7597 memcpy (&hop[1],
7598 &path[2],
7599 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7601 hop->path_valid_until = path_valid_until;
7602 hop->distance = path_len - 3;
7603 hop->pd.aged_rtt = network_latency;
7604 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7606 next_hop->dv_head,
7607 next_hop->dv_tail,
7608 hop);
7609 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7611 return GNUNET_YES;
7612}
7613
7614
7622static int
7623check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7624{
7625 uint16_t size = ntohs (dvl->header.size);
7626 uint16_t num_hops = ntohs (dvl->num_hops);
7627 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7628
7629 (void) cls;
7630 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7631 {
7632 GNUNET_break_op (0);
7633 return GNUNET_SYSERR;
7634 }
7635 if (num_hops > MAX_DV_HOPS_ALLOWED)
7636 {
7637 GNUNET_break_op (0);
7638 return GNUNET_SYSERR;
7639 }
7640 for (unsigned int i = 0; i < num_hops; i++)
7641 {
7642 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7643 {
7644 GNUNET_break_op (0);
7645 return GNUNET_SYSERR;
7646 }
7647 if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
7648 {
7649 GNUNET_break_op (0);
7650 return GNUNET_SYSERR;
7651 }
7652 }
7653 return GNUNET_YES;
7654}
7655
7656
7668static void
7670 const struct TransportDVLearnMessage *msg,
7671 uint16_t bi_history,
7672 uint16_t nhops,
7673 const struct DVPathEntryP *hops,
7674 struct GNUNET_TIME_Absolute in_time)
7675{
7676 struct Neighbour *n;
7677 struct VirtualLink *vl;
7678 struct DVPathEntryP *dhops;
7679 char buf[sizeof(struct TransportDVLearnMessage)
7680 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7681 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7682 struct GNUNET_TIME_Relative nnd;
7683
7684 /* compute message for forwarding */
7686 "Forwarding DV learn message originating from %s to %s\n",
7687 GNUNET_i2s (&msg->initiator),
7688 GNUNET_i2s2 (next_hop));
7691 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7692 + (nhops + 1) * sizeof(struct DVPathEntryP));
7693 fwd->num_hops = htons (nhops + 1);
7694 fwd->bidirectional = htons (bi_history);
7697 msg->non_network_delay));
7699 fwd->init_sig = msg->init_sig;
7700 fwd->initiator = msg->initiator;
7701 fwd->challenge = msg->challenge;
7702 fwd->monotonic_time = msg->monotonic_time;
7703 dhops = (struct DVPathEntryP *) &fwd[1];
7704 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7705 dhops[nhops].hop = GST_my_identity;
7706 {
7707 struct DvHopPS dhp = {
7709 .purpose.size = htonl (sizeof(dhp)),
7710 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7711 .succ = *next_hop,
7712 .challenge = msg->challenge
7713 };
7715 &dhp,
7716 &dhops[nhops].hop_sig);
7717 }
7718 /*route_control_message_without_fc (next_hop,
7719 &fwd->header,
7720 RMO_UNCONFIRMED_ALLOWED);*/
7721 vl = lookup_virtual_link (next_hop);
7722 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7723 {
7725 &fwd->header,
7727 }
7728 else
7729 {
7730 /* Use route via neighbour */
7731 n = lookup_neighbour (next_hop);
7732 if (NULL != n)
7734 n,
7735 &fwd->header,
7737 }
7738}
7739
7740
7750static int
7752 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
7753 const struct GNUNET_PeerIdentity *init,
7755 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
7756{
7757 struct DvInitPS ip = { .purpose.purpose = htonl (
7759 .purpose.size = htonl (sizeof(ip)),
7760 .monotonic_time = sender_monotonic_time,
7761 .challenge = *challenge };
7762
7763 if (
7764 GNUNET_OK !=
7766 &ip,
7767 init_sig,
7768 &init->public_key))
7769 {
7770 GNUNET_break_op (0);
7771 return GNUNET_SYSERR;
7772 }
7773 return GNUNET_OK;
7774}
7775
7776
7781{
7786
7790 const struct DVPathEntryP *hops;
7791
7796
7801
7805 unsigned int num_eligible;
7806
7810 unsigned int num_selections;
7811
7815 uint16_t nhops;
7816
7820 uint16_t bi_history;
7821};
7822
7823
7832static int
7834 const struct GNUNET_PeerIdentity *pid,
7835 void *value)
7836{
7837 struct NeighbourSelectionContext *nsc = cls;
7838
7839 (void) value;
7840 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7841 return GNUNET_YES; /* skip initiator */
7842 for (unsigned int i = 0; i < nsc->nhops; i++)
7843 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7844 return GNUNET_YES;
7845 /* skip peers on path */
7846 nsc->num_eligible++;
7847 return GNUNET_YES;
7848}
7849
7850
7861static int
7863 const struct GNUNET_PeerIdentity *pid,
7864 void *value)
7865{
7866 struct NeighbourSelectionContext *nsc = cls;
7867
7869 "transmission %s\n",
7870 GNUNET_i2s (pid));
7871 (void) value;
7872 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7873 return GNUNET_YES; /* skip initiator */
7874 for (unsigned int i = 0; i < nsc->nhops; i++)
7875 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7876 return GNUNET_YES;
7877 /* skip peers on path */
7878 for (unsigned int i = 0; i < nsc->num_selections; i++)
7879 {
7880 if (nsc->selections[i] == nsc->num_eligible)
7881 {
7883 nsc->dvl,
7884 nsc->bi_history,
7885 nsc->nhops,
7886 nsc->hops,
7887 nsc->in_time);
7888 break;
7889 }
7890 }
7891 nsc->num_eligible++;
7892 return GNUNET_YES;
7893}
7894
7895
7939static unsigned int
7940calculate_fork_degree (unsigned int hops_taken,
7941 unsigned int neighbour_count,
7942 unsigned int eligible_count)
7943{
7944 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
7945 double eligible_ratio =
7946 ((double) eligible_count) / ((double) neighbour_count);
7947 double boost_factor = eligible_ratio * eligible_ratio;
7948 unsigned int rnd;
7949 double left;
7950
7951 if (hops_taken >= 64)
7952 {
7953 GNUNET_break (0);
7954 return 0; /* precaution given bitshift below */
7955 }
7956 for (unsigned int i = 1; i < hops_taken; i++)
7957 {
7958 /* For each hop, subtract the expected number of targets
7959 reached at distance d (so what remains divided by 2^d) */
7960 target_total -= (target_total * boost_factor / (1LLU << i));
7961 }
7962 rnd =
7963 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
7964 /* round up or down probabilistically depending on how close we were
7965 when floor()ing to rnd */
7966 left = target_total - (double) rnd;
7967 if (UINT32_MAX * left >
7969 rnd++; /* round up */
7971 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
7972 hops_taken,
7973 rnd,
7974 eligible_count,
7975 neighbour_count);
7976 return rnd;
7977}
7978
7979
7986static void
7987neighbour_store_dvmono_cb (void *cls, int success)
7988{
7989 struct Neighbour *n = cls;
7990
7991 n->sc = NULL;
7992 if (GNUNET_YES != success)
7994 "Failed to store other peer's monotonic time in peerstore!\n");
7995}
7996
7997
7998static struct GNUNET_TIME_Relative
8000{
8001 struct GNUNET_TIME_Relative host_latency_sum;
8002 struct GNUNET_TIME_Relative latency;
8003 struct GNUNET_TIME_Relative network_latency;
8004 uint16_t nhops = ntohs (dvl->num_hops);;
8005
8006 /* We initiated this, learn the forward path! */
8007 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8008
8009 // Need also something to lookup initiation time
8010 // to compute RTT! -> add RTT argument here?
8012 dvl->monotonic_time));
8013 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8014 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8015 // (based on dvl->challenge, we can identify time of origin!)
8016
8017 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8018 /* assumption: latency on all links is the same */
8019 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8020
8021 return network_latency;
8022}
8023
8024
8032static void
8033handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8034{
8035 struct CommunicatorMessageContext *cmc = cls;
8037 int bi_hop;
8038 uint16_t nhops;
8039 uint16_t bi_history;
8040 const struct DVPathEntryP *hops;
8041 int do_fwd;
8042 int did_initiator;
8043 struct GNUNET_TIME_Absolute in_time;
8044 struct Neighbour *n;
8045
8046 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8047 bi_history = ntohs (dvl->bidirectional);
8048 hops = (const struct DVPathEntryP *) &dvl[1];
8049 if (0 == nhops)
8050 {
8051 /* sanity check */
8052 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8053 {
8054 GNUNET_break (0);
8055 finish_cmc_handling (cmc);
8056 return;
8057 }
8058 }
8059 else
8060 {
8062 "handle dv learn message last hop %s\n",
8063 GNUNET_i2s (&hops[nhops - 1].hop));
8064 /* sanity check */
8065 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8066 {
8067 GNUNET_break (0);
8068 finish_cmc_handling (cmc);
8069 return;
8070 }
8071 }
8072
8074 cc = cmc->tc->details.communicator.cc;
8075 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8076 cc); // FIXME: add bi-directional flag to cc?
8077 in_time = GNUNET_TIME_absolute_get ();
8078
8079 /* continue communicator here, everything else can happen asynchronous! */
8080 finish_cmc_handling (cmc);
8081
8082 n = lookup_neighbour (&dvl->initiator);
8083 if (NULL != n)
8084 {
8085 if ((n->dv_monotime_available == GNUNET_YES) &&
8088 {
8090 "DV learn from %s discarded due to time travel",
8091 GNUNET_i2s (&dvl->initiator));
8093 "# DV learn discarded due to time travel",
8094 1,
8095 GNUNET_NO);
8096 return;
8097 }
8099 &dvl->initiator,
8100 &dvl->challenge,
8101 &dvl->init_sig))
8102 {
8104 "DV learn signature from %s invalid\n",
8105 GNUNET_i2s (&dvl->initiator));
8106 GNUNET_break_op (0);
8107 return;
8108 }
8111 {
8112 if (NULL != n->sc)
8113 {
8115 "store cancel\n");
8117 }
8118 n->sc =
8120 "transport",
8121 &dvl->initiator,
8123 &dvl->monotonic_time,
8124 sizeof(dvl->monotonic_time),
8128 n);
8129 }
8130 }
8131 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8132 If signature verification load too high, implement random drop strategy */
8133 for (unsigned int i = 0; i < nhops; i++)
8134 {
8135 struct DvHopPS dhp = { .purpose.purpose =
8137 .purpose.size = htonl (sizeof(dhp)),
8138 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8139 .succ = (nhops == i + 1) ? GST_my_identity
8140 : hops[i + 1].hop,
8141 .challenge = dvl->challenge };
8142
8143 if (GNUNET_OK !=
8145 &dhp,
8146 &hops[i].hop_sig,
8147 &hops[i].hop.public_key))
8148 {
8150 "DV learn from %s signature of hop %u invalid\n",
8151 GNUNET_i2s (&dvl->initiator),
8152 i);
8154 "signature of hop %s invalid\n",
8155 GNUNET_i2s (&hops[i].hop));
8157 "pred %s\n",
8158 GNUNET_i2s (&dhp.pred));
8160 "succ %s\n",
8161 GNUNET_i2s (&dhp.succ));
8163 "hash %s\n",
8164 GNUNET_sh2s (&dhp.challenge.value));
8165 GNUNET_break_op (0);
8166 return;
8167 }
8168 }
8169 if (GNUNET_EXTRA_LOGGING > 0)
8170 {
8171 char *path;
8172
8173 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8174 for (unsigned int i = 0; i < nhops; i++)
8175 {
8176 char *tmp;
8177
8178 GNUNET_asprintf (&tmp,
8179 "%s%s%s",
8180 path,
8181 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8182 GNUNET_i2s (&hops[i].hop));
8183 GNUNET_free (path);
8184 path = tmp;
8185 }
8187 "Received DVInit via %s%s%s\n",
8188 path,
8189 bi_hop ? "<->" : "-->",
8191 GNUNET_free (path);
8192 }
8193 do_fwd = GNUNET_YES;
8194 if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
8195 {
8196 struct GNUNET_PeerIdentity path[nhops + 1];
8197 struct GNUNET_TIME_Relative network_latency;
8198
8199 /* We initiated this, learn the forward path! */
8200 path[0] = GST_my_identity;
8201 path[1] = hops[0].hop;
8202
8203 network_latency = get_network_latency (dvl);
8204
8205 for (unsigned int i = 2; i <= nhops; i++)
8206 {
8207 struct GNUNET_TIME_Relative ilat;
8208
8209 /* assumption: linear latency increase per hop */
8210 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8211 path[i] = hops[i - 1].hop;
8213 "Learned path with %u hops to %s with latency %s\n",
8214 i,
8215 GNUNET_i2s (&path[i]),
8217 learn_dv_path (path,
8218 i + 1,
8219 ilat,
8222 }
8223 /* as we initiated, do not forward again (would be circular!) */
8224 do_fwd = GNUNET_NO;
8225 return;
8226 }
8227 if (bi_hop)
8228 {
8229 /* last hop was bi-directional, we could learn something here! */
8230 struct GNUNET_PeerIdentity path[nhops + 2];
8231 struct GNUNET_TIME_Relative ilat;
8232 struct GNUNET_TIME_Relative network_latency;
8233
8234 path[0] = GST_my_identity;
8235 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8236 for (unsigned int i = 0; i < nhops; i++)
8237 {
8238 int iret;
8239
8240 if (0 == (bi_history & (1 << i)))
8241 break; /* i-th hop not bi-directional, stop learning! */
8242 if (i == nhops - 1)
8243 {
8244 path[i + 2] = dvl->initiator;
8245 }
8246 else
8247 {
8248 path[i + 2] = hops[nhops - i - 2].hop;
8249 }
8250
8252 "Learned inverse path with %u hops to %s\n",
8253 i + 2,
8254 GNUNET_i2s (&path[i + 2]));
8255 network_latency = get_network_latency (dvl);
8256 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8257 iret = learn_dv_path (path,
8258 i + 3,
8259 ilat,
8262 if (GNUNET_SYSERR == iret)
8263 {
8264 /* path invalid or too long to be interesting for US, thus should also
8265 not be interesting to our neighbours, cut path when forwarding to
8266 'i' hops, except of course for the one that goes back to the
8267 initiator */
8269 "# DV learn not forwarded due invalidity of path",
8270 1,
8271 GNUNET_NO);
8272 do_fwd = GNUNET_NO;
8273 break;
8274 }
8275 if ((GNUNET_NO == iret) && (nhops == i + 1))
8276 {
8277 /* we have better paths, and this is the longest target,
8278 so there cannot be anything interesting later */
8280 "# DV learn not forwarded, got better paths",
8281 1,
8282 GNUNET_NO);
8283 do_fwd = GNUNET_NO;
8284 break;
8285 }
8286 }
8287 }
8288 if (MAX_DV_HOPS_ALLOWED == nhops)
8289 {
8290 /* At limit, we're out of here! */
8291 return;
8292 }
8293
8294 /* Forward to initiator, if path non-trivial and possible */
8295 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8296 did_initiator = GNUNET_NO;
8297 if ((1 <= nhops) &&
8298 (GNUNET_YES ==
8300 {
8301 /* send back to origin! */
8303 "Sending DVL back to initiator %s\n",
8304 GNUNET_i2s (&dvl->initiator));
8305 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8306 did_initiator = GNUNET_YES;
8307 }
8308 /* We forward under two conditions: either we still learned something
8309 ourselves (do_fwd), or the path was darn short and thus the initiator is
8310 likely to still be very interested in this (and we did NOT already
8311 send it back to the initiator) */
8312 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8313 (GNUNET_NO == did_initiator)))
8314 {
8315 /* Pick random neighbours that are not yet on the path */
8316 struct NeighbourSelectionContext nsc;
8317 unsigned int n_cnt;
8318
8320 nsc.nhops = nhops;
8321 nsc.dvl = dvl;
8322 nsc.bi_history = bi_history;
8323 nsc.hops = hops;
8324 nsc.in_time = in_time;
8325 nsc.num_eligible = 0;
8328 &nsc);
8329 if (0 == nsc.num_eligible)
8330 return; /* done here, cannot forward to anyone else */
8332 nsc.num_selections =
8335 "Forwarding DVL to %u other peers\n",
8336 nsc.num_selections);
8337 for (unsigned int i = 0; i < nsc.num_selections; i++)
8338 nsc.selections[i] =
8339 (nsc.num_selections == n_cnt)
8340 ? i /* all were selected, avoid collisions by chance */
8342 nsc.num_eligible = 0;
8345 &nsc);
8346 }
8347}
8348
8349
8357static int
8358check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8359{
8360 uint16_t size = ntohs (dvb->header.size);
8361 uint16_t num_hops = ntohs (dvb->num_hops);
8362 const struct GNUNET_PeerIdentity *hops =
8363 (const struct GNUNET_PeerIdentity *) &dvb[1];
8364
8365 (void) cls;
8366 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8367 + sizeof(struct GNUNET_MessageHeader))
8368 {
8369 GNUNET_break_op (0);
8370 return GNUNET_SYSERR;
8371 }
8372 /* This peer must not be on the path */
8373 for (unsigned int i = 0; i < num_hops; i++)
8374 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8375 {
8376 GNUNET_break_op (0);
8377 return GNUNET_SYSERR;
8378 }
8379 return GNUNET_YES;
8380}
8381
8382
8395static void
8396forward_dv_box (struct Neighbour *next_hop,
8397 struct TransportDVBoxMessage *hdr,
8398 uint16_t total_hops,
8399 uint16_t num_hops,
8400 const struct GNUNET_PeerIdentity *hops,
8401 const void *enc_payload,
8402 uint16_t enc_payload_size)
8403{
8404 struct VirtualLink *vl = next_hop->vl;
8405 struct PendingMessage *pm;
8406 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8407 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8408 + enc_payload_size;
8409 char *buf;
8410 char msg_buf[msg_size] GNUNET_ALIGN;
8411 struct GNUNET_PeerIdentity *dhops;
8412
8413 hdr->num_hops = htons (num_hops);
8414 hdr->total_hops = htons (total_hops);
8415 hdr->header.size = htons (msg_size);
8416 memcpy (msg_buf, hdr, sizeof(*hdr));
8417 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8419 ;
8420 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8421 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8422
8423 if (GNUNET_YES == ntohs (hdr->without_fc))
8424 {
8426 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8427 enc_payload_size,
8428 GNUNET_i2s (&next_hop->pid),
8429 (unsigned int) num_hops,
8430 (unsigned int) total_hops);
8431 route_via_neighbour (next_hop, (const struct
8432 GNUNET_MessageHeader *) msg_buf,
8434 }
8435 else
8436 {
8437 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8439 "2 created pm %p storing vl %p \n",
8440 pm,
8441 vl);
8442 pm->pmt = PMT_DV_BOX;
8443 pm->vl = vl;
8444 pm->target = next_hop->pid;
8446 pm->logging_uuid = logging_uuid_gen++;
8448 pm->bytes_msg = msg_size;
8449 buf = (char *) &pm[1];
8450 memcpy (buf, msg_buf, msg_size);
8451
8453 "Created pending message %" PRIu64
8454 " for DV Box with next hop %s (%u/%u)\n",
8455 pm->logging_uuid,
8456 GNUNET_i2s (&next_hop->pid),
8457 (unsigned int) num_hops,
8458 (unsigned int) total_hops);
8459
8460 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8461 {
8463 vl->pending_msg_head,
8464 vl->pending_msg_tail,
8465 pm);
8466
8468 }
8469 else
8470 {
8472 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8473
8475 {
8477
8478 GNUNET_free (pm_old);
8479 }
8482 {
8485 }
8486 else
8488
8490 "%u items stored in DV ring buffer\n",
8493 }
8494 }
8495}
8496
8497
8503static void
8505{
8506 if (NULL != b->get)
8507 {
8509 b->get = NULL;
8510 GNUNET_assert (NULL != b->cmc);
8512 b->cmc = NULL;
8513 }
8514 if (NULL != b->task)
8515 {
8517 b->task = NULL;
8518 }
8519 if (NULL != b->sc)
8520 {
8522 "store cancel\n");
8524 b->sc = NULL;
8525 }
8527 "Removing backtalker for %s\n",
8528 GNUNET_i2s (&b->pid));
8530 GNUNET_YES ==
8532 GNUNET_free (b);
8533}
8534
8535
8544static int
8546 const struct GNUNET_PeerIdentity *pid,
8547 void *value)
8548{
8549 struct Backtalker *b = value;
8550
8551 (void) cls;
8552 (void) pid;
8553 free_backtalker (b);
8554 return GNUNET_OK;
8555}
8556
8557
8563static void
8565{
8566 struct Backtalker *b = cls;
8567
8569 "backtalker timeout.\n");
8570 b->task = NULL;
8572 {
8574 return;
8575 }
8576 GNUNET_assert (NULL == b->sc);
8577 free_backtalker (b);
8578}
8579
8580
8589static void
8591 const struct GNUNET_PEERSTORE_Record *record,
8592 const char *emsg)
8593{
8594 struct Backtalker *b = cls;
8595 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8596 struct GNUNET_TIME_Absolute mt;
8597
8598 (void) emsg;
8599 if (NULL == record)
8600 {
8601 /* we're done with #backtalker_monotime_cb() invocations,
8602 continue normal processing */
8603 b->get = NULL;
8604 GNUNET_assert (NULL != b->cmc);
8605 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8606 if (0 != b->body_size)
8608 else
8610 b->cmc = NULL;
8611 return;
8612 }
8613 if (sizeof(*mtbe) != record->value_size)
8614 {
8616 GNUNET_break (0);
8617 return;
8618 }
8619 mtbe = record->value;
8620 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8622 {
8624 "Backtalker message from %s dropped, monotime in the past\n",
8625 GNUNET_i2s (&b->pid));
8627 GST_stats,
8628 "# Backchannel messages dropped: monotonic time not increasing",
8629 1,
8630 GNUNET_NO);
8631 b->monotonic_time = mt;
8632 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8633 */
8634 b->body_size = 0;
8635 }
8637}
8638
8639
8647static void
8648backtalker_monotime_store_cb (void *cls, int success)
8649{
8650 struct Backtalker *b = cls;
8651
8652 if (GNUNET_OK != success)
8653 {
8655 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8656 }
8657 b->sc = NULL;
8658 if (NULL != b->task)
8659 {
8661 b->task = NULL;
8662 }
8664}
8665
8666
8672static void
8674{
8675 struct GNUNET_TIME_AbsoluteNBO mtbe;
8676
8677 if (NULL != b->sc)
8678 {
8680 "store cancel before store with sc %p\n",
8681 b->sc);
8682 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8683 b->sc = NULL;*/
8685 "store cancel before store with sc %p is null\n",
8686 b->sc);
8687 }
8688 else
8689 {
8691 b->task = NULL;
8692 }
8694 b->sc =
8696 "transport",
8697 &b->pid,
8699 &mtbe,
8700 sizeof(mtbe),
8704 b);
8705}
8706
8707
8715static void
8716handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8717{
8718 struct CommunicatorMessageContext *cmc = cls;
8719 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
8720 uint16_t num_hops = ntohs (dvb->num_hops);
8721 const struct GNUNET_PeerIdentity *hops =
8722 (const struct GNUNET_PeerIdentity *) &dvb[1];
8723 const char *enc_payload = (const char *) &hops[num_hops];
8724 uint16_t enc_payload_size =
8725 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
8726 struct DVKeyState key;
8727 struct GNUNET_HashCode hmac;
8728 const char *hdr;
8729 size_t hdr_len;
8730
8731 if (GNUNET_EXTRA_LOGGING > 0)
8732 {
8733 char *path;
8734
8736 for (unsigned int i = 0; i < num_hops; i++)
8737 {
8738 char *tmp;
8739
8740 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
8741 GNUNET_free (path);
8742 path = tmp;
8743 }
8745 "Received DVBox with remaining path %s\n",
8746 path);
8747 GNUNET_free (path);
8748 }
8749
8750 if (num_hops > 0)
8751 {
8752 /* We're trying from the end of the hops array, as we may be
8753 able to find a shortcut unknown to the origin that way */
8754 for (int i = num_hops - 1; i >= 0; i--)
8755 {
8756 struct Neighbour *n;
8757
8758 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8759 {
8760 GNUNET_break_op (0);
8761 finish_cmc_handling (cmc);
8762 return;
8763 }
8764 n = lookup_neighbour (&hops[i]);
8765 if (NULL == n)
8766 continue;
8768 "Skipping %u/%u hops ahead while routing DV Box\n",
8769 i,
8770 num_hops);
8771
8772 forward_dv_box (n,
8773 (struct TransportDVBoxMessage *) dvb,
8774 ntohs (dvb->total_hops) + 1,
8775 num_hops - i - 1, /* number of hops left */
8776 &hops[i + 1], /* remaining hops */
8777 enc_payload,
8778 enc_payload_size);
8780 "# DV hops skipped routing boxes",
8781 i,
8782 GNUNET_NO);
8784 "# DV boxes routed (total)",
8785 1,
8786 GNUNET_NO);
8787 finish_cmc_handling (cmc);
8788 return;
8789 }
8790 /* Woopsie, next hop not in neighbours, drop! */
8792 "# DV Boxes dropped: next hop unknown",
8793 1,
8794 GNUNET_NO);
8795 finish_cmc_handling (cmc);
8796 return;
8797 }
8798 /* We are the target. Unbox and handle message. */
8800 "# DV boxes opened (ultimate target)",
8801 1,
8802 GNUNET_NO);
8803 cmc->total_hops = ntohs (dvb->total_hops);
8804
8805 // DH key derivation with received DV, could be garbage.
8806 {
8807 struct GNUNET_ShortHashCode km;
8808
8810 &dvb->ephemeral_key,
8811 &km))
8812 {
8813 GNUNET_break_op (0);
8814 finish_cmc_handling (cmc);
8815 return;
8816 }
8817 dv_setup_key_state_from_km (&km, &dvb->iv, &key);
8818 }
8819 hdr = (const char *) &dvb[1];
8820 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8822 * ntohs (dvb->total_hops);
8823
8824 dv_hmac (&key, &hmac, hdr, hdr_len);
8825 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
8826 {
8827 /* HMAC mismatch, discard! */
8828 GNUNET_break_op (0);
8829 finish_cmc_handling (cmc);
8830 return;
8831 }
8832 /* begin actual decryption */
8833 {
8834 struct Backtalker *b;
8835 struct GNUNET_TIME_Absolute monotime;
8836 struct TransportDVBoxPayloadP ppay;
8837 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
8838 const struct GNUNET_MessageHeader *mh;
8839
8840 GNUNET_assert (hdr_len >=
8841 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
8842 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
8843 {
8845 "Error decrypting DV payload header\n");
8846 GNUNET_break_op (0);
8847 finish_cmc_handling (cmc);
8848 return;
8849 }
8850 if (GNUNET_OK != dv_decrypt (&key, body,
8851 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
8852 {
8854 "Error decrypting DV payload\n");
8855 GNUNET_break_op (0);
8856 finish_cmc_handling (cmc);
8857 return;
8858 }
8859 mh = (const struct GNUNET_MessageHeader *) body;
8860 dv_key_clean (&key);
8861 if (ntohs (mh->size) != sizeof(body))
8862 {
8863 GNUNET_break_op (0);
8864 finish_cmc_handling (cmc);
8865 return;
8866 }
8867 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
8868 switch (ntohs (mh->type))
8869 {
8871 GNUNET_break_op (0);
8872 finish_cmc_handling (cmc);
8873 return;
8874
8876 GNUNET_break_op (0);
8877 finish_cmc_handling (cmc);
8878 return;
8879
8880 default:
8881 /* permitted, continue */
8882 break;
8883 }
8884 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
8886 "Decrypted backtalk from %s\n",
8887 GNUNET_i2s (&ppay.sender));
8889 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
8890 {
8892 GST_stats,
8893 "# Backchannel messages dropped: monotonic time not increasing",
8894 1,
8895 GNUNET_NO);
8896 finish_cmc_handling (cmc);
8897 return;
8898 }
8899 if ((NULL == b) ||
8900 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
8901 {
8902 /* Check signature */
8903 struct EphemeralConfirmationPS ec;
8904
8907 ec.ephemeral_key = dvb->ephemeral_key;
8908 ec.purpose.size = htonl (sizeof(ec));
8910 if (
8911 GNUNET_OK !=
8914 &ec,
8915 &ppay.sender_sig,
8916 &ppay.sender.public_key))
8917 {
8918 /* Signature invalid, discard! */
8919 GNUNET_break_op (0);
8920 finish_cmc_handling (cmc);
8921 return;
8922 }
8923 }
8924 /* Update sender, we now know the real origin! */
8926 "DVBox received for me from %s via %s\n",
8927 GNUNET_i2s2 (&ppay.sender),
8928 GNUNET_i2s (&cmc->im.sender));
8929 cmc->im.sender = ppay.sender;
8930
8931 if (NULL != b)
8932 {
8933 /* update key cache and mono time */
8934 b->last_ephemeral = dvb->ephemeral_key;
8935 b->monotonic_time = monotime;
8937 b->timeout =
8939 cmc->mh = mh;
8941 return;
8942 }
8943 /* setup data structure to cache signature AND check
8944 monotonic time with PEERSTORE before forwarding backchannel payload */
8945 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
8946 b->pid = ppay.sender;
8947 b->body_size = sizeof(body);
8948 memcpy (&b[1], body, sizeof(body));
8952 &b->pid,
8953 b,
8955 b->monotonic_time = monotime; /* NOTE: to be checked still! */
8956 b->cmc = cmc;
8957 b->timeout =
8960 b->get =
8962 "transport",
8963 &b->pid,
8966 b);
8967 } /* end actual decryption */
8968}
8969
8970
8978static int
8980 const struct GNUNET_TRANSPORT_IncomingMessage *im)
8981{
8982 struct TransportClient *tc = cls;
8983
8984 if (CT_COMMUNICATOR != tc->type)
8985 {
8986 GNUNET_break (0);
8987 return GNUNET_SYSERR;
8988 }
8990 return GNUNET_OK;
8991}
8992
8993
8998{
9002 const char *address;
9003
9008};
9009
9010
9020static int
9022 const struct GNUNET_PeerIdentity *pid,
9023 void *value)
9024{
9025 struct CheckKnownAddressContext *ckac = cls;
9026 struct ValidationState *vs = value;
9027
9028 (void) pid;
9029 if (0 != strcmp (vs->address, ckac->address))
9030 return GNUNET_OK;
9031 ckac->vs = vs;
9032 return GNUNET_NO;
9033}
9034
9035
9041static void
9042validation_start_cb (void *cls);
9043
9044
9052static void
9054 struct GNUNET_TIME_Absolute new_time)
9055{
9057
9058 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9059 return; /* be lazy */
9060 vs->next_challenge = new_time;
9061 if (NULL == vs->hn)
9062 vs->hn =
9064 else
9067 (NULL != validation_task))
9068 return;
9069 if (NULL != validation_task)
9071 /* randomize a bit */
9074 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9075 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9078}
9079
9080
9087static void
9089 const char *address)
9090{
9091 struct GNUNET_TIME_Absolute now;
9092 struct ValidationState *vs;
9093 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9094
9096 pid,
9098 &ckac);
9099 if (NULL != (vs = ckac.vs))
9100 {
9101 /* if 'vs' is not currently valid, we need to speed up retrying the
9102 * validation */
9103 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9104 {
9105 /* reduce backoff as we got a fresh advertisement */
9106 vs->challenge_backoff =
9109 vs->challenge_backoff,
9110 2));
9113 vs->challenge_backoff));
9114 }
9115 return;
9116 }
9118 vs = GNUNET_new (struct ValidationState);
9119 vs->pid = *pid;
9120 vs->valid_until =
9122 vs->first_challenge_use = now;
9123 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9125 &vs->challenge,
9126 sizeof(vs->challenge));
9127 vs->address = GNUNET_strdup (address);
9128 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9130 "Starting address validation `%s' of peer %s using challenge %s\n",
9131 address,
9132 GNUNET_i2s (pid),
9133 GNUNET_sh2s (&vs->challenge.value));
9137 &vs->pid,
9138 vs,
9141}
9142
9143
9144static struct Queue *
9145find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9146
9147
9148static void
9149suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9150
9151
9152static void
9154 const struct GNUNET_PeerIdentity *pid,
9155 const char *uri)
9156{
9157 struct Queue *q;
9158 int pfx_len;
9159 const char *eou;
9160 char *address;
9161 (void) cls;
9162
9163 eou = strstr (uri,
9164 "://");
9165 pfx_len = eou - uri;
9166 eou += 3;
9168 "%.*s-%s",
9169 pfx_len,
9170 uri,
9171 eou);
9172
9174 "helo for client %s\n",
9175 address);
9176 q = find_queue (pid, address);
9177 if (NULL == q)
9178 {
9180 }
9181 else
9184}
9185
9186
9194static void
9196 const struct GNUNET_PEERSTORE_Record *record,
9197 const char *emsg)
9198{
9199 struct IncomingRequest *ir = cls;
9201 struct GNUNET_MessageHeader *hello;
9202
9203 if (NULL != emsg)
9204 {
9206 "Got failure from PEERSTORE: %s\n",
9207 emsg);
9208 return;
9209 }
9210 hello = record->value;
9211 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
9212 {
9214 return;
9215 }
9219 NULL);
9221}
9222
9223
9224static void
9226{
9228 "Error in PEERSTORE monitoring\n");
9229}
9230
9231
9232static void
9234{
9236 "Done with initial PEERSTORE iteration during monitoring\n");
9237}
9238
9239
9248static void
9250 void *cls,
9251 const struct TransportValidationChallengeMessage *tvc)
9252{
9253 struct CommunicatorMessageContext *cmc = cls;
9255 struct VirtualLink *vl;
9256 struct GNUNET_TIME_RelativeNBO validity_duration;
9257 struct IncomingRequest *ir;
9258 struct Neighbour *n;
9259 struct GNUNET_PeerIdentity sender;
9260
9261 /* DV-routed messages are not allowed for validation challenges */
9262 if (cmc->total_hops > 0)
9263 {
9264 GNUNET_break_op (0);
9265 finish_cmc_handling (cmc);
9266 return;
9267 }
9268 validity_duration = cmc->im.expected_address_validity;
9270 "Received address validation challenge %s\n",
9271 GNUNET_sh2s (&tvc->challenge.value));
9272 /* If we have a virtual link, we use this mechanism to signal the
9273 size of the flow control window, and to allow the sender
9274 to ask for increases. If for us the virtual link is still down,
9275 we will always give a window size of zero. */
9276 tvr.header.type =
9278 tvr.header.size = htons (sizeof(tvr));
9279 tvr.reserved = htonl (0);
9280 tvr.challenge = tvc->challenge;
9281 tvr.origin_time = tvc->sender_time;
9282 tvr.validity_duration = validity_duration;
9283 {
9284 /* create signature */
9285 struct TransportValidationPS tvp = {
9287 .purpose.size = htonl (sizeof(tvp)),
9288 .validity_duration = validity_duration,
9289 .challenge = tvc->challenge
9290 };
9291
9293 &tvp,
9294 &tvr.signature);
9295 }
9296 sender = cmc->im.sender;
9297 vl = lookup_virtual_link (&sender);
9298 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9299 {
9300 // route_control_message_without_fc (&cmc->im.sender,
9302 &tvr.header,
9304 }
9305 else
9306 {
9307 /* Use route via neighbour */
9308 n = lookup_neighbour (&sender);
9309 if (NULL != n)
9310 route_via_neighbour (n, &tvr.header,
9313 }
9314
9315 finish_cmc_handling (cmc);
9316 if (NULL != vl)
9317 return;
9318
9319 /* For us, the link is still down, but we need bi-directional
9320 connections (for flow-control and for this to be useful for
9321 CORE), so we must try to bring the link up! */
9322
9323 /* (1) Check existing queues, if any, we may be lucky! */
9324 n = lookup_neighbour (&sender);
9325 if (NULL != n)
9326 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9327 start_address_validation (&sender, q->address);
9328 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9329 we could use */
9330 for (ir = ir_head; NULL != ir; ir = ir->next)
9331 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9332 return;
9333 /* we are already trying */
9334 ir = GNUNET_new (struct IncomingRequest);
9335 ir->pid = sender;
9337
9339 GNUNET_YES,
9340 "peerstore",
9341 NULL,
9344 NULL,
9346 NULL,
9348 ir);
9349 ir_total++;
9350 /* Bound attempts we do in parallel here, might otherwise get excessive */
9353}
9354
9355
9360{
9365
9370};
9371
9372
9382static int
9384 const struct GNUNET_PeerIdentity *pid,
9385 void *value)
9386{
9387 struct CheckKnownChallengeContext *ckac = cls;
9388 struct ValidationState *vs = value;
9389
9390 (void) pid;
9391 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9392 return GNUNET_OK;
9393 ckac->vs = vs;
9394 return GNUNET_NO;
9395}
9396
9397
9405static void
9406peerstore_store_validation_cb (void *cls, int success)
9407{
9408 struct ValidationState *vs = cls;
9409
9410 vs->sc = NULL;
9411 if (GNUNET_YES == success)
9412 return;
9414 "# Peerstore failed to store foreign address",
9415 1,
9416 GNUNET_NO);
9417}
9418
9419
9427static struct Queue *
9428find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9429{
9430 struct Neighbour *n;
9431
9432 n = lookup_neighbour (pid);
9433 if (NULL == n)
9434 return NULL;
9435 for (struct Queue *pos = n->queue_head; NULL != pos;
9436 pos = pos->next_neighbour)
9437 {
9438 if (0 == strcmp (pos->address, address))
9439 return pos;
9440 }
9441 return NULL;
9442}
9443
9444
9445static void
9447
9448static void
9450{
9451 struct ValidationState *vs = cls;
9452 struct Queue *q;
9453 struct GNUNET_TIME_Absolute now;
9454
9455 vs->revalidation_task = NULL;
9456 q = find_queue (&vs->pid, vs->address);
9457 if (NULL == q)
9458 {
9459 now = GNUNET_TIME_absolute_get ();
9460 vs->awaiting_queue = GNUNET_YES;
9461 suggest_to_connect (&vs->pid, vs->address);
9463 }
9464 else
9466}
9467
9468
9469static enum GNUNET_GenericReturnValue
9471 void *cls,
9472 const struct GNUNET_HashCode *key,
9473 void *value)
9474{
9475 (void) cls;
9477 "Key in revalidate map %s \n",
9478 GNUNET_h2s (key));
9479 return GNUNET_YES;
9480}
9481
9482
9491static void
9493 void *cls,
9494 const struct TransportValidationResponseMessage *tvr)
9495{
9496 struct CommunicatorMessageContext *cmc = cls;
9497 struct ValidationState *vs;
9498 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9499 .vs = NULL};
9500 struct GNUNET_TIME_Absolute origin_time;
9501 struct Queue *q;
9502 struct Neighbour *n;
9503 struct VirtualLink *vl;
9505 GST_cfg);
9506
9507 /* check this is one of our challenges */
9509 &cmc->im.sender,
9511 &ckac);
9512 if (NULL == (vs = ckac.vs))
9513 {
9514 /* This can happen simply if we 'forgot' the challenge by now,
9515 i.e. because we received the validation response twice */
9517 "# Validations dropped, challenge unknown",
9518 1,
9519 GNUNET_NO);
9521 "Validation response %s dropped, challenge unknown\n",
9522 GNUNET_sh2s (&tvr->challenge.value));
9523 finish_cmc_handling (cmc);
9524 return;
9525 }
9526
9527 /* sanity check on origin time */
9528 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9529 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9530 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9531 {
9533 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9534 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9535 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9536 GNUNET_break_op (0);
9537 finish_cmc_handling (cmc);
9538 return;
9539 }
9540
9541 {
9542 /* check signature */
9543 struct TransportValidationPS tvp = {
9545 .purpose.size = htonl (sizeof(tvp)),
9546 .validity_duration = tvr->validity_duration,
9547 .challenge = tvr->challenge
9548 };
9549
9550 if (
9551 GNUNET_OK !=
9553 &tvp,
9554 &tvr->signature,
9555 &cmc->im.sender.public_key))
9556 {
9557 GNUNET_break_op (0);
9558 finish_cmc_handling (cmc);
9559 return;
9560 }
9561 }
9562
9563 /* validity is capped by our willingness to keep track of the
9564 validation entry and the maximum the other peer allows */
9567 tvr->validity_duration),
9569 vs->validated_until =
9573 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9574 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9576 &vs->challenge,
9577 sizeof(vs->challenge));
9578 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9579 vs->validated_until,
9580 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9582 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9583 {
9585 "First challenge use is now %" PRIu64 " %s \n",
9586 vs->first_challenge_use.abs_value_us,
9587 GNUNET_sh2s (&vs->challenge.value));
9588 vs->first_challenge_use = now;
9589 }
9590 else
9592 "First challenge use is later %" PRIu64 " %s \n",
9593 vs->first_challenge_use.abs_value_us,
9594 GNUNET_sh2s (&vs->challenge.value));
9595 vs->last_challenge_use =
9596 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
9597 update_next_challenge_time (vs, vs->first_challenge_use);
9599 "Validation response %s from %s accepted, address valid until %s\n",
9600 GNUNET_sh2s (&tvr->challenge.value),
9601 GNUNET_i2s (&cmc->im.sender),
9603 /*memcpy (&hkey,
9604 &hc,
9605 sizeof (hkey));*/
9607 "Key %s for address %s map size %u contains %u\n",
9608 GNUNET_h2s (&vs->hc),
9609 vs->address,
9612 &vs->hc));
9616 &vs->hc,
9617 vs,
9621 NULL);
9622 vs->revalidation_task =
9627 "transport",
9628 &cmc->im.sender,
9630 vs->address,
9631 strlen (vs->address) + 1,
9632 vs->valid_until,
9635 vs);
9636 finish_cmc_handling (cmc);
9637
9638 /* Finally, we now possibly have a confirmed (!) working queue,
9639 update queue status (if queue still is around) */
9640 q = find_queue (&vs->pid, vs->address);
9641 if (NULL == q)
9642 {
9644 "# Queues lost at time of successful validation",
9645 1,
9646 GNUNET_NO);
9647 return;
9648 }
9649 q->validated_until = vs->validated_until;
9650 q->pd.aged_rtt = vs->validation_rtt;
9651 n = q->neighbour;
9652 vl = lookup_virtual_link (&vs->pid);
9653 if (NULL == vl)
9654 {
9655 vl = GNUNET_new (struct VirtualLink);
9657 "Creating new virtual link %p to %s using direct neighbour!\n",
9658 vl,
9659 GNUNET_i2s (&vs->pid));
9660 vl->burst_addr = NULL;
9661 vl->confirmed = GNUNET_YES;
9662 vl->message_uuid_ctr =
9664 vl->target = n->pid;
9670 links,
9671 &vl->target,
9672 vl,
9674 vl->n = n;
9675 n->vl = vl;
9676 q->idle = GNUNET_YES;
9677 vl->visibility_task =
9678 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9680 /* We lacked a confirmed connection to the target
9681 before, so tell CORE about it (finally!) */
9684 }
9685 else
9686 {
9687 /* Link was already up, remember n is also now available and we are done */
9688 if (NULL == vl->n)
9689 {
9690 vl->n = n;
9691 n->vl = vl;
9692 if (GNUNET_YES == vl->confirmed)
9694 "Virtual link to %s could now also use direct neighbour!\n",
9695 GNUNET_i2s (&vs->pid));
9696 }
9697 else
9698 {
9699 GNUNET_assert (n == vl->n);
9700 }
9701 if (GNUNET_NO == vl->confirmed)
9702 {
9703 vl->confirmed = GNUNET_YES;
9704 q->idle = GNUNET_YES;
9705 vl->visibility_task =
9706 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9708 /* We lacked a confirmed connection to the target
9709 before, so tell CORE about it (finally!) */
9712 }
9713 }
9714}
9715
9716
9722static void
9724 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9725{
9726 struct TransportClient *tc = cls;
9727 struct CommunicatorMessageContext *cmc =
9729
9730 cmc->tc = tc;
9731 cmc->im = *im;
9733 "Received message with size %u and flow control id %" PRIu64
9734 " via communicator from peer %s\n",
9735 ntohs (im->header.size),
9736 im->fc_id,
9737 GNUNET_i2s (&im->sender));
9738 cmc->im.neighbour_sender = cmc->im.sender;
9739 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
9741}
9742
9743
9752static int
9754{
9755 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
9756 (void) cls;
9757
9759 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
9760 ntohs (fc->header.size),
9761 ntohl (fc->size_of_addresses),
9762 ntohl (fc->number_of_addresses),
9763 sizeof(struct TransportFlowControlMessage),
9764 sizeof (struct TransportGlobalNattedAddress));
9765
9766 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
9768 + ntohl (fc->number_of_addresses) * sizeof (struct
9770 + ntohl (fc->size_of_addresses))
9771 return GNUNET_OK;
9772 else
9773 {
9774 GNUNET_break_op (0);
9775 return GNUNET_SYSERR;
9776 }
9777}
9778
9779
9780static struct GNUNET_TIME_Relative
9782{
9784 unsigned int n_hops = 0;
9785
9787 "calculate_rtt\n");
9788 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
9789 pos = pos->next_dv)
9790 {
9792 "calculate_rtt %lu\n",
9793 (unsigned long) pos->pd.aged_rtt.rel_value_us);
9794 n_hops++;
9796 aged_rtt, pos
9797 ->distance
9798 + 2), ret);
9799 }
9800
9801 GNUNET_assert (0 != n_hops);
9802
9803 return ret;
9804}
9805
9806
9807static void
9809 const struct GNUNET_PeerIdentity *pid,
9810 const char *uri)
9811{
9812 struct VirtualLink *vl = cls;
9813 const char *slash;
9814 char *address_uri;
9815 char *prefix;
9816 char *uri_without_port;
9817
9818 slash = strrchr (uri, '/');
9819 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
9820 GNUNET_assert (NULL != slash);
9821 slash++;
9822 GNUNET_asprintf (&address_uri,
9823 "%s-%s",
9824 prefix,
9825 slash);
9826
9827 uri_without_port = get_address_without_port (address_uri);
9829 "iterate_address_start_burst %s %s %s %s\n",
9830 uri_without_port,
9831 uri,
9832 address_uri,
9833 slash);
9834 if (0 == strcmp (uri_without_port, slash))
9835 {
9836 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
9837 );
9838 }
9839 else
9840 vl->burst_addr = NULL;
9841
9843 GNUNET_free (uri_without_port);
9844}
9845
9846
9847static void
9849 const struct GNUNET_PEERSTORE_Record *record,
9850 const char *emsg)
9851{
9852 struct GNUNET_StartBurstCls *sb_cls = cls;
9853 struct VirtualLink *vl = sb_cls->vl;
9854 struct GNUNET_MessageHeader *hello;
9856
9857 if (NULL != emsg)
9858 {
9860 "Got failure from PEERSTORE: %s\n",
9861 emsg);
9862 return;
9863 }
9864 if (NULL == record)
9865 {
9867 "Hello iteration end for %s\n",
9868 GNUNET_i2s (&vl->target));
9869 vl->ic = NULL;
9870 GNUNET_free (sb_cls);
9871 return;
9872 }
9873
9875 "check_for_burst_address\n");
9876 hello = record->value;
9880 vl);
9882
9884 GNUNET_free (sb_cls);
9885}
9886
9887
9888static void
9889burst_timeout (void *cls)
9890{
9892}
9893
9894
9895static void
9896start_burst (void *cls)
9897{
9898 struct GNUNET_StartBurstCls *sb_cls = cls;
9899 struct VirtualLink *vl = sb_cls->vl;
9900 struct GNUNET_TRANSPORT_StartBurst *sb;
9901 struct GNUNET_MQ_Envelope *env;
9902 char *uri_without_port = vl->burst_addr;
9903
9904 burst_task = NULL;
9905 /*char buf[strlen (uri_without_port) + 1];
9906
9907 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
9908 buf[strlen (uri_without_port)] = '\0';*/
9909 env =
9911 strlen (uri_without_port) + 1,
9913 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
9914 sb->pid = vl->target;
9915 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
9916 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
9917 {
9919 "iterate_address_start_burst client tc prefix %s\n",
9920 tc->details.communicator.address_prefix);
9921 if (CT_COMMUNICATOR != tc->type)
9922 continue;
9923 if (GNUNET_YES == tc->details.communicator.can_burst)
9924 {
9926 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
9927 uri_without_port,
9928 strlen (uri_without_port),
9929 ntohs (sb->header.size),
9930 (unsigned long) sb_cls->rtt.rel_value_us);
9931 GNUNET_MQ_send (tc->mq, env);
9935 60),
9937 NULL);
9938 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
9939 break;
9940 }
9941 }
9942 GNUNET_free (env);
9943 GNUNET_free (sb_cls);
9944}
9945
9946
9947static void
9948queue_burst (void *cls)
9949{
9950 struct GNUNET_StartBurstCls *sb_cls = cls;
9951 struct VirtualLink *vl = sb_cls->vl;
9952
9953 if (GNUNET_YES != use_burst)
9954 return;
9956 "burst_task %p ready %s burst addr %s (%p)\n",
9957 burst_task,
9958 sb_cls->sync_ready ? "yes" : "no",
9959 vl->burst_addr,
9960 vl->burst_addr);
9961 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
9962 {
9964 burst_task = NULL;
9966 return;
9967 }
9968 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
9969 )
9970 {
9972 &start_burst,
9973 sb_cls);
9974 }
9975 else if (NULL == vl->burst_addr)
9976 {
9978 "peerstore",
9979 &vl->target,
9982 sb_cls);
9983 }
9984}
9985
9986
9995static void
9997{
9998 struct CommunicatorMessageContext *cmc = cls;
9999 struct VirtualLink *vl;
10001 uint32_t seq;
10002 struct GNUNET_TIME_Absolute st;
10003 uint64_t os;
10004 uint64_t wnd;
10005 uint32_t random;
10006
10008 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10009 vl = lookup_virtual_link (&cmc->im.sender);
10010 if (NULL == vl)
10011 {
10012 vl = GNUNET_new (struct VirtualLink);
10014 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10015 vl,
10016 GNUNET_i2s (&cmc->im.sender));
10017 vl->burst_addr = NULL;
10018 vl->confirmed = GNUNET_NO;
10019 vl->message_uuid_ctr =
10021 vl->target = cmc->im.sender;
10027 links,
10028 &vl->target,
10029 vl,
10031 }
10032 if (NULL != vl->n)
10033 {
10034 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10035 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10036 }
10037
10039 "remaining %lu timeout for neighbour %p\n",
10040 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10041 rel_value_us,
10042 vl->n);
10043 if (NULL == vl->n ||
10044 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10045 {
10046 struct GNUNET_TIME_Relative rtt;
10047 struct GNUNET_BurstSync burst_sync;
10048 struct GNUNET_StartBurstCls *bcls;
10049
10050 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10051 bcls->vl = vl;
10052 vl->sb_cls = bcls;
10053 if (NULL != vl->dv)
10054 rtt = calculate_rtt (vl->dv);
10055 else
10057 burst_sync.rtt_average = fc->rtt;
10058 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10059 burst_sync.sync_ready = fc->sync_ready;
10060
10062 &burst_sync,
10063 &queue_burst,
10064 bcls);
10065 }
10066 if (0 != ntohl (fc->number_of_addresses))
10067 {
10068 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10069 const char *tgnas;
10070 unsigned int off = 0;
10071
10072 tgnas = (const char *) &fc[1];
10073
10074 for (int i = 1; i <= number_of_addresses; i++)
10075 {
10076 struct TransportGlobalNattedAddress *tgna;
10077 char *addr;
10078 unsigned int address_length;
10079
10080 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10081 addr = (char *) &tgna[1];
10082 address_length = ntohl (tgna->address_length);
10083 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10084
10086 "received address %s length %u\n",
10087 addr,
10088 ntohl (tgna->address_length));
10089
10090 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10091 }
10092 }
10094 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10095 {
10097 "FC dropped: Message out of order\n");
10098 /* out of order, drop */
10100 "# FC dropped: message out of order",
10101 1,
10102 GNUNET_NO);
10103 finish_cmc_handling (cmc);
10104 return;
10105 }
10106 seq = ntohl (fc->seq);
10107 if (seq < vl->last_fc_seq)
10108 {
10109 /* Wrap-around/reset of other peer; start all counters from zero */
10111 }
10112 vl->last_fc_seq = seq;
10113 vl->last_fc_timestamp = st;
10117 (int64_t) (os - vl->incoming_fc_window_size_used);
10119 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10120 GNUNET_i2s (&vl->target),
10121 (unsigned int) seq,
10122 (unsigned long long) vl->outbound_fc_window_size,
10123 (long long) vl->incoming_fc_window_size_loss);
10126 UINT32_MAX);
10127 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10131 != wnd) ||
10132 (0 == random
10134 {
10136 "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",
10137 (unsigned long long) wnd,
10138 (unsigned long long) vl->incoming_fc_window_size,
10139 (unsigned long long) vl->last_outbound_window_size_received,
10142 }
10143 if ((wnd == vl->incoming_fc_window_size
10147 (NULL != vl->fc_retransmit_task))
10148 {
10150 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10151 GNUNET_i2s (&vl->target),
10152 (unsigned long long) wnd);
10154 vl->fc_retransmit_task = NULL;
10155 vl->fc_retransmit_count = 0;
10156 }
10158 /* FC window likely increased, check transmission possibilities! */
10160 finish_cmc_handling (cmc);
10161}
10162
10163
10171static void
10173{
10175 { GNUNET_MQ_hd_var_size (fragment_box,
10178 cmc),
10179 GNUNET_MQ_hd_var_size (reliability_box,
10182 cmc),
10183 GNUNET_MQ_hd_var_size (reliability_ack,
10186 cmc),
10187 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10190 cmc),
10191 GNUNET_MQ_hd_var_size (dv_learn,
10194 cmc),
10195 GNUNET_MQ_hd_var_size (dv_box,
10197 struct TransportDVBoxMessage,
10198 cmc),
10199 GNUNET_MQ_hd_var_size (flow_control,
10202 cmc),
10204 validation_challenge,
10207 cmc),
10209 validation_response,
10212 cmc),
10214 int ret;
10215 const struct GNUNET_MessageHeader *msg = cmc->mh;
10216
10218 "Handling message of type %u with %u bytes\n",
10219 (unsigned int) ntohs (msg->type),
10220 (unsigned int) ntohs (msg->size));
10222 if (GNUNET_SYSERR == ret)
10223 {
10224 GNUNET_break (0);
10226 GNUNET_free (cmc);
10227 return;
10228 }
10229 if (GNUNET_NO == ret)
10230 {
10231 /* unencapsulated 'raw' message */
10232 handle_raw_message (cmc, msg);
10233 }
10234}
10235
10236
10243static int
10245 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10246{
10247 struct TransportClient *tc = cls;
10248
10249 if (CT_COMMUNICATOR != tc->type)
10250 {
10251 GNUNET_break (0);
10252 return GNUNET_SYSERR;
10253 }
10255 return GNUNET_OK;
10256}
10257
10258
10264static void
10266{
10267 if (pm->msg_uuid_set)
10268 return;
10269 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10270 pm->msg_uuid_set = GNUNET_YES;
10271}
10272
10273
10282static struct PendingAcknowledgement *
10284 struct DistanceVectorHop *dvh,
10285 struct PendingMessage *pm)
10286{
10287 struct PendingAcknowledgement *pa;
10288
10289 pa = GNUNET_new (struct PendingAcknowledgement);
10290 pa->queue = queue;
10291 pa->dvh = dvh;
10292 pa->pm = pm;
10293 do
10294 {
10296 &pa->ack_uuid,
10297 sizeof(pa->ack_uuid));
10298 }
10301 &pa->ack_uuid.value,
10302 pa,
10304 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10305 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10306 if (NULL != dvh)
10309 pa->message_size = pm->bytes_msg;
10311 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10313 pm->logging_uuid);
10314 return pa;
10315}
10316
10317
10329static struct PendingMessage *
10331 struct DistanceVectorHop *dvh,
10332 struct PendingMessage *pm)
10333{
10334 struct PendingAcknowledgement *pa;
10335 struct PendingMessage *ff;
10336 uint16_t mtu;
10337 uint16_t msize;
10338
10339 mtu = (UINT16_MAX == queue->mtu)
10340 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10341 : queue->mtu;
10343 "Fragmenting message <%" PRIu64
10344 "> with size %u to %s for MTU %u\n",
10345 pm->logging_uuid,
10346 pm->bytes_msg,
10347 GNUNET_i2s (&pm->vl->target),
10348 (unsigned int) mtu);
10351 "Fragmenting message %" PRIu64 " <%" PRIu64
10352 "> with size %u to %s for MTU %u\n",
10353 pm->msg_uuid.uuid,
10354 pm->logging_uuid,
10355 pm->bytes_msg,
10356 GNUNET_i2s (&pm->vl->target),
10357 (unsigned int) mtu);
10358
10359 /* This invariant is established in #handle_add_queue_message() */
10360 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10361
10362 /* select fragment for transmission, descending the tree if it has
10363 been expanded until we are at a leaf or at a fragment that is small
10364 enough
10365 */
10366 ff = pm;
10367 msize = ff->bytes_msg;
10368
10369 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10370 (ff->frag_off == msize) && (NULL != ff->head_frag))
10371 {
10372 ff = ff->head_frag; /* descent into fragmented fragments */
10373 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10374 }
10375
10376 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10377 {
10378 /* Did not yet calculate all fragments, calculate next fragment */
10379 struct PendingMessage *frag;
10380 struct TransportFragmentBoxMessage tfb;
10381 const char *orig;
10382 char *msg;
10383 uint16_t fragmax;
10384 uint16_t fragsize;
10385 uint16_t msize_ff;
10386 uint16_t xoff = 0;
10387 pm->frag_count++;
10388
10389 orig = (const char *) &ff[1];
10390 msize_ff = ff->bytes_msg;
10391 if (pm != ff)
10392 {
10393 const struct TransportFragmentBoxMessage *tfbo;
10394
10395 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10396 orig += sizeof(struct TransportFragmentBoxMessage);
10397 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10398 xoff = ntohs (tfbo->frag_off);
10399 }
10400 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10401 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10402 frag =
10403 GNUNET_malloc (sizeof(struct PendingMessage)
10404 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10406 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10407 frag,
10408 ff,
10409 pm->vl,
10410 pm);
10412 frag->vl = pm->vl;
10413 frag->frag_parent = ff;
10414 frag->timeout = pm->timeout;
10415 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10416 frag->pmt = PMT_FRAGMENT_BOX;
10417 msg = (char *) &frag[1];
10419 tfb.header.size =
10420 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10421 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10422 tfb.ack_uuid = pa->ack_uuid;
10423 tfb.msg_uuid = pm->msg_uuid;
10424 tfb.frag_off = htons (ff->frag_off + xoff);
10425 tfb.msg_size = htons (pm->bytes_msg);
10426 memcpy (msg, &tfb, sizeof(tfb));
10427 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10429 ff->tail_frag, frag);
10430 ff->frag_off += fragsize;
10431 ff = frag;
10432 }
10433
10434 /* Move head to the tail and return it */
10438 ff);
10442 ff);
10443
10444 return ff;
10445}
10446
10447
10460static struct PendingMessage *
10462 struct DistanceVectorHop *dvh,
10463 struct PendingMessage *pm)
10464{
10466 struct PendingAcknowledgement *pa;
10467 struct PendingMessage *bpm;
10468 char *msg;
10469
10470 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10471 return pm; /* already fragmented or reliability boxed, or control message:
10472 do nothing */
10473 if (NULL != pm->bpm)
10474 return pm->bpm; /* already computed earlier: do nothing */
10475 // TODO I guess we do not need this assertion. We might have a DLL with
10476 // fragments, because the MTU changed, and we do not need to fragment anymore.
10477 // But we should keep the fragments until message was completed, because
10478 // the MTU might change again.
10479 // GNUNET_assert (NULL == pm->head_frag);
10480 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10481 {
10482 /* failed hard */
10483 GNUNET_break (0);
10485 return NULL;
10486 }
10487
10489
10490 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10491 + pm->bytes_msg);
10493 "4 created pm %p storing vl %p from pm %p\n",
10494 bpm,
10495 pm->vl,
10496 pm);
10498 bpm->vl = pm->vl;
10499 bpm->frag_parent = pm;
10500 // Why was this needed?
10501 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10502 bpm->timeout = pm->timeout;
10504 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10507 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10508 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10509
10510 rbox.ack_uuid = pa->ack_uuid;
10511 msg = (char *) &bpm[1];
10512 memcpy (msg, &rbox, sizeof(rbox));
10513 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10514 pm->bpm = bpm;
10516 "Preparing reliability box for message <%" PRIu64
10517 "> of size %d (%d) to %s on queue %s\n",
10518 pm->logging_uuid,
10519 pm->bytes_msg,
10520 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10521 GNUNET_i2s (&pm->vl->target),
10522 queue->address);
10523 return bpm;
10524}
10525
10526
10527static void
10530{
10531 struct VirtualLink *vl = pm->vl;
10532 struct PendingMessage *pos;
10533
10534 /* re-insert sort in neighbour list */
10538 pm);
10539 pos = vl->pending_msg_tail;
10540 while ((NULL != pos) &&
10542 pos = pos->prev_vl;
10546 pos,
10547 pm);
10548}
10549
10550
10551static unsigned int
10553{
10554 struct PendingMessage *pos;
10556
10557 pos = pm->head_frag;
10558 while (NULL != pos)
10559 {
10560 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10561 GNUNET_NO == check_next_attempt_tree (pos, root))
10563 else
10564 {
10566 break;
10567 }
10568 pos = pos->next_frag;
10569 }
10570
10571 return frags_in_flight;
10572}
10573
10574
10575static void
10577{
10578 struct PendingMessage *pos;
10579
10580 pos = pm->head_frag;
10581 while (NULL != pos)
10582 {
10583 pos->frags_in_flight_round = pm->frags_in_flight_round;
10585 pos = pos->next_frag;
10586 }
10587}
10588
10589
10598static void
10601{
10602 if (NULL == pm->frag_parent)
10603 {
10604 pm->next_attempt = next_attempt;
10606 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
10607 pm->logging_uuid,
10610 }
10611 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
10612 {
10613 struct PendingMessage *root = pm->frag_parent;
10614
10615 while (NULL != root->frag_parent)
10616 root = root->frag_parent;
10618 "Next attempt for root message <%" PRIu64 "> set to %s\n",
10619 root->logging_uuid,
10621 root->next_attempt = next_attempt;
10623 }
10624 else
10625 {
10626 struct PendingMessage *root = pm->frag_parent;
10627
10628 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10629 root = root->frag_parent;
10630
10632 "frag_count next attempt %u\n",
10633 root->frag_count);
10634
10635 if (GNUNET_NO == root->frags_in_flight)
10636 {
10637 root->next_attempt = next_attempt;
10639 root->frags_in_flight_round++;
10641 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
10642 ">)set to %" PRIu64 "\n",
10643 pm->logging_uuid,
10644 root->logging_uuid,
10646 }
10647
10648 pm->next_attempt = root->next_attempt;
10649 pm->frags_in_flight_round = root->frags_in_flight_round;
10651
10652 if (root->bytes_msg == root->frag_off)
10653 root->frags_in_flight = check_next_attempt_tree (root, root);
10654 else
10656
10657 if (GNUNET_NO == root->frags_in_flight)
10658 {
10660 "We have no fragments in flight for message %" PRIu64
10661 ", reorder root! Next attempt is %" PRIu64 "\n",
10662 root->logging_uuid,
10664 if (PMT_DV_BOX == root->pmt)
10665 root = root->frag_parent;
10666 reorder_root_pm (root, root->next_attempt);
10667 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
10668 }
10669 else
10670 {
10671 double factor = ((double) root->frag_count - 1)
10672 / (double) root->frag_count;
10673 struct GNUNET_TIME_Relative s1;
10674 struct GNUNET_TIME_Relative s2;
10675 struct GNUNET_TIME_Relative plus_mean =
10678 next_attempt);
10679
10681 "frag_count %u after factor\n",
10682 root->frag_count);
10684 factor);
10685 s2 = GNUNET_TIME_relative_divide (plus,
10686 root->frag_count);
10687 plus_mean = GNUNET_TIME_relative_add (s1, s2);
10690 "We have fragments in flight for message %" PRIu64
10691 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
10692 root->logging_uuid,
10694 }
10695 }
10696}
10697
10698
10703{
10708
10713
10718
10723
10727 int frag;
10728
10732 int relb;
10733
10738
10742 unsigned int frags_in_flight;
10743
10748};
10749
10750
10762static void
10764 struct Queue *queue,
10765 struct VirtualLink *vl,
10766 struct DistanceVectorHop *dvh,
10767 size_t overhead)
10768{
10769 struct GNUNET_TIME_Absolute now;
10770
10771 now = GNUNET_TIME_absolute_get ();
10772 sc->to_early = GNUNET_NO;
10773 sc->frags_in_flight = GNUNET_NO;
10774 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
10775 pos = pos->next_vl)
10776 {
10777 size_t real_overhead = overhead;
10778 int frag;
10779 int relb;
10780
10781 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
10782 {
10784 "DV messages must not be DV-routed to next hop!\n");
10785 continue; /* DV messages must not be DV-routed to next hop! */
10786 }
10787 if (pos->next_attempt.abs_value_us > now.abs_value_us)
10788 {
10789 if (GNUNET_YES == pos->frags_in_flight)
10790 {
10791 sc->frags_in_flight = GNUNET_YES;
10793 "Fragments in flight for message %" PRIu64 "\n",
10794 pos->logging_uuid);
10795 }
10796 else
10797 {
10799 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
10800 PRIu64 "\n",
10801 pos->logging_uuid);
10802 sc->to_early = GNUNET_YES;
10803 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
10804 pos->next_attempt);
10805 continue;
10806 }
10807 // break; /* too early for all messages, they are sorted by next_attempt */
10808 }
10809 if (NULL != pos->qe)
10810 {
10812 "not eligible\n");
10813 continue; /* not eligible */
10814 }
10815 sc->consideration_counter++;
10816 /* determine if we have to fragment, if so add fragmentation
10817 overhead! */
10819 "check %" PRIu64 " for sc->best\n",
10820 pos->logging_uuid);
10821 frag = GNUNET_NO;
10822 if (((0 != queue->mtu) &&
10823 (pos->bytes_msg + real_overhead > queue->mtu)) ||
10824 (pos->bytes_msg > UINT16_MAX - sizeof(struct
10826 ||
10827 (NULL != pos->head_frag /* fragments already exist, should
10828 respect that even if MTU is UINT16_MAX for
10829 this queue */))
10830 {
10832 "fragment msg with size %u, realoverhead is %lu\n",
10833 pos->bytes_msg,
10834 real_overhead);
10835 frag = GNUNET_YES;
10836 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
10837 {
10838 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
10839 header without the ACK UUID when using a *reliable* channel! */
10840 }
10841 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10842 }
10843 /* determine if we have to reliability-box, if so add reliability box
10844 overhead */
10845 relb = GNUNET_NO;
10846 if ((GNUNET_NO == frag) &&
10847 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
10848 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
10849 {
10850 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
10851
10852 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
10853 {
10854 frag = GNUNET_YES;
10855 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10856 }
10857 else
10858 {
10859 relb = GNUNET_YES;
10860 }
10862 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
10863 pos->bytes_msg,
10864 real_overhead,
10865 queue->mtu,
10866 frag,
10867 relb);
10868 }
10869
10870 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
10871 message would beat it! */
10872 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
10873 {
10874 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
10875 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
10876 experimentally validated. There may be some huge potential for
10877 improvement here. Also, we right now only compare how well the
10878 given message fits _this_ queue, and do not consider how well other
10879 queues might suit the message. Taking other queues into consideration
10880 may further improve the result, but could also be expensive
10881 in terms of CPU time. */
10882 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
10883 long long pm_score = frag * 40 + relb * 20 + real_overhead;
10884 long long time_delta =
10885 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
10886 / 1000LL;
10887
10888 /* "time_delta" considers which message has been 'ready' for transmission
10889 for longer, if a message has a preference for low latency, increase
10890 the weight of the time_delta by 10x if it is favorable for that message */
10891 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10892 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
10893 time_delta *= 10; /* increase weight (always, both are low latency) */
10894 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10895 (time_delta > 0))
10896 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
10897 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10898 (time_delta < 0))
10899 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
10900 if (0 != queue->mtu)
10901 {
10902 /* Grant bonus if we are below MTU, larger bonus the closer we will
10903 be to the MTU */
10904 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
10905 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
10906 if (queue->mtu > real_overhead + pos->bytes_msg)
10907 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
10908 }
10909 if (sc_score + time_delta > pm_score)
10910 {
10912 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
10913 "\n",
10914 pos->logging_uuid,
10915 sc->best->logging_uuid);
10916 continue; /* sc_score larger, keep sc->best */
10917 }
10918 }
10919 sc->best = pos;
10920 sc->dvh = dvh;
10921 sc->frag = frag;
10922 sc->relb = relb;
10923 sc->real_overhead = real_overhead;
10924 }
10925}
10926
10927
10938static void
10940 struct Neighbour *next_hop,
10941 const struct GNUNET_MessageHeader *hdr,
10943{
10944 struct PendingMessageScoreContext *sc = cls;
10945 struct PendingMessage *pm = sc->best;
10946 struct PendingMessage *bpm;
10947 uint16_t bsize = ntohs (hdr->size);
10948
10949 GNUNET_assert (NULL == pm->bpm);
10950 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
10952 "5 created pm %p storing vl %p from pm %p\n",
10953 bpm,
10954 pm->vl,
10955 pm);
10957 bpm->pmt = PMT_DV_BOX;
10958 bpm->vl = pm->vl;
10959 bpm->timeout = pm->timeout;
10960 bpm->bytes_msg = bsize;
10961 bpm->frag_parent = pm;
10964 "Creating DV Box %" PRIu64 " for original message %" PRIu64
10965 " (next hop is %s)\n",
10967 pm->logging_uuid,
10968 GNUNET_i2s (&next_hop->pid));
10969 memcpy (&bpm[1], hdr, bsize);
10970 pm->bpm = bpm;
10971}
10972
10973
10989static void
10991{
10992 struct Queue *queue = cls;
10993 struct Neighbour *n = queue->neighbour;
10995 struct PendingMessage *pm;
10996
10997 queue->transmit_task = NULL;
10998 if (NULL == n->vl)
10999 {
11001 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11002 GNUNET_i2s (&n->pid),
11003 queue->address);
11004 queue->idle = GNUNET_YES;
11005 return;
11006 }
11007 memset (&sc, 0, sizeof(sc));
11008 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11009 if (NULL == sc.best)
11010 {
11011 /* Also look at DVH that have the n as first hop! */
11012 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11013 dvh = dvh->next_neighbour)
11014 {
11016 queue,
11017 dvh->dv->vl,
11018 dvh,
11019 sizeof(struct GNUNET_PeerIdentity)
11020 * (1 + dvh->distance)
11021 + sizeof(struct TransportDVBoxMessage)
11022 + sizeof(struct TransportDVBoxPayloadP));
11023 }
11024 }
11025 if (NULL == sc.best)
11026 {
11027 /* no message pending, nothing to do here! */
11029 "No pending messages, queue `%s' to %s now idle\n",
11030 queue->address,
11031 GNUNET_i2s (&n->pid));
11032 if (GNUNET_YES == sc.to_early)
11033 schedule_transmit_on_queue (sc.to_early_retry_delay,
11034 queue,
11036 queue->idle = GNUNET_YES;
11037 return;
11038 }
11039 /* There is a message pending, we are certainly not idle */
11040 queue->idle = GNUNET_NO;
11041
11042 /* Given selection in `sc`, do transmission */
11043 pm = sc.best;
11045 "Selected message <%" PRIu64 ">\n",
11046 pm->logging_uuid);
11047 if (NULL != sc.dvh)
11048 {
11050 "Is this %u a DV box?\n",
11051 pm->pmt);
11052 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11053 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11054 {
11056 "Discard old box, because we have a new DV path.\n");
11057 free_pending_message (sc.best->bpm);
11058 sc.best->bpm = NULL;
11059 }
11060
11061 if (NULL == sc.best->bpm)
11062 {
11064 "encapsulate_for_dv 2\n");
11065 encapsulate_for_dv (sc.dvh->dv,
11066 1,
11067 &sc.dvh,
11068 (const struct GNUNET_MessageHeader *) &sc.best[1],
11070 &sc,
11071 RMO_NONE,
11072 GNUNET_NO);
11073 GNUNET_assert (NULL != sc.best->bpm);
11075 "%lu %lu %lu %lu %u\n",
11076 sizeof(struct GNUNET_PeerIdentity),
11077 sizeof(struct TransportDVBoxMessage),
11078 sizeof(struct TransportDVBoxPayloadP),
11079 sizeof(struct TransportFragmentBoxMessage),
11080 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11081 sc.best->bpm->used_dvh = sc.dvh;
11082 }
11083 pm = sc.best->bpm;
11084 }
11085 if (GNUNET_YES == sc.frag)
11086 {
11087 pm = fragment_message (queue, sc.dvh, pm);
11088 if (NULL == pm)
11089 {
11091 "Fragmentation failed queue %s to %s for <%" PRIu64
11092 ">, trying again\n",
11093 queue->address,
11094 GNUNET_i2s (&n->pid),
11095 sc.best->logging_uuid);
11097 queue,
11099 return;
11100 }
11101 }
11102 else if (GNUNET_YES == sc.relb)
11103 {
11105 if (NULL == pm)
11106 {
11107 /* Reliability boxing failed, try next message... */
11108 GNUNET_log (
11110 "Reliability boxing failed queue %s to %s for <%" PRIu64
11111 ">, trying again\n",
11112 queue->address,
11113 GNUNET_i2s (&n->pid),
11114 sc.best->logging_uuid);
11116 queue,
11118 return;
11119 }
11120 }
11121
11122 /* Pass 'pm' for transission to the communicator */
11123 GNUNET_log (
11125 "Passing message <%" PRIu64
11126 "> to queue %s for peer %s (considered %u others)\n",
11127 pm->logging_uuid,
11128 queue->address,
11129 GNUNET_i2s (&n->pid),
11130 sc.consideration_counter);
11131
11132 /* Flow control: increment amount of traffic sent; if we are routing
11133 via DV (and thus the ultimate target of the pending message is for
11134 a different virtual link than the one of the queue), then we need
11135 to use up not only the window of the direct link but also the
11136 flow control window for the DV link! */
11137 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11138
11139 if (pm->vl != queue->neighbour->vl)
11140 {
11141 /* If the virtual link of the queue differs, this better be distance
11142 vector routing! */
11143 GNUNET_assert (NULL != sc.dvh);
11144 /* If we do distance vector routing, we better not do this for a
11145 message that was itself DV-routed */
11146 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11147 /* We use the size of the unboxed message here, to avoid counting
11148 the DV-Box header which is eaten up on the way by intermediaries */
11149 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11150 }
11151 else
11152 {
11153 GNUNET_assert (NULL == sc.dvh);
11154 }
11155
11156 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11157
11158 /* Check if this transmission somehow conclusively finished handing 'pm'
11159 even without any explicit ACKs */
11160 if ((PMT_CORE == pm->pmt) ||
11161 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11162 {
11164 }
11165 else
11166 {
11167 struct GNUNET_TIME_Relative wait_duration;
11168 unsigned int wait_multiplier;
11169
11170 if (PMT_FRAGMENT_BOX == pm->pmt)
11171 {
11172 struct PendingMessage *root;
11173
11174 root = pm->frag_parent;
11175 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11176 root = root->frag_parent;
11177
11178 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11179 / ((double) root->frag_off
11180 / (double) root->frag_count))
11181 * 4;
11182 }
11183 else
11184 {
11185 // No fragments, we use 4 RTT before retransmitting.
11186 wait_multiplier = 4;
11187 }
11188
11189 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11190 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11191
11193 "Wait multiplier %u\n",
11194 wait_multiplier);
11195
11196 /* Message not finished, waiting for acknowledgement.
11197 Update time by which we might retransmit 's' based on queue
11198 characteristics (i.e. RTT); it takes one RTT for the message to
11199 arrive and the ACK to come back in the best case; but the other
11200 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11201 retransmitting.
11202
11203 OPTIMIZE: Note that in the future this heuristic should likely
11204 be improved further (measure RTT stability, consider message
11205 urgency and size when delaying ACKs, etc.) */
11206
11207 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11208 queue->pd.aged_rtt.rel_value_us)
11209 wait_duration = queue->pd.aged_rtt;
11210 else
11211 {
11212 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11213 wait_multiplier = 4;
11214 }
11215 {
11218 wait_duration, wait_multiplier));
11220 wait_duration, wait_multiplier);
11222 "Waiting %s for ACK until %s\n",
11227 GNUNET_TIME_relative_multiply (wait_duration,
11228 wait_multiplier))
11229 );
11230 }
11231 }
11232 /* finally, re-schedule queue transmission task itself */
11234 queue,
11236}
11237
11238
11245static void
11247 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11248{
11249 struct TransportClient *tc = cls;
11250
11251 if (CT_COMMUNICATOR != tc->type)
11252 {
11253 GNUNET_break (0);
11255 return;
11256 }
11257 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11258 queue = queue->next_client)
11259 {
11260 struct Neighbour *neighbour = queue->neighbour;
11261
11262 if ((ntohl (dqm->qid) != queue->qid) ||
11263 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11264 continue;
11266 "Dropped queue %s to peer %s\n",
11267 queue->address,
11268 GNUNET_i2s (&neighbour->pid));
11269 free_queue (queue);
11271 return;
11272 }
11273 GNUNET_break (0);
11275}
11276
11277
11278static void
11280 struct TransportClient *tc)
11281{
11282 struct PendingMessage *pm;
11283
11284 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11285 qe->queue->queue_tail,
11286 qe);
11287 qe->queue->queue_length--;
11288 tc->details.communicator.total_queue_length--;
11290 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11291 qe->queue->address,
11292 qe->queue->qid,
11293 GNUNET_i2s (&qe->queue->neighbour->pid),
11294 qe->queue->queue_length,
11295 tc->details.communicator.total_queue_length);
11296
11297 /* if applicable, resume transmissions that waited on ACK */
11299 tc->details.communicator.total_queue_length)
11300 {
11301 /* Communicator dropped below threshold, resume all queues
11302 incident with this client! */
11304 GST_stats,
11305 "# Transmission throttled due to communicator queue limit",
11306 -1,
11307 GNUNET_NO);
11308 for (struct Queue *queue = tc->details.communicator.queue_head;
11309 NULL != queue;
11310 queue = queue->next_client)
11311 {
11313 queue,
11315 }
11316 }
11317 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11318 {
11319 /* queue dropped below threshold; only resume this one queue */
11321 "# Transmission throttled due to queue queue limit",
11322 -1,
11323 GNUNET_NO);
11325 qe->queue,
11327 }
11328 else if (1 == qe->queue->q_capacity)
11329 {
11330 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11332 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11333 PRIu64 ".\n",
11334 qe->queue->qid,
11335 qe->queue->q_capacity);
11336 /* message queue has capacity; only resume this one queue */
11337 /* queue dropped below threshold; only resume this one queue */
11339 "# Transmission throttled due to message queue capacity",
11340 -1,
11341 GNUNET_NO);
11343 qe->queue,
11345 }
11346
11347 if (NULL != (pm = qe->pm))
11348 {
11349 struct VirtualLink *vl;
11350
11351 // GNUNET_assert (qe == pm->qe);
11352 pm->qe = NULL;
11353 /* If waiting for this communicator may have blocked transmission
11354 of pm on other queues for this neighbour, force schedule
11355 transmit on queue for queues of the neighbour */
11356 if (NULL == pm->frag_parent)
11357 {
11358 vl = pm->vl;
11359 if ((NULL != vl) &&
11360 (NULL != vl->pending_msg_head) &&
11361 (vl->pending_msg_head == pm))
11363 }
11364 }
11365 GNUNET_free (qe);
11366}
11367
11368
11375static void
11377 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11378{
11379 struct TransportClient *tc = cls;
11380 struct QueueEntry *qe;
11381
11382 if (CT_COMMUNICATOR != tc->type)
11383 {
11384 GNUNET_break (0);
11386 return;
11387 }
11388
11389 /* find our queue entry matching the ACK */
11390 qe = NULL;
11392 "Looking for queue for PID %s\n",
11393 GNUNET_i2s (&sma->receiver));
11394 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11395 queue = queue->next_client)
11396 {
11397 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11398 continue;
11400 "Found PID %s\n",
11401 GNUNET_i2s (&queue->neighbour->pid));
11402
11403
11404 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11405 qep = qep->next)
11406 {
11407 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11408 sma->qid))
11409 continue;
11411 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11412 PRIu64 " Ack QID %u\n",
11413 qep->mid,
11414 queue->qid,
11415 GNUNET_ntohll (sma->mid),
11416 ntohl (sma->qid));
11417 qe = qep;
11418 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11420 "For pending message %" PRIu64 " we had retransmissions.\n",
11421 qe->pm->logging_uuid);
11422 break;
11423 }
11424 }
11425 if (NULL == qe)
11426 {
11428 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11429 GNUNET_ntohll (sma->mid),
11430 ntohl (sma->qid));
11431 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11432 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11433 /* this should never happen */
11434 // GNUNET_break (0);
11435 // GNUNET_SERVICE_client_drop (tc->client);
11437 return;
11438 }
11441}
11442
11443
11449static void
11451{
11453}
11454
11455
11465static int
11467 const struct GNUNET_PeerIdentity *pid,
11468 void *value)
11469{
11470 struct TransportClient *tc = cls;
11471 struct Neighbour *neighbour = value;
11472
11473 GNUNET_assert (CT_MONITOR == tc->type);
11474 for (struct Queue *q = neighbour->queue_head; NULL != q;
11475 q = q->next_neighbour)
11476 {
11477 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11478 .cs = q->cs,
11479 .num_msg_pending = q->num_msg_pending,
11480 .num_bytes_pending = q->num_bytes_pending };
11481
11482 notify_monitor (tc, pid, q->address, q->nt, &me);
11483 }
11484 return GNUNET_OK;
11485}
11486
11487
11494static void
11497{
11498 struct TransportClient *tc = cls;
11499
11500 if (CT_NONE != tc->type)
11501 {
11502 GNUNET_break (0);
11504 return;
11505 }
11506 tc->type = CT_MONITOR;
11507 tc->details.monitor.peer = start->peer;
11508 tc->details.monitor.one_shot = ntohl (start->one_shot);
11512}
11513
11514
11522static struct TransportClient *
11524{
11525 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11526 {
11527 if (CT_COMMUNICATOR != tc->type)
11528 continue;
11529 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11530 return tc;
11531 }
11532 GNUNET_log (
11534 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11535 prefix);
11536 return NULL;
11537}
11538
11539
11547static void
11549{
11550 static uint32_t idgen;
11551 struct TransportClient *tc;
11552 char *prefix;
11553 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11554 struct GNUNET_MQ_Envelope *env;
11555 size_t alen;
11556
11558 if (NULL == prefix)
11559 {
11560 GNUNET_break (0); /* We got an invalid address!? */
11561 return;
11562 }
11564 if (NULL == tc)
11565 {
11567 "# Suggestions ignored due to missing communicator",
11568 1,
11569 GNUNET_NO);
11571 "Cannot connect to %s at `%s', no matching communicator present\n",
11572 GNUNET_i2s (pid),
11573 address);
11575 return;
11576 }
11577 /* forward suggestion for queue creation to communicator */
11579 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11580 (unsigned int) idgen,
11581 prefix,
11582 GNUNET_i2s (pid),
11583 address);
11585 alen = strlen (address) + 1;
11586 env =
11588 cqm->request_id = htonl (idgen++);
11589 cqm->receiver = *pid;
11590 memcpy (&cqm[1], address, alen);
11591 GNUNET_MQ_send (tc->mq, env);
11592}
11593
11594
11602static void
11604{
11606 struct GNUNET_TIME_Absolute monotonic_time;
11607
11608 if (NULL != vs->revalidation_task)
11609 {
11610 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
11611 vs->revalidation_task = NULL;
11612 }
11613 /*memcpy (&hkey,
11614 &hc,
11615 sizeof (hkey));*/
11617 "Remove key %s for address %s map size %u contains %u\n",
11618 GNUNET_h2s (&vs->hc),
11619 vs->address,
11622 &vs->hc));
11624
11626 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
11627 vs->last_challenge_use.abs_value_us)
11628 {
11629 vs->first_challenge_use = monotonic_time;
11630 }
11631 vs->last_challenge_use = monotonic_time;
11632 tvc.header.type =
11634 tvc.header.size = htons (sizeof(tvc));
11635 tvc.reserved = htonl (0);
11636 tvc.challenge = vs->challenge;
11637 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
11639 "Sending address validation challenge %s to %s\n",
11641 GNUNET_i2s (&q->neighbour->pid));
11642 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
11643}
11644
11645
11651static void
11653{
11654 struct ValidationState *vs;
11655 struct Queue *q;
11657 GST_cfg);
11658
11659 (void) cls;
11660 validation_task = NULL;
11662 /* drop validations past their expiration */
11663 while (
11664 (NULL != vs) &&
11666 {
11668 "Validation response %s cleaned up\n",
11669 GNUNET_sh2s (&vs->challenge.value));
11672 }
11673 if (NULL == vs)
11674 {
11676 "Address validation task not scheduled anymore, nothing to do\n");
11677 return; /* woopsie, no more addresses known, should only
11678 happen if we're really a lonely peer */
11679 }
11680 q = find_queue (&vs->pid, vs->address);
11681 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
11682 {
11684 "To early to start next address validation for challenge %s\n",
11685 GNUNET_sh2s (&vs->challenge.value));
11686 return;
11687 }
11688 if (NULL == q)
11689 {
11690 vs->awaiting_queue = GNUNET_YES;
11691 suggest_to_connect (&vs->pid, vs->address);
11692 }
11693 else
11695 /* Finally, reschedule next attempt */
11696 vs->challenge_backoff =
11697 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
11700 "Address validation task will run again in %s\n",
11701 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
11702 GNUNET_YES));
11705 vs->challenge_backoff));
11706}
11707
11708
11713{
11717 struct Queue *q;
11718
11722 unsigned int quality_count;
11723
11727 unsigned int num_queues;
11728
11733 unsigned int k;
11734};
11735
11736
11748static int
11750 const struct GNUNET_PeerIdentity *pid,
11751 void *value)
11752{
11753 struct QueueQualityContext *ctx = cls;
11754 struct Neighbour *n = value;
11755 int do_inc;
11756
11757 (void) pid;
11758 do_inc = GNUNET_NO;
11759 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
11760 {
11761 ctx->num_queues++;
11762 if (0 == ctx->k--)
11763 ctx->q = q;
11764 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
11765 statistics and consider those as well here? */
11766 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
11767 do_inc = GNUNET_YES;
11768 }
11769 if (GNUNET_YES == do_inc)
11770 ctx->quality_count++;
11771 return GNUNET_OK;
11772}
11773
11774
11786static void
11788{
11789 struct LearnLaunchEntry *lle;
11790 struct QueueQualityContext qqc;
11791 struct TransportDVLearnMessage dvl;
11792
11793 (void) cls;
11794 dvlearn_task = NULL;
11796 return; /* lost all connectivity, cannot do learning */
11797 qqc.quality_count = 0;
11798 qqc.num_queues = 0;
11802 &qqc);
11804 {
11805 struct GNUNET_TIME_Relative delay;
11806 unsigned int factor;
11807
11808 /* scale our retries by how far we are above the threshold */
11812 "At connection quality %u, will launch DV learn in %s\n",
11813 qqc.quality_count,
11816 return;
11817 }
11818 /* remove old entries in #dvlearn_map if it has grown too big */
11819 while (MAX_DV_LEARN_PENDING <=
11821 {
11822 lle = lle_tail;
11825 &lle->challenge.value,
11826 lle));
11828 GNUNET_free (lle);
11829 }
11830 /* setup data structure for learning */
11831 lle = GNUNET_new (struct LearnLaunchEntry);
11833 &lle->challenge,
11834 sizeof(lle->challenge));
11836 "Starting launch DV learn with challenge %s\n",
11837 GNUNET_sh2s (&lle->challenge.value));
11842 &lle->challenge.value,
11843 lle,
11846 dvl.header.size = htons (sizeof(dvl));
11847 dvl.num_hops = htons (0);
11848 dvl.bidirectional = htons (0);
11850 dvl.monotonic_time =
11852 {
11853 struct DvInitPS dvip = {
11854 .purpose.purpose = htonl (
11856 .purpose.size = htonl (sizeof(dvip)),
11857 .monotonic_time = dvl.monotonic_time,
11858 .challenge = lle->challenge
11859 };
11860
11862 &dvip,
11863 &dvl.init_sig);
11864 }
11866 dvl.challenge = lle->challenge;
11867
11868 qqc.quality_count = 0;
11870 qqc.num_queues = 0;
11871 qqc.q = NULL;
11874 &qqc);
11875 GNUNET_assert (NULL != qqc.q);
11876
11877 /* Do this as close to transmission time as possible! */
11879
11880 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
11881 /* reschedule this job, randomizing the time it runs (but no
11882 actual backoff!) */
11886 NULL);
11887}
11888
11889
11897static char *
11899{
11900 const char *colon;
11901 char *colon_rest;
11902 size_t colon_rest_length;
11903 char *address_without_port;
11904
11905 colon = strchr (address,':');
11906 colon_rest = GNUNET_strndup (address, colon - address);
11907 colon_rest_length = strlen (colon_rest);
11908 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
11909 GNUNET_free (colon_rest);
11910
11911 return address_without_port;
11912}
11913
11914
11924static int
11926 const struct GNUNET_PeerIdentity *pid,
11927 void *value)
11928{
11929 struct Queue *q = cls;
11930 struct ValidationState *vs = value;
11931 char *address_without_port_vs;
11932 char *address_without_port_q;
11933 int success = GNUNET_YES;
11934
11935 // TODO Check if this is really necessary.
11936 address_without_port_vs = get_address_without_port (vs->address);
11937 address_without_port_q = get_address_without_port (q->address);
11938
11940 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
11941 GNUNET_i2s (pid),
11942 address_without_port_vs,
11943 address_without_port_q);
11944 (void) pid;
11945 if ((GNUNET_YES == vs->awaiting_queue) &&
11946 (0 == strcmp (address_without_port_vs, address_without_port_q)))
11947 {
11948
11949 vs->awaiting_queue = GNUNET_NO;
11951 success = GNUNET_NO;
11952 }
11953
11954 GNUNET_free (address_without_port_vs);
11955 GNUNET_free (address_without_port_q);
11956 return success;
11957}
11958
11959
11968static void
11970 const struct GNUNET_PEERSTORE_Record *record,
11971 const char *emsg)
11972{
11973 struct Neighbour *n = cls;
11974 struct GNUNET_TIME_AbsoluteNBO *mtbe;
11975
11976 (void) emsg;
11977 if (NULL == record)
11978 {
11979 /* we're done with #neighbour_dv_monotime_cb() invocations,
11980 continue normal processing */
11981 n->get = NULL;
11983 return;
11984 }
11985 if (0 == record->value_size)
11986 {
11988 GNUNET_break (0);
11989 return;
11990 }
11991 mtbe = record->value;
11996}
11997
11998
11999static void
12001 const struct GNUNET_PeerIdentity *pid,
12002 const char *uri)
12003{
12004 struct Queue *queue = cls;
12005 struct sockaddr_in v4;
12006 const char *slash;
12007 char *address_uri;
12008 char *prefix;
12009 char *uri_without_port;
12010 char *address_uri_without_port;
12011
12012 slash = strrchr (uri, '/');
12013 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12014 GNUNET_assert (NULL != slash);
12015 slash++;
12016 GNUNET_asprintf (&address_uri,
12017 "%s-%s",
12018 prefix,
12019 slash);
12020
12022 "1 not global natted_address %u %s %s %s\n",
12023 queue->is_global_natted,
12024 uri,
12025 queue->address,
12026 slash);
12027
12028 uri_without_port = get_address_without_port (address_uri);
12029 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12030 {
12032 GNUNET_free (address_uri);
12033 GNUNET_free (uri_without_port);
12034 return;
12035 }
12036
12038 "2 not global natted_address %u %s %s\n",
12039 queue->is_global_natted,
12040 uri,
12041 queue->address);
12042
12043 if (GNUNET_NO == queue->is_global_natted)
12044 {
12046 GNUNET_free (address_uri);
12047 GNUNET_free (uri_without_port);
12048 return;
12049 }
12050
12052 "3 not global natted_address %u %s %s\n",
12053 queue->is_global_natted,
12054 uri,
12055 queue->address);
12056
12057 if (0 == strcmp (uri_without_port, address_uri))
12058 {
12060 GNUNET_free (address_uri);
12061 GNUNET_free (uri_without_port);
12062 return;
12063 }
12064
12066 "4 not global natted_address %u %s %s\n",
12067 queue->is_global_natted,
12068 uri,
12069 queue->address);
12070
12071 address_uri_without_port = get_address_without_port (queue->address);
12072 if (0 == strcmp (uri_without_port, address_uri_without_port))
12073 {
12074 queue->is_global_natted = GNUNET_NO;
12075 }
12076
12078 "not global natted_address %u %s %s %s %s %s %u\n",
12079 queue->is_global_natted,
12080 uri,
12081 queue->address,
12082 uri_without_port,
12083 address_uri_without_port,
12084 prefix,
12085 GNUNET_NO);
12087 GNUNET_free (address_uri);
12088 GNUNET_free (address_uri_without_port);
12089 GNUNET_free (uri_without_port);
12090}
12091
12092
12094{
12098 char *addr;
12099
12104};
12105
12106
12107static enum GNUNET_GenericReturnValue
12109 const struct GNUNET_PeerIdentity *pid,
12110 void *value)
12111{
12112 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12113 struct TransportGlobalNattedAddress *tgna = value;
12114 char *addr = (char *) &tgna[1];
12115
12117 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12118 tgna,
12119 addr,
12120 ntohl (tgna->address_length),
12121 strlen (tgna_cls->addr));
12122 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12123 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12124 {
12125 tgna_cls->tgna = tgna;
12126 return GNUNET_NO;
12127 }
12128 return GNUNET_YES;
12129}
12130
12131
12132static void
12134{
12136 "Error in PEERSTORE monitoring for checking global natted\n");
12137}
12138
12139
12140static void
12142{
12144 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12145}
12146
12147
12148static void
12150 const struct GNUNET_PEERSTORE_Record *record,
12151 const char *emsg)
12152{
12153 struct Queue *queue = cls;
12154 struct Neighbour *neighbour = queue->neighbour;
12156 struct GNUNET_MessageHeader *hello;
12158 size_t address_len_without_port;
12159
12160 if (NULL != emsg)
12161 {
12163 "Got failure from PEERSTORE: %s\n",
12164 emsg);
12165 return;
12166 }
12167 if (0 == record->value_size)
12168 {
12170 GNUNET_break (0);
12171 return;
12172 }
12173 queue->is_global_natted = GNUNET_YES;
12174 hello = record->value;
12177 "before not global natted %u\n",
12178 queue->is_global_natted);
12181 queue);
12183 "after not global natted %u\n",
12184 queue->is_global_natted);
12186
12187 tgna_cls.addr = get_address_without_port (queue->address);
12188 address_len_without_port = strlen (tgna_cls.addr);
12189 /*{
12190 char buf[address_len_without_port + 1];
12191
12192 GNUNET_memcpy (&buf, addr, address_len_without_port);
12193 buf[address_len_without_port] = '\0';
12194 GNUNET_free (addr);
12195 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12196 }*/
12197 tgna_cls.tgna = NULL;
12199 &neighbour->pid,
12201 &tgna_cls);
12202 if (NULL != tgna_cls.tgna)
12204 " tgna_cls.tgna tgna %p %lu %u %u\n",
12205 tgna_cls.tgna,
12206 neighbour->size_of_global_addresses,
12207 ntohl (tgna_cls.tgna->address_length),
12208 neighbour->number_of_addresses);
12209 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12210 {
12211 struct TransportGlobalNattedAddress *tgna;
12212
12213 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12214 + address_len_without_port);
12215 tgna->address_length = htonl (address_len_without_port);
12216 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12218 &neighbour->pid,
12219 tgna,
12221 neighbour->number_of_addresses++;
12222 neighbour->size_of_global_addresses += address_len_without_port + 1;
12224 "Created tgna %p with address %s and length %lu\n",
12225 tgna,
12226 tgna_cls.addr,
12227 address_len_without_port + 1);
12228 }
12229 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12230 {
12232 &neighbour->pid,
12233 tgna_cls.tgna);
12234 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12236 );
12237 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12238 ;
12239 GNUNET_assert (0 < neighbour->number_of_addresses);
12240 neighbour->number_of_addresses--;
12242 "removed tgna %p\n",
12243 tgna_cls.tgna);
12244 GNUNET_free (tgna_cls.tgna);
12245 }
12247 GNUNET_free (tgna_cls.addr);
12248}
12249
12250
12257static void
12259 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12260{
12261 struct TransportClient *tc = cls;
12262 struct Queue *queue;
12263 struct Neighbour *neighbour;
12264 const char *addr;
12265 uint16_t addr_len;
12266
12267 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12268 {
12269 /* MTU so small as to be useless for transmissions,
12270 required for #fragment_message()! */
12271 GNUNET_break_op (0);
12273 return;
12274 }
12275 /* This may simply be a queue update */
12276 for (queue = tc->details.communicator.queue_head;
12277 NULL != queue;
12278 queue = queue->next_client)
12279 {
12280 if (queue->qid != ntohl (aqm->qid))
12281 continue;
12282 break;
12283 }
12284
12285 if (NULL != queue)
12286 {
12287 neighbour = queue->neighbour;
12288 }
12289 else
12290 {
12291 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12292
12293 neighbour = lookup_neighbour (&aqm->receiver);
12294 if (NULL == neighbour)
12295 {
12296 neighbour = GNUNET_new (struct Neighbour);
12298 GNUNET_YES);
12299 neighbour->pid = aqm->receiver;
12302 neighbours,
12303 &neighbour->pid,
12304 neighbour,
12306 neighbour->get =
12308 "transport",
12309 &neighbour->pid,
12312 neighbour);
12313 }
12314 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12315 addr = (const char *) &aqm[1];
12317 "New queue %s to %s available with QID %u and q_len %" PRIu64
12318 " and mtu %u\n",
12319 addr,
12320 GNUNET_i2s (&aqm->receiver),
12321 ntohl (aqm->qid),
12322 GNUNET_ntohll (aqm->q_len),
12323 ntohl (aqm->mtu));
12324 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12325 queue->tc = tc;
12326 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12327 next_neighbour)
12328 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12329 validated_until);
12330 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12331 {
12333 "New queue with QID %u inherit validated until\n",
12334 ntohl (aqm->qid));
12335 queue->validated_until = validated_until;
12336 }
12337 queue->address = (const char *) &queue[1];
12338 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12339 queue->qid = ntohl (aqm->qid);
12340 queue->neighbour = neighbour;
12342 queue->unlimited_length = GNUNET_YES;
12343 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12344 memcpy (&queue[1], addr, addr_len);
12345 /* notify monitors about new queue */
12346 {
12347 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12348
12349 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12350 }
12352 neighbour->queue_head,
12353 neighbour->queue_tail,
12354 queue);
12356 tc->details.communicator.queue_head,
12357 tc->details.communicator.queue_tail,
12358 queue);
12359
12360 }
12361 queue->mtu = ntohl (aqm->mtu);
12362 queue->nt = ntohl (aqm->nt);
12363 queue->cs = ntohl (aqm->cs);
12364 queue->idle = GNUNET_YES;
12365
12366 {
12367 struct sockaddr_in v4;
12368 char *addr_without = get_address_without_port (queue->address);
12369 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12370 {
12372 "start not global natted\n");
12374 GNUNET_YES,
12375 "peerstore",
12376 &neighbour->pid,
12378 &
12380 NULL,
12381 &
12383 NULL,
12385 queue);
12386 }
12387 GNUNET_free (addr_without);
12388 }
12389 /* check if valdiations are waiting for the queue */
12391 &aqm->receiver))
12392 {
12395 &aqm->
12396 receiver,
12397 &
12399 queue))
12400 start_address_validation (&aqm->receiver, queue->address);
12401 }
12402 else
12403 start_address_validation (&aqm->receiver, queue->address);
12404 /* look for traffic for this queue */
12405 // TODO Check whether this makes any sense at all.
12406 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12407 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12408 /* might be our first queue, try launching DV learning */
12409 if (NULL == dvlearn_task)
12412}
12413
12414
12421static void
12423 const struct
12425{
12426 struct TransportClient *tc = cls;
12427 struct Queue *target_queue = NULL;
12428
12430 "Received queue update message for %u with q_len %llu and mtu %u\n",
12431 ntohl (msg->qid),
12432 (unsigned long long) GNUNET_ntohll (msg->q_len),
12433 ntohl (msg->mtu));
12434 for (target_queue = tc->details.communicator.queue_head;
12435 NULL != target_queue;
12436 target_queue = target_queue->next_client)
12437 {
12438 if (ntohl (msg->qid) == target_queue->qid)
12439 break;
12440 }
12441 if (NULL == target_queue)
12442 {
12444 "Queue to update no longer exists! Discarding update.\n");
12445 return;
12446 }
12447
12448 target_queue->nt = msg->nt;
12449 target_queue->mtu = ntohl (msg->mtu);
12450 target_queue->cs = msg->cs;
12451 target_queue->priority = ntohl (msg->priority);
12452 /* The update message indicates how many messages
12453 * the queue should be able to handle.
12454 */
12456 target_queue->unlimited_length = GNUNET_YES;
12457 else
12458 target_queue->unlimited_length = GNUNET_NO;
12459 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12460 if (0 < target_queue->q_capacity)
12462 target_queue,
12465}
12466
12467
12475static void
12477 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12478{
12479 struct TransportClient *tc = cls;
12480
12481 if (CT_COMMUNICATOR != tc->type)
12482 {
12483 GNUNET_break (0);
12485 return;
12486 }
12488 "# Suggestions succeeded at communicator",
12489 1,
12490 GNUNET_NO);
12492 "Request #%u for communicator to create queue succeeded\n",
12493 (unsigned int) ntohs (cqr->request_id));
12495}
12496
12497
12506static void
12508 void *cls,
12509 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12510{
12511 struct TransportClient *tc = cls;
12512
12513 if (CT_COMMUNICATOR != tc->type)
12514 {
12515 GNUNET_break (0);
12517 return;
12518 }
12520 "Request #%u for communicator to create queue failed\n",
12521 (unsigned int) ntohs (cqr->request_id));
12523 "# Suggestions failed in queue creation at communicator",
12524 1,
12525 GNUNET_NO);
12527}
12528
12529
12537static void
12539{
12540 struct TransportClient *tc = cls;
12541 struct PeerRequest *pr;
12542
12543 if (CT_APPLICATION != tc->type)
12544 {
12545 GNUNET_break (0);
12547 return;
12548 }
12549 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
12550 &msg->peer);
12551 if (NULL == pr)
12552 {
12553 GNUNET_break (0);
12555 return;
12556 }
12557 (void) stop_peer_request (tc, &pr->pid, pr);
12559}
12560
12561
12562static void
12564 const struct GNUNET_PeerIdentity *pid,
12565 const char *uri)
12566{
12567 struct Queue *q;
12568 int pfx_len;
12569 const char *eou;
12570 char *address;
12571 (void) cls;
12572
12573 eou = strstr (uri,
12574 "://");
12575 pfx_len = eou - uri;
12576 eou += 3;
12578 "%.*s-%s",
12579 pfx_len,
12580 uri,
12581 eou);
12582
12584 "hello for client %s\n",
12585 address);
12586
12587 q = find_queue (pid, address);
12588 if (NULL == q)
12589 {
12591 }
12592 else
12595}
12596
12597
12605static void
12607 const struct GNUNET_PEERSTORE_Record *record,
12608 const char *emsg)
12609{
12610 struct PeerRequest *pr = cls;
12612 struct GNUNET_MessageHeader *hello;
12613
12614 if (NULL != emsg)
12615 {
12617 "Got failure from PEERSTORE: %s\n",
12618 emsg);
12619 return;
12620 }
12621 hello = record->value;
12622 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
12623 {
12625 return;
12626 }
12630 NULL);
12632}
12633
12634
12635static void
12637{
12639 "Error in PEERSTORE monitoring\n");
12640}
12641
12642
12643static void
12645{
12647 "Done with initial PEERSTORE iteration during monitoring\n");
12648}
12649
12650
12658static void
12660{
12661 struct TransportClient *tc = cls;
12662 struct PeerRequest *pr;
12663
12664 if (CT_NONE == tc->type)
12665 {
12666 tc->type = CT_APPLICATION;
12667 tc->details.application.requests =
12669 }
12670 if (CT_APPLICATION != tc->type)
12671 {
12672 GNUNET_break (0);
12674 return;
12675 }
12677 "Client suggested we talk to %s with preference %d at rate %u\n",
12678 GNUNET_i2s (&msg->peer),
12679 (int) ntohl (msg->pk),
12680 (int) ntohl (msg->bw.value__));
12681 pr = GNUNET_new (struct PeerRequest);
12682 pr->tc = tc;
12683 pr->pid = msg->peer;
12684 pr->bw = msg->bw;
12685 pr->pk = ntohl (msg->pk);
12687 tc->details.application.requests,
12688 &pr->pid,
12689 pr,
12691 {
12692 GNUNET_break (0);
12693 GNUNET_free (pr);
12695 return;
12696 }
12697 pr->nc =
12699 GNUNET_YES,
12700 "peerstore",
12701 NULL,
12704 NULL,
12706 NULL,
12708 pr);
12710}
12711
12712
12721static int
12723 const struct RequestHelloValidationMessage *m)
12724{
12725 (void) cls;
12727 return GNUNET_OK;
12728}
12729
12730
12738static void
12740 const struct RequestHelloValidationMessage *m)
12741{
12742 struct TransportClient *tc = cls;
12743 struct Queue *q;
12744
12745 q = find_queue (&m->peer, (const char *) &m[1]);
12746 if (NULL == q)
12747 {
12748 suggest_to_connect (&m->peer, (const char *) &m[1]);
12749 }
12750 else
12751 start_address_validation (&m->peer, (const char *) &m[1]);
12753}
12754
12755
12764static int
12766 const struct GNUNET_PeerIdentity *pid,
12767 void *value)
12768{
12769 struct Neighbour *neighbour = value;
12770
12771 (void) cls;
12772 (void) pid;
12773 GNUNET_break (0); // should this ever happen?
12774 free_neighbour (neighbour, GNUNET_YES);
12775
12776 return GNUNET_OK;
12777}
12778
12779
12788static int
12790 const struct GNUNET_PeerIdentity *pid,
12791 void *value)
12792{
12793 struct DistanceVector *dv = value;
12794
12795 (void) cls;
12796 (void) pid;
12797 free_dv_route (dv);
12798
12799 return GNUNET_OK;
12800}
12801
12802
12811static int
12813 const struct GNUNET_PeerIdentity *pid,
12814 void *value)
12815{
12816 struct ValidationState *vs = value;
12817
12818 (void) cls;
12819 (void) pid;
12821 return GNUNET_OK;
12822}
12823
12824
12833static int
12834free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
12835{
12836 struct PendingAcknowledgement *pa = value;
12837
12838 (void) cls;
12839 (void) key;
12841 return GNUNET_OK;
12842}
12843
12844
12853static int
12855 const struct GNUNET_PeerIdentity *pid,
12856 void *value)
12857{
12858 struct AcknowledgementCummulator *ac = value;
12859
12860 (void) cls;
12861 (void) pid;
12863 GNUNET_free (ac);
12864 return GNUNET_OK;
12865}
12866
12867
12874static void
12875do_shutdown (void *cls)
12876{
12877 struct LearnLaunchEntry *lle;
12878 (void) cls;
12879
12881 "shutdown logic\n");
12884 &free_neighbour_cb, NULL);
12885 if (NULL != validation_task)
12886 {
12888 validation_task = NULL;
12889 }
12890 if (NULL != dvlearn_task)
12891 {
12893 dvlearn_task = NULL;
12894 }
12896 dvlearn_map = NULL;
12898 validation_heap = NULL;
12901 dv_routes = NULL;
12902 if (NULL != GST_stats)
12903 {
12905 GST_stats = NULL;
12906 }
12907 if (NULL != GST_my_hello)
12908 {
12910 GST_my_hello = NULL;
12911 }
12912 if (NULL != GST_my_private_key)
12913 {
12915 GST_my_private_key = NULL;
12916 }
12919 NULL);
12921 ack_cummulators = NULL;
12924 NULL);
12926 pending_acks = NULL;
12929 neighbours = NULL;
12932 links = NULL;
12935 NULL);
12937 backtalkers = NULL;
12940 NULL);
12942 validation_map = NULL;
12944 revalidation_map = NULL;
12945 while (NULL != ir_head)
12947 GNUNET_assert (0 == ir_total);
12948 while (NULL != (lle = lle_head))
12949 {
12951 GNUNET_free (lle);
12952 }
12953 if (NULL != peerstore)
12954 {
12956 "Disconnecting from PEERSTORE service\n");
12958 peerstore = NULL;
12959 }
12961}
12962
12963
12964static void
12965shutdown_task (void *cls)
12966{
12968
12970 "Shutdown task executed\n");
12971 if (NULL != clients_head)
12972 {
12973 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
12974 {
12976 "client still connected: %u\n",
12977 tc->type);
12978 }
12979 }
12980 else
12981 do_shutdown (cls);
12982
12983}
12984
12985
12993static void
12994run (void *cls,
12995 const struct GNUNET_CONFIGURATION_Handle *c,
12997{
12998 (void) cls;
12999 (void) service;
13000 /* setup globals */
13003 GST_cfg = c;
13011 GNUNET_YES);
13018 if (NULL == GST_my_private_key)
13019 {
13020 GNUNET_log (
13022 _ (
13023 "Transport service is lacking key configuration settings. Exiting.\n"));
13025 return;
13026 }
13030 "My identity is `%s'\n",
13034 "transport",
13035 "USE_BURST_NAT");
13036 if (GNUNET_SYSERR == use_burst)
13038 "Could not configure burst nat use. Default to no.\n");
13043 "transport",
13044 0,
13045 0,
13046 NULL,
13047 0,
13048 NULL,
13049 NULL,
13050 NULL);
13051 if (NULL == peerstore)
13052 {
13053 GNUNET_break (0);
13055 return;
13056 }
13057}
13058
13059
13065 "transport",
13067 &run,
13070 NULL,
13071 /* communication with applications */
13072 GNUNET_MQ_hd_fixed_size (suggest,
13075 NULL),
13076 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13079 NULL),
13080 GNUNET_MQ_hd_var_size (request_hello_validation,
13083 NULL),
13084 /* communication with core */
13085 GNUNET_MQ_hd_fixed_size (client_start,
13087 struct StartMessage,
13088 NULL),
13089 GNUNET_MQ_hd_var_size (client_send,
13091 struct OutboundMessage,
13092 NULL),
13093 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13095 struct RecvOkMessage,
13096 NULL),
13097 /* communication with communicators */
13098 GNUNET_MQ_hd_var_size (communicator_available,
13101 NULL),
13102 GNUNET_MQ_hd_var_size (communicator_backchannel,
13105 NULL),
13106 GNUNET_MQ_hd_var_size (add_address,
13109 NULL),
13110 GNUNET_MQ_hd_fixed_size (del_address,
13113 NULL),
13114 GNUNET_MQ_hd_var_size (incoming_msg,
13117 NULL),
13118 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13121 NULL),
13122 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13125 NULL),
13126 GNUNET_MQ_hd_var_size (add_queue_message,
13129 NULL),
13130 GNUNET_MQ_hd_fixed_size (update_queue_message,
13133 NULL),
13134 GNUNET_MQ_hd_fixed_size (del_queue_message,
13137 NULL),
13138 GNUNET_MQ_hd_fixed_size (send_message_ack,
13141 NULL),
13142 GNUNET_MQ_hd_fixed_size (burst_finished,
13145 NULL),
13146 /* communication with monitors */
13147 GNUNET_MQ_hd_fixed_size (monitor_start,
13150 NULL),
13152
13153
13154/* 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:103
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:38
static int ret
Final status code.
Definition: gnunet-arm.c:93
static char * init
Set to the name of a service to start.
Definition: gnunet-arm.c:73
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
static struct GNUNET_TESTING_Interpreter * is
static struct Queue * queue_head
Head of queue of messages to transmit.
static int prefix
If printing the value of PREFIX has been requested.
Definition: gnunet-config.c:65
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct GNUNET_FS_Handle * ctx
static 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.
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "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(burst_finished, GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED, struct GNUNET_TRANSPORT_BurstFinished, 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 void start_dv_learn(void *cls)
Task run when we CONSIDER initiating a DV learn process.
static int dv_neighbour_selection(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void start_address_validation(const struct GNUNET_PeerIdentity *pid, const char *address)
Start address validation.
static void handle_del_queue_message(void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
Queue to a peer went down.
#define QUEUE_LENGTH_LIMIT
How many messages can we have pending for a given queue (queue to a particular peer via a communicato...
static void update_backtalker_monotime(struct Backtalker *b)
The backtalker b monotonic time changed.
#define MAX_CUMMULATIVE_ACKS
Maximum number of messages we acknowledge together in one cumulative ACK.
#define MAX_DV_HOPS_ALLOWED
Maximum DV distance allowed ever.
static void burst_timeout(void *cls)
#define BACKCHANNEL_INACTIVITY_TIMEOUT
How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
static struct GNUNET_TIME_Relative get_network_latency(const struct TransportDVLearnMessage *dvl)
static void hello_for_client_error_cb(void *cls)
static void check_for_global_natted(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
#define ADDRESS_VALIDATION_LIFETIME
How long do we consider an address valid if we just checked?
static void free_distance_vector_hop(struct DistanceVectorHop *dvh)
Free a dvh.
#define MAX_FC_RETRANSMIT_COUNT
Maximum number of FC retransmissions for a running retransmission task.
static void sign_ephemeral(struct DistanceVector *dv)
Sign ephemeral keys in our dv are current.
static void handle_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment.
static struct PendingMessage * fragment_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Fragment the given pm to the given mtu.
static struct GNUNET_SCHEDULER_Task * validation_task
Task to run address validation.
static void handle_suggest(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void cores_send_connect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we gained a connection.
static void cummulative_ack(const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
static void task_consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define DV_LEARN_QUALITY_THRESHOLD
How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiati...
static void free_neighbour(struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
Release memory used by neighbour.
PendingMessageType
Types of different pending messages.
@ PMT_FRAGMENT_BOX
Fragment box.
@ PMT_DV_BOX
Pending message created during forward_dv_box().
@ PMT_CORE
Ordinary message received from the CORE service.
@ PMT_RELIABILITY_BOX
Reliability box.
static struct GNUNET_TIME_Relative calculate_rtt(struct DistanceVector *dv)
static int check_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int stop_peer_request(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Stop the peer request in value.
static void handle_update_queue_message(void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
Handle updates to queues.
static void cores_send_disconnect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void handle_client_start(void *cls, const struct StartMessage *start)
Initialize a "CORE" client.
#define MAX_DV_PATHS_TO_TARGET
Maximum number of DV paths we keep simultaneously to the same target.
static void free_virtual_link(struct VirtualLink *vl)
Free virtual link.
RouteMessageOptions
Which transmission options are allowable for transmission? Interpreted bit-wise!
@ RMO_UNCONFIRMED_ALLOWED
We are allowed to use unconfirmed queues or DV routes for this message.
@ RMO_DV_ALLOWED
We are allowed to use DV routing for this hdr.
@ RMO_REDUNDANT
If we have multiple choices, it is OK to send this message over multiple channels at the same time to...
@ RMO_NONE
Only confirmed, non-DV direct neighbours.
@ RMO_ANYTHING_GOES
Reliable and unreliable, DV and non-DV are all acceptable.
static 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_burst_finished()
The burst finished.
static void queue_burst(void *cls)
static void handle_monitor_start(void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
Initialize a monitor client.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static void finish_cmc_handling(struct CommunicatorMessageContext *cmc)
static int learn_dv_path(const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
We have learned a path through the network to some other peer, add it to our DV data structure (retur...
static void store_pi(void *cls)
Ask peerstore to store our address.
#define FC_NO_CHANGE_REPLY_PROBABILITY
What is the 1:n chance that we send a Flow control response when receiving a flow control message tha...
static void notify_monitors(const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Send information in me about a peer's status with respect to some address to all monitors that care.
static struct GNUNET_TIME_Relative route_via_neighbour(const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Pick a queue of n under constraints options and schedule transmission of hdr.
#define RECV_WINDOW_SIZE
Window size.
static int check_known_challenge(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the challenge from cls.
static unsigned int check_for_queue_with_higher_prio(struct Queue *queue, struct Queue *queue_head)
Check if the communicator has another queue with higher prio ready for sending.
#define GOODPUT_AGING_SLOTS
Number of slots we keep of historic data for computation of goodput / message loss ratio.
static int free_validation_state_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free validation state.
static int free_neighbour_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free neighbour entry.
static void handle_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static enum GNUNET_GenericReturnValue burst_running
Is there a burst running?
struct GNUNET_HELLO_Builder * GST_my_hello
Our HELLO.
static void start_burst(void *cls)
#define DV_QUALITY_RTT_THRESHOLD
We only consider queues as "quality" connections when suppressing the generation of DV initiation mes...
static struct TransportClient * clients_head
Head of linked list of all clients to this service.
static void handle_validation_challenge(void *cls, const struct TransportValidationChallengeMessage *tvc)
Communicator gave us a transport address validation challenge.
static void dv_hmac(const struct DVKeyState *key, struct GNUNET_HashCode *hmac, const void *data, size_t data_size)
Do HMAC calculation for backchannel messages over data using key material from key.
#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?
struct GNUNET_SCHEDULER_Task * burst_timeout_task
static void free_pending_acknowledgement(struct PendingAcknowledgement *pa)
Release pa data structure.
static struct GNUNET_CONTAINER_MultiUuidmap * pending_acks
Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgemen...
static struct GNUNET_CONTAINER_MultiShortmap * dvlearn_map
Map from challenges to struct LearnLaunchEntry values.
#define DV_FORWARD_TIMEOUT
If a DVBox could not be forwarded after this number of seconds we drop it.
static void finish_handling_raw_message(struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
static void handle_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static void update_queue_performance(struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via q, update metrics.
static void schedule_transmit_on_queue(struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
Called whenever something changed that might effect when we try to do the next transmission on queue ...
static void set_pending_message_uuid(struct PendingMessage *pm)
If necessary, generates the UUID for a pm.
static void free_pending_message(struct PendingMessage *pm)
Release memory associated with pm and remove pm from associated data structures.
static void revalidation_start_cb(void *cls)
static void backtalker_monotime_store_cb(void *cls, int success)
Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
static 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.
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 void iterate_address_start_burst(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct Queue * find_queue(const struct GNUNET_PeerIdentity *pid, const char *address)
Find the queue matching pid and address.
static void activate_core_visible_dv_path(struct DistanceVectorHop *hop)
The hop is a validated path to the respective target peer and we should tell core about it – and sche...
static void free_dv_route(struct DistanceVector *dv)
Free entry in dv_routes.
static unsigned int is_ring_buffer_dv_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static int check_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
#define DEFAULT_WINDOW_SIZE
How big is the flow control window size by default; limits per-neighbour RAM utilization.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate transport service.
#define MAX_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges?
static void handle_queue_create_ok(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue "worked", that is setting up the queue is no...
static int notify_client_connect_info(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new CORE client about all existing connections to peers.
static void shc_cont(void *cls, int success)
static void handle_raw_message(void *cls, const struct GNUNET_MessageHeader *mh)
Communicator gave us an unencapsulated message to pass as-is to CORE.
static void handle_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
static unsigned long long logging_uuid_gen
Generator of logging_uuid in struct PendingMessage.
static int check_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Client notified us about transmission from a peer.
#define REASSEMBLY_EXPIRATION
How long do we keep partially reassembled messages around before giving up?
static void update_next_challenge_time(struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
Set the time for next_challenge of vs to new_time.
static struct Neighbour * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup neighbour for peer pid.
static void peerstore_store_own_cb(void *cls, int success)
Function called when peerstore is done storing our address.
static struct RingBufferEntry * ring_buffer[RING_BUFFER_SIZE]
Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
#define MIN_DELAY_ADDRESS_VALIDATION
What is the maximum frequency at which we do address validation? A random value between 0 and this va...
static void handle_acknowledged(struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
The pa was acknowledged, process the acknowledgement.
static struct GNUNET_CONTAINER_MultiPeerMap * backtalkers
Map from PIDs to struct Backtalker entries.
static struct GNUNET_TIME_Absolute hello_mono_time
Monotonic time we use for HELLOs generated at this time.
static int check_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static void handle_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct GNUNET_CONTAINER_MultiHashMap * revalidation_map
Map from addresses to struct ValidationState entries describing addresses we are aware of and their v...
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
static enum GNUNET_GenericReturnValue revalidate_map_it(void *cls, const struct GNUNET_HashCode *key, void *value)
#define DEFAULT_ACK_WAIT_DURATION
Default value for how long we wait for reliability ack.
static struct PendingMessage * reliability_box_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Reliability-box the given pm.
static int free_backtalker_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Callback to free backtalker records.
static enum GNUNET_GenericReturnValue contains_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void path_cleanup_cb(void *cls)
Task called when we should check if any of the DV paths we have learned to a target are due for garba...
#define FAST_VALIDATION_CHALLENGE_FREQ
What is the fastest rate at which we send challenges if we keep learning an address (gossip,...
static int check_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void demultiplex_with_cmc(struct CommunicatorMessageContext *cmc)
Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the ri...
#define MAX_DV_LEARN_PENDING
Maximum number of DV learning activities we may have pending at the same time.
static void hello_for_client_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void validation_start_cb(void *cls)
Task run periodically to validate some address based on validation_heap.
#define VALIDATION_RTT_BUFFER_FACTOR
How many network RTTs before an address validation expires should we begin trying to revalidate?...
static void handle_client_recv_ok(void *cls, const struct RecvOkMessage *rom)
Client confirms that it is done handling message(s) to a particular peer.
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
static int check_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static int check_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct TransportClient * clients_tail
Tail of linked list of all clients to this service.
static struct GNUNET_CONTAINER_MultiPeerMap * ack_cummulators
Map from PIDs to struct AcknowledgementCummulators.
static void transmit_cummulative_ack_cb(void *cls)
Do the transmission of a cumulative acknowledgement now.
static int check_validation_request_pending(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
A new queue has been created, check if any address validation requests have been waiting for it.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static struct GNUNET_SCHEDULER_Task * burst_task
The task to start the burst.
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 void check_for_burst_address(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
static unsigned int check_next_attempt_tree(struct PendingMessage *pm, struct PendingMessage *root)
static void hello_for_incoming_error_cb(void *cls)
static void queue_send_msg(struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
Send the message payload on queue.
static void dv_setup_key_state_from_km(const struct GNUNET_ShortHashCode *km, const struct GNUNET_ShortHashCode *iv, struct DVKeyState *key)
Given the key material in km and the initialization vector iv, setup the key material for the backcha...
static void handle_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void handle_hello_for_incoming(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static int check_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void dv_encrypt(struct DVKeyState *key, const void *in, void *dst, size_t in_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
static void iterate_address_and_compare_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validi...
static int free_dv_routes_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free DV route entry.
static enum GNUNET_GenericReturnValue add_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR
Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope...
static void handle_queue_create_fail(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue failed.
static void check_link_down(void *cls)
Task run to check whether the hops of the cls still are validated, or if we need to core about discon...
static void check_for_global_natted_error_cb(void *cls)
static void finish_cmc_handling_with_continue(struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
Send ACK to communicator (if requested) and free cmc.
static void forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
Build and forward a DV learn message to next_hop.
static void handle_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Incoming message.
static void validation_transmit_on_queue(struct Queue *q, struct ValidationState *vs)
The queue q (which matches the peer and address in vs) is ready for queueing.
static int free_ack_cummulator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free acknowledgement cummulator.
static void update_pm_next_attempt(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission ...
static int check_known_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the address from cls.
enum GNUNET_GenericReturnValue use_burst
static struct GNUNET_CONTAINER_MultiPeerMap * dv_routes
Map from PIDs to struct DistanceVector entries describing known paths to the peer.
static struct GNUNET_TIME_Relative route_control_message_without_fc(struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
We need to transmit hdr to target.
static void free_incoming_request(struct IncomingRequest *ir)
Release ir data structure.
#define MAX_INCOMING_REQUEST
For how many incoming connections do we try to create a virtual link for (at the same time!...
static void neighbour_dv_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a DV initiator by PEERSTORE.
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
#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.
API to create, modify and access statistics.
API of the transport service towards the communicator processes.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
GNUNET_TRANSPORT_CommunicatorCharacteristics
What characteristics does this communicator have?
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_CS_DOWN
Connection is down.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
Definition: crypto_hpke.c:407
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:201
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
Definition: crypto_hpke.c:312
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer's key from the file specified in the configuration.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_CONTAINER_MDLL_remove(mdll, head, tail, element)
Remove an element from a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_tail(mdll, head, tail, element)
Insert an element at the tail of a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_after(mdll, head, tail, other, element)
Insert an element into a MDLL after the given other element.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_MDLL_insert(mdll, head, tail, element)
Insert an element at the head of a MDLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
Definition: crypto_hash.c:327
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf_expand(void *result, size_t out_len, const struct GNUNET_ShortHashCode *prk,...)
HKDF-Expand using SHA256.
Definition: crypto_hkdf.c:156
struct GNUNET_CONTAINER_MultiUuidmap * GNUNET_CONTAINER_multiuuidmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_remove(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_remove(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, const void *value)
Remove the given key-value pair from the map.
void GNUNET_CONTAINER_multiuuidmap_destroy(struct GNUNET_CONTAINER_MultiUuidmap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_iterate(struct GNUNET_CONTAINER_MultiUuidmap *map, GNUNET_CONTAINER_MultiUuidmapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_put(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multiuuidmap_get(const struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition: hello-uri.c:435
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-uri.c:1310
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg)
Parse msg.
Definition: hello-uri.c:471
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition: hello-uri.c:453
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new(const struct GNUNET_PeerIdentity *pid)
Allocate builder.
Definition: hello-uri.c:401
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_iterate(const struct GNUNET_HELLO_Parser *parser, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a parser.
Definition: hello-uri.c:1201
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:646
char * GNUNET_HELLO_address_to_prefix(const char *address)
Given an address as a string, extract the prefix that identifies the communicator offering transmissi...
Definition: hello-uri.c:1288
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:1168
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
GNUNET_SCHEDULER_Priority
Valid task priorities.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_EXTRA_LOGGING
define GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source tree where gnunet_config....
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:61
#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:76
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition: mq.c:205
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition: mq.c:655
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition: mq.c:896
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
@ GNUNET_MQ_PRIO_BACKGROUND
Lowest priority, i.e.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
@ GNUNET_MQ_PREF_LOW_LATENCY
Flag to indicate that low latency is important.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition: nat.c:89
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition: nat_api.c:703
void GNUNET_NAT_add_global_address(struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
Add global address to the list of addresses and notify clients.
Definition: nat_api.c:460
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:44
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
#define GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME
Key used to store sender's monotonic time from backchannel messages.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
#define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME
Key used to store sender's monotonic time from DV learn messages.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY
Key used for storing HELLOs in the peerstore.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
struct GNUNET_PEERSTORE_StoreHelloContext * GNUNET_PEERSTORE_hello_add(struct GNUNET_PEERSTORE_Handle *h, const struct GNUNET_MessageHeader *msg, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Add hello to peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
P2P message: transport requests confirmation that an address works.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK
transport acknowledges processing an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN
inform transport that a queue was torn down
#define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
Type of the 'struct RequestHelloValidationMessage' send by clients to TRANSPORT to trigger validation...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START
Message from the core saying that the transport server should start giving it messages.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA
Message sent to indicate to a monitor about events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR
Message sent to indicate to the transport which address prefix is supported by a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
Message telling transport to limit its receive rate.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
Type of a fragment of a CORE message created by transport to adjust message length to a queue's MTU.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL
Response from communicator: address bogus, will not try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
Source-routed transport message based DV information gathered.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
Wrapper around non-fragmented CORE message used to measure RTT and ensure reliability.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to abandon bandwidth prefe...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
Message from TRANSPORT notifying about a message that was received.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION
Message type used between transport services when they internally forward communicator backchannel me...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE
transport tells communicator it wants a queue
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
Message sent for topology discovery at transport level.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
Tell transport that it should assist with exchanging a message between communicators.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
Message from TRANSPORT notifying about a client that disconnected from us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG
inform transport about an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK
Response from communicator: will try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK
communicator tells transports that message was sent
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS
inform transport to add an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START
Message sent to indicate to the transport that a monitor wants to observe certain events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS
inform transport to delete an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
P2P message: transport proves that an address worked.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG
transport tells communicator it wants to transmit
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
Request to TRANSPORT to transmit a message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
Confirmation from TRANSPORT that message for transmission has been queued (and that the next message ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
Confirmation for a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP
inform transport that a queue was setup to talk to some peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to establish bandwidth pre...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE
inform transport that a queue was updated
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c: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:1254
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:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
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:1304
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:1277
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:1207
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2483
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2418
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
@ 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:344
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition: time.c:264
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition: time.c:630
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:438
#define GNUNET_TIME_relative_cmp(t1, op, t2)
Compare two relative times.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:368
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:579
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:834
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:605
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply_double(struct GNUNET_TIME_Relative rel, double factor)
Multiply relative time by a given factor.
Definition: time.c:506
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:741
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:587
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:855
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition: time.c:471
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:486
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition: time.c:360
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition: time.c:620
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:452
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition: time.c:864
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:552
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition: time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:640
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:640
#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:179
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
Data structure in which we track acknowledgements still to be sent to the.
struct GNUNET_SCHEDULER_Task * task
Task scheduled either to transmit the cumulative ACK message, or to clean up this data structure afte...
struct GNUNET_TIME_Absolute min_transmission_time
When is task run (only used if num_acks is non-zero)?
struct TransportCummulativeAckPayload ack_uuids[64]
ACK data being accumulated.
struct GNUNET_PeerIdentity target
Target peer for which we are accumulating ACKs here.
unsigned int num_acks
Number of entries used in ack_uuids.
uint32_t ack_counter
Counter to produce the ack_counter in the struct TransportReliabilityAckMessage.
Unique identifier to map an acknowledgement to a transmission.
struct GNUNET_Uuid value
The UUID value.
One of the addresses of this peer.
struct GNUNET_TIME_Relative expiration
What is a typical lifetime the communicator expects this address to have? (Always from now....
uint32_t aid
Address identifier used by the communicator.
size_t signed_address_len
Signed address length.
enum GNUNET_NetworkType nt
Network type offered by this address.
struct AddressListEntry * prev
Kept in a DLL.
struct TransportClient * tc
Which communicator provides this address?
struct AddressListEntry * next
Kept in a DLL.
struct GNUNET_PEERSTORE_StoreHelloContext * shc
Store hello handle.
void * signed_address
Signed address.
const char * address
The actual address.
struct GNUNET_SCHEDULER_Task * st
Task to periodically do st operation.
struct GNUNET_PEERSTORE_StoreContext * sc
Current context for storing this address in the peerstore.
A Backtalker is a peer sending us backchannel messages.
struct GNUNET_TIME_Absolute timeout
When will this entry time out?
struct CommunicatorMessageContext * cmc
Communicator context waiting on this backchannel's get, or NULL.
struct GNUNET_CRYPTO_HpkeEncapsulation last_ephemeral
Last (valid) ephemeral key received from this sender.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation for this pid's monotonic_time.
struct GNUNET_SCHEDULER_Task * task
Task associated with this backtalker.
size_t body_size
Number of bytes of the original message body that follows after this struct.
struct GNUNET_TIME_Absolute monotonic_time
Last (valid) monotonic time received from this sender.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch monotonic_time information from the PEERSTORE, or NULL.
struct GNUNET_PeerIdentity pid
Peer this is about.
Closure for check_known_address.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const char * address
Set to the address we are looking for.
Closure for check_known_challenge.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const struct GNUNET_CRYPTO_ChallengeNonceP * challenge
Set to the challenge we are looking for.
Context from handle_incoming_msg().
struct CommunicatorMessageContext * next
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
uint16_t total_hops
Number of hops the message has travelled (if DV-routed).
struct GNUNET_TRANSPORT_IncomingMessage im
Additional information for flow control and about the sender.
unsigned int continue_send
Did we already call GNUNET_SERVICE_client_continue and send ACK to communicator?
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
struct CommunicatorMessageContext * prev
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
struct TransportClient * tc
Which communicator provided us with the message.
Message from the transport service to the library informing about neighbors.
Definition: transport.h:88
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition: transport.h:111
Closure for core_env_sent_cb.
uint16_t isize
By how much should we increment vl's incoming_fc_window_size_used once we are done sending to CORE?...
struct CoreSentContext * next
Kept in a DLL to clear vl in case vl is lost.
struct VirtualLink * vl
Virtual link this is about.
struct CoreSentContext * prev
Kept in a DLL to clear vl in case vl is lost.
uint16_t size
How big was the message.
Structure of the key material used to encrypt backchannel messages.
struct GNUNET_CRYPTO_AuthKey hmac_key
Key used for HMAC calculations (via GNUNET_CRYPTO_hmac()).
gcry_cipher_hd_t cipher
State of our block cipher.
struct DVKeyState::@65 material
Actual key material.
char aes_key[256/8]
Symmetric key to use for encryption.
char aes_ctr[128/8]
Counter value to use during setup.
An entry describing a peer on a path in a struct TransportDVLearnMessage message.
struct GNUNET_CRYPTO_EddsaSignature hop_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity hop
Identity of a peer on the path.
Message from the transport service to the library informing about disconnects.
Definition: transport.h:120
One possible hop towards a DV target.
struct PerformanceData pd
Performance data for this transmission possibility.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used our path.
unsigned int distance
Number of hops in total to the target (excluding next_hop and target itself).
struct DistanceVectorHop * next_neighbour
Kept in a MDLL.
struct Neighbour * next_hop
What would be the next hop to target?
struct GNUNET_TIME_Absolute timeout
At what time do we forget about this path unless we see it again while learning?
struct DistanceVector * dv
Distance vector entry this hop belongs with.
const struct GNUNET_PeerIdentity * path
Array of distance hops to the target, excluding next_hop.
struct DistanceVectorHop * next_dv
Kept in a MDLL, sorted by timeout.
struct GNUNET_TIME_Absolute path_valid_until
For how long is the validation of this path considered valid? Set to ZERO if the path is learned by s...
struct DistanceVectorHop * prev_dv
Kept in a MDLL, sorted by timeout.
struct DistanceVectorHop * prev_neighbour
Kept in a MDLL.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used our path.
Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer.
struct DistanceVectorHop * dv_head
Known paths to target.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct GNUNET_TIME_Absolute monotime
What time was sender_sig created.
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature affirming ephemeral_key of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct DistanceVectorHop * dv_tail
Known paths to target.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Our ephemeral key.
struct GNUNET_ShortHashCode * km
Master secret for the setup of the Key material for the backchannel.
struct GNUNET_PeerIdentity target
To which peer is this a route?
struct GNUNET_TIME_Absolute ephemeral_validity
How long is sender_sig valid.
struct GNUNET_SCHEDULER_Task * timeout_task
Task scheduled to purge expired paths from dv_head MDLL.
Content signed by each peer during DV learning.
struct GNUNET_PeerIdentity pred
Identity of the previous peer on the path.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
Body by which a peer confirms that it is using an ephemeral key.
struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time
How long is this signature over the ephemeral key valid?
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_PeerIdentity target
Target's peer identity.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
Application client to TRANSPORT service: we would like to have address suggestions for this peer.
Definition: transport.h:806
Closure for find_by_message_uuid.
struct ReassemblyContext * rc
Set to the reassembly context if found.
struct MessageUUIDP message_uuid
UUID to look for.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
Wrapper struct with the average RTT of message to some peer and if this peer und us is ready to sync.
enum GNUNET_GenericReturnValue sync_ready
Is this peer already ready to sync.
struct GNUNET_TIME_RelativeNBO rtt_average
The average RTT for the peer to communicate with.
Handle to a node in a heap.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
type for (message) authentication keys
Type of a nonce used for challenges.
struct GNUNET_ShortHashCode value
The value of the nonce.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Private ECC key encoded for transmission.
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
Context for building (or parsing) HELLO URIs.
Definition: hello-uri.c:205
Context for parsing HELLOs.
Definition: hello-uri.c:258
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
Header for all communications.
Handle for active NAT registrations.
Definition: nat_api.c:72
Handle to the PEERSTORE service.
Definition: peerstore_api.c:44
Context for a iterate request.
Context for a monitor.
Single PEERSTORE record.
Context for a store request.
Context for a add hello uri request.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a client that is connected to a service.
Definition: service.c:249
Handle to a service.
Definition: service.c:116
Handle for the service.
A 256-bit hashcode.
Struct wrapping information we use for starting the burst.
struct VirtualLink * vl
The VirtualLink of the peer to which we like to burst with.
struct GNUNET_TIME_Relative delay
The delay - calculate from the RTT and which peer was ready to sync first, after we will start the bu...
unsigned int sync_ready
We are ready to start the burst.
struct GNUNET_TIME_Relative rtt
The average RTT between the peers.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds and in network byte order.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Add address to the list.
Definition: transport.h:287
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
Definition: transport.h:291
struct GNUNET_TIME_RelativeNBO expiration
When does the address expire?
Definition: transport.h:301
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition: transport.h:306
uint32_t aid
Address identifier (used during deletion).
Definition: transport.h:296
Add queue to the transport.
Definition: transport.h:401
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition: transport.h:420
uint32_t mtu
Maximum transmission unit, in NBO.
Definition: transport.h:425
uint64_t q_len
Queue length, in NBO.
Definition: transport.h:431
uint32_t qid
Queue identifier (used to identify the queue).
Definition: transport.h:410
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition: transport.h:415
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
Definition: transport.h:405
uint32_t cs
An enum GNUNET_TRANSPORT_ConnectionStatus in NBO.
Definition: transport.h:441
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
uint32_t can_burst
The communicator can do burst msgs.
Definition: transport.h:277
Message from transport to communicator passing along a backchannel message from the given peer pid.
Definition: transport.h:655
struct GNUNET_PeerIdentity pid
Origin peer.
Definition: transport.h:670
Message from communicator to transport service asking for transmission of a backchannel message with ...
Definition: transport.h:626
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL.
Definition: transport.h:630
struct GNUNET_PeerIdentity pid
Target peer.
Definition: transport.h:640
Communicator tells transport how queue creation went down.
Definition: transport.h:545
uint32_t request_id
Unique ID for the request.
Definition: transport.h:555
Transport tells communicator that it wants a new queue.
Definition: transport.h:521
uint32_t request_id
Unique ID for the request.
Definition: transport.h:530
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition: transport.h:535
Remove address from the list.
Definition: transport.h:316
uint32_t aid
Address identifier.
Definition: transport.h:325
Remove queue, it is no longer available.
Definition: transport.h:499
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition: transport.h:513
uint32_t qid
Address identifier.
Definition: transport.h:508
Transport informs us about being done with an incoming message.
Definition: transport.h:374
struct GNUNET_PeerIdentity sender
Sender identifier of the original message.
Definition: transport.h:393
uint64_t fc_id
Which message is being ACKed?
Definition: transport.h:388
uint32_t reserved
Reserved (0)
Definition: transport.h:383
Inform transport about an incoming message.
Definition: transport.h:333
struct GNUNET_PeerIdentity neighbour_sender
Direct neighbour sender identifier.
Definition: transport.h:363
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:353
struct GNUNET_PeerIdentity sender
Sender identifier.
Definition: transport.h:358
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
Definition: transport.h:337
uint32_t fc_on
Do we use flow control or not?
Definition: transport.h:342
uint64_t fc_id
64-bit number to identify the matching ACK.
Definition: transport.h:347
uint32_t num_msg_pending
Messages pending (in NBO).
Definition: transport.h:766
struct GNUNET_PeerIdentity peer
Target identifier.
Definition: transport.h:744
struct GNUNET_TIME_AbsoluteNBO valid_until
Definition: transport.h:750
struct GNUNET_TIME_AbsoluteNBO last_validation
Definition: transport.h:749
uint32_t num_bytes_pending
Bytes pending (in NBO).
Definition: transport.h:771
struct GNUNET_TIME_AbsoluteNBO next_validation
Definition: transport.h:751
uint32_t nt
Network type (an enum GNUNET_NetworkType in NBO).
Definition: transport.h:739
struct GNUNET_TIME_RelativeNBO rtt
Current round-trip time estimate.
Definition: transport.h:756
uint32_t cs
Connection status (in NBO).
Definition: transport.h:761
Request to start monitoring.
Definition: transport.h:708
Inform transport that message was sent.
Definition: transport.h:592
uint64_t mid
Message ID of the original message.
Definition: transport.h:606
uint32_t qid
Queue ID for the queue which was used to send the message.
Definition: transport.h:611
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition: transport.h:616
Inform communicator about transport's desire to send a message.
Definition: transport.h:563
uint32_t qid
Which queue should we use?
Definition: transport.h:572
uint64_t mid
Message ID, used for flow control.
Definition: transport.h:577
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
Definition: transport.h:567
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition: transport.h:582
Message from transport to communicator to start a burst.
Definition: transport.h:680
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST.
Definition: transport.h:684
struct GNUNET_TIME_RelativeNBO rtt
Definition: transport.h:691
struct GNUNET_PeerIdentity pid
Target peer.
Definition: transport.h:689
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 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:837
Entry for the ring buffer caching messages send to core, when virtual link is available.
struct CommunicatorMessageContext * cmc
Communicator context for this ring buffer entry.
struct GNUNET_MessageHeader * mh
The message in this entry.
Message used to notify the transport API that it can send another message to the transport service.
Definition: transport.h:161
struct GNUNET_PeerIdentity peer
Which peer can send more now?
Definition: transport.h:195
Message from the transport service to the library asking to check if both processes agree about this ...
Definition: transport.h:62
Information we keep per GOODPUT_AGING_SLOTS about historic (or current) transmission performance.
uint64_t bytes_received
Number of bytes received and acknowledged by the other peer in the interval.
uint64_t bytes_sent
Number of bytes actually sent in the interval.
Outer layer of an encapsulated backchannel message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
Client connected to the transport service.
enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc
Characteristics of this communicator.
struct PendingMessage * pending_msg_head
Head of list of messages pending for this client, sorted by transmission time ("next_attempt" + possi...
enum ClientType type
What type of client is this?
struct AddressListEntry * addr_tail
Tail of list of the addresses of this peer offered by this communicator.
struct TransportClient * next
Kept in a DLL.
struct GNUNET_MQ_Handle * mq
Message queue to the client.
struct GNUNET_SCHEDULER_Task * free_queue_entry_task
Task to check for timed out QueueEntry.
struct PendingMessage * pending_msg_tail
Tail of list of messages pending for this client.
struct TransportClient::@60::@62 monitor
Information for type CT_MONITOR.
struct Queue * queue_head
Head of DLL of queues offered by this communicator.
struct TransportClient::@60::@61 core
Information for type CT_CORE.
struct AddressListEntry * addr_head
Head of list of the addresses of this peer offered by this communicator.
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of requests for peers the given client application would like to see connections for.
struct TransportClient::@60::@64 application
Information for type CT_APPLICATION.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct TransportClient * prev
Kept in a DLL.
char * address_prefix
If type is CT_COMMUNICATOR, this communicator supports communicating using these addresses.
struct Queue * queue_tail
Tail of DLL of queues offered by this communicator.
union TransportClient::@60 details
struct TransportClient::@60::@63 communicator
Information for type CT_COMMUNICATOR.
unsigned int total_queue_length
Number of queue entries in all queues to this communicator.
int one_shot
Is this a one-shot monitor?
struct GNUNET_PeerIdentity peer
Peer identity to monitor the addresses of.
enum GNUNET_GenericReturnValue can_burst
Can be used for burst messages.
struct GNUNET_TIME_RelativeNBO ack_delay
How long was the ACK delayed for generating cumulative ACKs? Used to calculate the correct network RT...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
struct GNUNET_TIME_Absolute receive_time
When did we receive the message we are ACKing? Used to calculate the delay we introduced by cummulati...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
Outer layer of an encapsulated message send over multiple hops.
struct GNUNET_HashCode hmac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX.
uint16_t num_hops
Number of hops this messages includes.
uint16_t orig_size
Size this msg had initially.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
unsigned int without_fc
Flag if the payload is a control message.
struct GNUNET_ShortHashCode iv
We use an IV here as the ephemeral_key is re-used for EPHEMERAL_VALIDITY time to avoid re-signing it ...
uint16_t total_hops
Number of total hops this messages travelled.
Plaintext of the variable-size payload that is encrypted within a struct TransportBackchannelEncapsul...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature of the sender over an GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Current monotonic time of the sending transport service.
struct GNUNET_PeerIdentity sender
Sender's peer identity.
Internal message used by transport for distance vector learning.
struct GNUNET_PeerIdentity initiator
Identity of the peer that started this learning activity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN.
struct GNUNET_TIME_RelativeNBO non_network_delay
Peers receiving this message and delaying forwarding to other peers for any reason should increment t...
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EddsaSignature init_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
uint16_t num_hops
Number of hops this messages has travelled, in NBO.
uint16_t bidirectional
Bitmask of the last 16 hops indicating whether they are confirmed available (without DV) in both dire...
Message for Transport-to-Transport Flow control.
uint64_t outbound_window_size
Latest flow control window size we learned from the other peer, in bytes, in NBO.
unsigned int number_of_addresses
Number of TransportGlobalNattedAddress following the struct.
size_t size_of_addresses
Size of all the addresses attached to all TransportGlobalNattedAddress.
uint64_t inbound_window_size
Flow control window size in bytes, in NBO.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender.
uint32_t seq
Sequence number of the flow control message.
uint64_t outbound_sent
How many bytes has the sender sent that count for flow control at this time.
struct GNUNET_TIME_RelativeNBO rtt
Average RTT for the DistanceVector of the VirtualLink we tell the target.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL.
unsigned int sync_ready
We tell the target, if we are ready to start the burst.
Outer layer of an encapsulated fragmented application message.
uint16_t frag_off
Offset of this fragment in the overall message.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct AcknowledgementUUIDP ack_uuid
Unique ID of this fragment (and fragment transmission!).
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT.
uint16_t msg_size
Total size of the message that is being fragmented.
char * addr
The address to search for.
struct TransportGlobalNattedAddress * tgna
The struct TransportGlobalNattedAddress to set.
unsigned int address_length
Length of the address following the struct in NBO.
Confirmation that the receiver got a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
uint32_t ack_counter
Counter of ACKs transmitted by the sender to us.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK.
Outer layer of an encapsulated unfragmented application message sent over an unreliable channel.
uint32_t ack_countdown
Number of messages still to be sent before a commulative ACK is requested.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
struct AcknowledgementUUIDP ack_uuid
Unique ID of the message used for signalling receipt of messages sent over possibly unreliable channe...
Message send to another peer to validate that it can indeed receive messages at a particular address.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge to be signed by the receiving peer.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender, to be copied into the reply to allow sender to calculate RTT.
Message signed by a peer to confirm that it can indeed receive messages at a particular address.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
struct GNUNET_TIME_RelativeNBO validity_duration
How long does the sender believe the address on which the challenge was received to remain valid?
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge signed by the receiving peer.
Message send to a peer to respond to a #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
The challenge that was signed by the receiving peer.
struct GNUNET_CRYPTO_EddsaSignature signature
The peer's signature matching the GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
State we keep for validation activities.
struct GNUNET_TIME_Absolute valid_until
How long did the peer claim this address to be valid? Capped at minimum of MAX_ADDRESS_VALID_UNTIL re...
struct GNUNET_PeerIdentity pid
For which peer is address to be validated (or possibly valid)? Serves as key in the validation_map.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
common internal definitions for transport service