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
3576 while (NULL != (dvh = dv->dv_head))
3578 if (NULL == dv->dv_head)
3579 {
3580 struct VirtualLink *vl;
3581
3583 GNUNET_YES ==
3585 if (NULL != (vl = dv->vl))
3586 {
3587 GNUNET_assert (dv == vl->dv);
3588 vl->dv = NULL;
3589 if (NULL == vl->n)
3590 {
3592 free_virtual_link (vl);
3593 }
3594 else
3595 {
3598 }
3599 dv->vl = NULL;
3600 }
3601
3602 if (NULL != dv->timeout_task)
3603 {
3605 dv->timeout_task = NULL;
3606 }
3607 GNUNET_free (dv->km);
3608 GNUNET_free (dv);
3609 }
3610}
3611
3612
3626static void
3628 const struct GNUNET_PeerIdentity *peer,
3629 const char *address,
3631 const struct MonitorEvent *me)
3632{
3633 struct GNUNET_MQ_Envelope *env;
3635 size_t addr_len = strlen (address) + 1;
3636
3638 addr_len,
3640 md->nt = htonl ((uint32_t) nt);
3641 md->peer = *peer;
3642 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3643 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3644 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3645 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3646 md->cs = htonl ((uint32_t) me->cs);
3647 md->num_msg_pending = htonl (me->num_msg_pending);
3648 md->num_bytes_pending = htonl (me->num_bytes_pending);
3649 memcpy (&md[1], address, addr_len);
3650 GNUNET_MQ_send (tc->mq, env);
3651}
3652
3653
3663static void
3665 const char *address,
3667 const struct MonitorEvent *me)
3668{
3669 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3670 {
3671 if (CT_MONITOR != tc->type)
3672 continue;
3673 if (tc->details.monitor.one_shot)
3674 continue;
3675 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3676 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3677 continue;
3679 }
3680}
3681
3682
3692static void *
3694 struct GNUNET_SERVICE_Client *client,
3695 struct GNUNET_MQ_Handle *mq)
3696{
3697 struct TransportClient *tc;
3698
3699 (void) cls;
3700 tc = GNUNET_new (struct TransportClient);
3701 tc->client = client;
3702 tc->mq = mq;
3705 "Client %p of type %u connected\n",
3706 tc,
3707 tc->type);
3708 return tc;
3709}
3710
3711
3712static enum GNUNET_GenericReturnValue
3714 const struct GNUNET_PeerIdentity *pid,
3715 void *value)
3716{
3717 struct TransportGlobalNattedAddress *tgna = value;
3718 (void) cls;
3719
3720 GNUNET_free (tgna);
3721
3722 return GNUNET_OK;
3723}
3724
3725
3732static void
3733free_neighbour (struct Neighbour *neighbour,
3734 enum GNUNET_GenericReturnValue drop_link)
3735{
3736 struct DistanceVectorHop *dvh;
3737 struct VirtualLink *vl;
3738
3739 GNUNET_assert (NULL == neighbour->queue_head);
3742 &neighbour->pid,
3743 neighbour));
3745 "Freeing neighbour\n");
3748 NULL);
3750 while (NULL != (dvh = neighbour->dv_head))
3751 {
3752 struct DistanceVector *dv = dvh->dv;
3753
3755 if (NULL == dv->dv_head)
3756 free_dv_route (dv);
3757 }
3758 if (NULL != neighbour->get)
3759 {
3761 neighbour->get = NULL;
3762 }
3763 if (NULL != neighbour->sc)
3764 {
3766 "store cancel\n");
3767 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3768 neighbour->sc = NULL;
3769 }
3770 if (NULL != (vl = neighbour->vl))
3771 {
3772 GNUNET_assert (neighbour == vl->n);
3773 vl->n = NULL;
3774 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3775 {
3778 }
3779 else
3780 {
3783 }
3784 neighbour->vl = NULL;
3785 }
3786 GNUNET_free (neighbour);
3787}
3788
3789
3796static void
3798 const struct GNUNET_PeerIdentity *pid)
3799{
3800 struct GNUNET_MQ_Envelope *env;
3801 struct ConnectInfoMessage *cim;
3802
3803 GNUNET_assert (CT_CORE == tc->type);
3805 cim->id = *pid;
3806 GNUNET_MQ_send (tc->mq, env);
3807}
3808
3809
3815static void
3817{
3819 "Informing CORE clients about connection to %s\n",
3820 GNUNET_i2s (pid));
3821 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3822 {
3823 if (CT_CORE != tc->type)
3824 continue;
3826 }
3827}
3828
3829
3837static void
3838transmit_on_queue (void *cls);
3839
3840
3844static unsigned int
3846{
3847 for (struct Queue *s = queue_head; NULL != s;
3848 s = s->next_client)
3849 {
3850 if (s->tc->details.communicator.address_prefix !=
3851 queue->tc->details.communicator.address_prefix)
3852 {
3854 "queue address %s qid %u compare with queue: address %s qid %u\n",
3855 queue->address,
3856 queue->qid,
3857 s->address,
3858 s->qid);
3859 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3860 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3861 return GNUNET_YES;
3863 "Lower prio\n");
3864 }
3865 }
3866 return GNUNET_NO;
3867}
3868
3869
3877static void
3879 struct Queue *queue,
3881{
3883
3884 if (queue->validated_until.abs_value_us < now.abs_value_us)
3885 return;
3887 queue->tc->details.communicator.
3888 queue_head))
3889 return;
3890
3891 if (queue->tc->details.communicator.total_queue_length >=
3893 {
3895 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3896 queue->address,
3897 queue->qid);
3899 GST_stats,
3900 "# Transmission throttled due to communicator queue limit",
3901 1,
3902 GNUNET_NO);
3903 queue->idle = GNUNET_NO;
3904 return;
3905 }
3906 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3907 {
3909 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3910 queue->address,
3911 queue->qid);
3913 "# Transmission throttled due to queue queue limit",
3914 1,
3915 GNUNET_NO);
3916 queue->idle = GNUNET_NO;
3917 return;
3918 }
3919 if (0 == queue->q_capacity)
3920 {
3922 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3923 PRIu64 ".\n",
3924 queue->address,
3925 queue->qid,
3926 queue->q_capacity);
3928 "# Transmission throttled due to message queue capacity",
3929 1,
3930 GNUNET_NO);
3931 queue->idle = GNUNET_NO;
3932 return;
3933 }
3934 /* queue might indeed be ready, schedule it */
3935 if (NULL != queue->transmit_task)
3936 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3937 queue->transmit_task =
3939 queue);
3941 "Considering transmission on queue `%s' QID %llu to %s\n",
3942 queue->address,
3943 (unsigned long long) queue->qid,
3944 GNUNET_i2s (&queue->neighbour->pid));
3945}
3946
3947
3954static void
3956{
3957 struct VirtualLink *vl = cls;
3958 struct DistanceVector *dv = vl->dv;
3959 struct Neighbour *n = vl->n;
3960 struct GNUNET_TIME_Absolute dvh_timeout;
3961 struct GNUNET_TIME_Absolute q_timeout;
3962
3964 "Checking if link is down\n");
3965 vl->visibility_task = NULL;
3966 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3967 if (NULL != dv)
3968 {
3969 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3970 pos = pos->next_dv)
3971 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
3972 pos->path_valid_until);
3973 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3974 {
3975 vl->dv->vl = NULL;
3976 vl->dv = NULL;
3977 }
3978 }
3979 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3980 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3981 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3982 if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3983 {
3984 vl->n->vl = NULL;
3985 vl->n = NULL;
3986 }
3987 if ((NULL == vl->n) && (NULL == vl->dv))
3988 {
3990 free_virtual_link (vl);
3991 return;
3992 }
3993 vl->visibility_task =
3994 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3996 vl);
3997}
3998
3999
4005static void
4007{
4008 struct Neighbour *neighbour = queue->neighbour;
4009 struct TransportClient *tc = queue->tc;
4010 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4012 struct QueueEntry *qe;
4013 int maxxed;
4014 struct PendingAcknowledgement *pa;
4015 struct VirtualLink *vl;
4016
4018 "Cleaning up queue %u\n", queue->qid);
4019 if (NULL != queue->mo)
4020 {
4022 queue->mo = NULL;
4023 }
4024 if (NULL != queue->transmit_task)
4025 {
4026 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4027 queue->transmit_task = NULL;
4028 }
4029 while (NULL != (pa = queue->pa_head))
4030 {
4031 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4032 pa->queue = NULL;
4033 }
4034
4036 neighbour->queue_head,
4037 neighbour->queue_tail,
4038 queue);
4040 tc->details.communicator.queue_head,
4041 tc->details.communicator.queue_tail,
4042 queue);
4044 tc->details.communicator.total_queue_length);
4046 "Cleaning up queue with length %u\n",
4047 queue->queue_length);
4048 while (NULL != (qe = queue->queue_head))
4049 {
4050 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4051 queue->queue_length--;
4052 tc->details.communicator.total_queue_length--;
4053 if (NULL != qe->pm)
4054 {
4055 GNUNET_assert (qe == qe->pm->qe);
4056 qe->pm->qe = NULL;
4057 }
4058 GNUNET_free (qe);
4059 }
4060 GNUNET_assert (0 == queue->queue_length);
4061 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4062 tc->details.communicator.total_queue_length))
4063 {
4064 /* Communicator dropped below threshold, resume all _other_ queues */
4066 GST_stats,
4067 "# Transmission throttled due to communicator queue limit",
4068 -1,
4069 GNUNET_NO);
4070 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4071 s = s->next_client)
4073 s,
4075 }
4076 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4078
4079 vl = lookup_virtual_link (&neighbour->pid);
4080 if ((NULL != vl) && (neighbour == vl->n))
4081 {
4083 check_link_down (vl);
4084 }
4085 if (NULL == neighbour->queue_head)
4086 {
4087 free_neighbour (neighbour, GNUNET_NO);
4088 }
4089}
4090
4091
4097static void
4099{
4100 struct TransportClient *tc = ale->tc;
4101
4102 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4103 tc->details.communicator.addr_tail,
4104 ale);
4105 if (NULL != ale->sc)
4106 {
4108 "store cancel\n");
4110 ale->sc = NULL;
4111 }
4112 if (NULL != ale->st)
4113 {
4115 ale->st = NULL;
4116 }
4117 if (NULL != ale->signed_address)
4119 GNUNET_free (ale);
4120}
4121
4122
4131static int
4133 const struct GNUNET_PeerIdentity *pid,
4134 void *value)
4135{
4136 struct TransportClient *tc = cls;
4137 struct PeerRequest *pr = value;
4138
4139 if (NULL != pr->nc)
4141 pr->nc = NULL;
4143 GNUNET_YES ==
4144 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4145 pid,
4146 pr));
4147 GNUNET_free (pr);
4148
4149 return GNUNET_OK;
4150}
4151
4152
4153static void
4154do_shutdown (void *cls);
4155
4164static void
4166 struct GNUNET_SERVICE_Client *client,
4167 void *app_ctx)
4168{
4169 struct TransportClient *tc = app_ctx;
4170
4171 (void) cls;
4172 (void) client;
4174 switch (tc->type)
4175 {
4176 case CT_NONE:
4178 "Unknown Client %p disconnected, cleaning up.\n",
4179 tc);
4180 break;
4181
4182 case CT_CORE: {
4183 struct PendingMessage *pm;
4185 "CORE Client %p disconnected, cleaning up.\n",
4186 tc);
4187
4188
4189 while (NULL != (pm = tc->details.core.pending_msg_head))
4190 {
4192 tc->details.core.pending_msg_head,
4193 tc->details.core.pending_msg_tail,
4194 pm);
4195 pm->client = NULL;
4196 }
4197 }
4198 break;
4199
4200 case CT_MONITOR:
4202 "MONITOR Client %p disconnected, cleaning up.\n",
4203 tc);
4204
4205 break;
4206
4207 case CT_COMMUNICATOR: {
4208 struct Queue *q;
4209 struct AddressListEntry *ale;
4210
4212 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4213 tc);
4214
4215 if (NULL != tc->details.communicator.free_queue_entry_task)
4217 tc->details.communicator.free_queue_entry_task);
4218 while (NULL != (q = tc->details.communicator.queue_head))
4219 free_queue (q);
4220 while (NULL != (ale = tc->details.communicator.addr_head))
4222 GNUNET_free (tc->details.communicator.address_prefix);
4223 }
4224 break;
4225
4226 case CT_APPLICATION:
4228 "APPLICATION Client %p disconnected, cleaning up.\n",
4229 tc);
4230
4231 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4233 tc);
4234 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4235 break;
4236 }
4237 GNUNET_free (tc);
4238 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4239 {
4241 "Our last client disconnected\n");
4242 do_shutdown (cls);
4243 }
4244}
4245
4246
4256static int
4258 const struct GNUNET_PeerIdentity *pid,
4259 void *value)
4260{
4261 struct TransportClient *tc = cls;
4262 struct VirtualLink *vl = value;
4263
4264 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4265 return GNUNET_OK;
4266
4268 "Telling new CORE client about existing connection to %s\n",
4269 GNUNET_i2s (pid));
4271 return GNUNET_OK;
4272}
4273
4274
4280static void
4282 unsigned
4283 int free_cmc);
4284
4285static enum GNUNET_GenericReturnValue
4287 const struct GNUNET_PeerIdentity *pid,
4288 void *value)
4289{
4290 struct VirtualLink *vl = value;
4291 struct CommunicatorMessageContext *cmc;
4292
4293 /* resume communicators */
4294 while (NULL != (cmc = vl->cmc_tail))
4295 {
4297 if (GNUNET_NO == cmc->continue_send)
4299 }
4300 return GNUNET_OK;
4301}
4302
4303
4312static void
4313handle_client_start (void *cls, const struct StartMessage *start)
4314{
4315 struct TransportClient *tc = cls;
4316 uint32_t options;
4317
4318 options = ntohl (start->options);
4319 if ((0 != (1 & options)) &&
4320 (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4321 {
4322 /* client thinks this is a different peer, reject */
4323 GNUNET_break (0);
4325 return;
4326 }
4327 if (CT_NONE != tc->type)
4328 {
4329 GNUNET_break (0);
4331 return;
4332 }
4333 tc->type = CT_CORE;
4335 "New CORE client with PID %s registered\n",
4336 GNUNET_i2s (&start->self));
4339 tc);
4342 NULL);
4344}
4345
4346
4353static int
4354check_client_send (void *cls, const struct OutboundMessage *obm)
4355{
4356 struct TransportClient *tc = cls;
4357 uint16_t size;
4358 const struct GNUNET_MessageHeader *obmm;
4359
4360 if (CT_CORE != tc->type)
4361 {
4362 GNUNET_break (0);
4363 return GNUNET_SYSERR;
4364 }
4365 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4366 if (size < sizeof(struct GNUNET_MessageHeader))
4367 {
4368 GNUNET_break (0);
4369 return GNUNET_SYSERR;
4370 }
4371 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4372 if (size != ntohs (obmm->size))
4373 {
4374 GNUNET_break (0);
4375 return GNUNET_SYSERR;
4376 }
4377 return GNUNET_OK;
4378}
4379
4380
4388static void
4390{
4391 struct TransportClient *tc = pm->client;
4392 struct VirtualLink *vl = pm->vl;
4393
4395 "client send response\n");
4396 if (NULL != tc)
4397 {
4398 struct GNUNET_MQ_Envelope *env;
4399 struct SendOkMessage *so_msg;
4400
4402 so_msg->peer = vl->target;
4404 "Confirming transmission of <%" PRIu64 "> to %s\n",
4405 pm->logging_uuid,
4406 GNUNET_i2s (&vl->target));
4407 GNUNET_MQ_send (tc->mq, env);
4408 }
4410}
4411
4412
4422static unsigned int
4425 struct DistanceVectorHop **hops_array,
4426 unsigned int hops_array_length)
4427{
4428 uint64_t choices[hops_array_length];
4429 uint64_t num_dv;
4430 unsigned int dv_count;
4431
4432 /* Pick random vectors, but weighted by distance, giving more weight
4433 to shorter vectors */
4434 num_dv = 0;
4435 dv_count = 0;
4436 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4437 pos = pos->next_dv)
4438 {
4439 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4440 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4441 .rel_value_us == 0))
4442 continue; /* pos unconfirmed and confirmed required */
4443 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4444 dv_count++;
4445 }
4446 if (0 == dv_count)
4447 return 0;
4448 if (dv_count <= hops_array_length)
4449 {
4450 dv_count = 0;
4451 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4452 pos = pos->next_dv)
4453 hops_array[dv_count++] = pos;
4454 return dv_count;
4455 }
4456 for (unsigned int i = 0; i < hops_array_length; i++)
4457 {
4458 int ok = GNUNET_NO;
4459 while (GNUNET_NO == ok)
4460 {
4461 choices[i] =
4463 ok = GNUNET_YES;
4464 for (unsigned int j = 0; j < i; j++)
4465 if (choices[i] == choices[j])
4466 {
4467 ok = GNUNET_NO;
4468 break;
4469 }
4470 }
4471 }
4472 dv_count = 0;
4473 num_dv = 0;
4474 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4475 pos = pos->next_dv)
4476 {
4477 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4478
4479 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4480 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4481 .rel_value_us == 0))
4482 continue; /* pos unconfirmed and confirmed required */
4483 for (unsigned int i = 0; i < hops_array_length; i++)
4484 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4485 hops_array[dv_count++] = pos;
4486 num_dv += delta;
4487 }
4488 return dv_count;
4489}
4490
4491
4498static int
4500 void *cls,
4502{
4503 struct TransportClient *tc = cls;
4504 uint16_t size;
4505
4506 if (CT_NONE != tc->type)
4507 {
4508 GNUNET_break (0);
4509 return GNUNET_SYSERR;
4510 }
4511 tc->type = CT_COMMUNICATOR;
4512 size = ntohs (cam->header.size) - sizeof(*cam);
4513 if (0 == size)
4514 return GNUNET_OK; /* receive-only communicator */
4516 return GNUNET_OK;
4517}
4518
4519
4525static void
4527 unsigned
4528 int free_cmc)
4529{
4530 if (0 != ntohl (cmc->im.fc_on))
4531 {
4532 /* send ACK when done to communicator for flow control! */
4533 struct GNUNET_MQ_Envelope *env;
4535
4537 "Acknowledge message with flow control id %" PRIu64 "\n",
4538 cmc->im.fc_id);
4540 ack->reserved = htonl (0);
4541 ack->fc_id = cmc->im.fc_id;
4542 ack->sender = cmc->im.neighbour_sender;
4543 GNUNET_MQ_send (cmc->tc->mq, env);
4544 }
4545
4547
4548 if (GNUNET_YES == free_cmc)
4549 {
4550 GNUNET_free (cmc);
4551 }
4552}
4553
4554
4555static void
4557{
4559}
4560
4561
4571static void
4572handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4573{
4574 struct TransportClient *tc = cls;
4575 struct VirtualLink *vl;
4576 uint32_t delta;
4577 struct CommunicatorMessageContext *cmc;
4578
4579 if (CT_CORE != tc->type)
4580 {
4581 GNUNET_break (0);
4583 return;
4584 }
4585 vl = lookup_virtual_link (&rom->peer);
4586 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4587 {
4589 "# RECV_OK dropped: virtual link unknown",
4590 1,
4591 GNUNET_NO);
4593 return;
4594 }
4595 delta = ntohl (rom->increase_window_delta);
4596 vl->core_recv_window += delta;
4598 "CORE ack receiving message, increased CORE recv window to %d\n",
4599 vl->core_recv_window);
4601 if (vl->core_recv_window <= 0)
4602 return;
4603 /* resume communicators */
4604 while (NULL != (cmc = vl->cmc_tail))
4605 {
4607 if (GNUNET_NO == cmc->continue_send)
4609 }
4610}
4611
4612
4619static void
4621 void *cls,
4623{
4624 struct TransportClient *tc = cls;
4625 uint16_t size;
4626
4627 size = ntohs (cam->header.size) - sizeof(*cam);
4628 if (0 == size)
4629 {
4631 "Receive-only communicator connected\n");
4632 return; /* receive-only communicator */
4633 }
4634 tc->details.communicator.address_prefix =
4635 GNUNET_strdup ((const char *) &cam[1]);
4636 tc->details.communicator.cc = ntohl (cam->cc);
4637 tc->details.communicator.can_burst = ntohl (cam->can_burst);
4639 "Communicator for peer %s with prefix '%s' connected %s\n",
4641 tc->details.communicator.address_prefix,
4642 tc->details.communicator.can_burst ? "can burst" :
4643 "can not burst");
4645}
4646
4647
4655static int
4657 void *cls,
4659{
4660 const struct GNUNET_MessageHeader *inbox;
4661 const char *is;
4662 uint16_t msize;
4663 uint16_t isize;
4664
4665 (void) cls;
4666 msize = ntohs (cb->header.size) - sizeof(*cb);
4667 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4668 isize = ntohs (inbox->size);
4669 if (isize >= msize)
4670 {
4671 GNUNET_break (0);
4672 return GNUNET_SYSERR;
4673 }
4674 is = (const char *) inbox;
4675 is += isize;
4676 msize -= isize;
4677 GNUNET_assert (0 < msize);
4678 if ('\0' != is[msize - 1])
4679 {
4680 GNUNET_break (0);
4681 return GNUNET_SYSERR;
4682 }
4683 return GNUNET_OK;
4684}
4685
4686
4692static void
4694{
4695 struct EphemeralConfirmationPS ec;
4696
4698 dv->ephemeral_validity =
4701 ec.target = dv->target;
4704 ec.purpose.size = htonl (sizeof(ec));
4706 &ec,
4707 &dv->sender_sig);
4708}
4709
4710
4711static void
4713 struct TransportClient *tc);
4714
4715
4716static void
4718{
4719 struct TransportClient *tc = cls;
4721
4723 "freeing timedout queue entries\n");
4724
4725 tc->details.communicator.free_queue_entry_task = NULL;
4726 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4727 queue = queue->next_client)
4728 {
4729 struct QueueEntry *qep = queue->queue_head;
4730
4732 "checking QID %u for timedout queue entries\n",
4733 queue->qid);
4734 while (NULL != qep)
4735 {
4736 struct QueueEntry *pos = qep;
4738 pos->creation_timestamp, now);
4739 qep = qep->next;
4740
4742 "diff to now %s \n",
4745 {
4747 "Freeing timed out QueueEntry with MID %" PRIu64
4748 " and QID %u\n",
4749 pos->mid,
4750 queue->qid);
4751 free_queue_entry (pos, tc);
4752 }
4753 }
4754 }
4755}
4756
4757
4767static void
4769 struct PendingMessage *pm,
4770 const void *payload,
4771 size_t payload_size)
4772{
4773 struct Neighbour *n = queue->neighbour;
4775 struct GNUNET_MQ_Envelope *env;
4776 struct PendingAcknowledgement *pa;
4777
4778 GNUNET_log (
4780 "Queueing %u bytes of payload for transmission <%" PRIu64
4781 "> on queue %llu to %s\n",
4782 (unsigned int) payload_size,
4783 (NULL == pm) ? 0 : pm->logging_uuid,
4784 (unsigned long long) queue->qid,
4785 GNUNET_i2s (&queue->neighbour->pid));
4786 env = GNUNET_MQ_msg_extra (smt,
4787 payload_size,
4789 smt->qid = htonl (queue->qid);
4790 smt->mid = GNUNET_htonll (queue->mid_gen);
4791 smt->receiver = n->pid;
4792 memcpy (&smt[1], payload, payload_size);
4793 {
4794 /* Pass the env to the communicator of queue for transmission. */
4795 struct QueueEntry *qe;
4796
4797 qe = GNUNET_new (struct QueueEntry);
4798 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4799 qe->mid = queue->mid_gen;
4801 "Create QueueEntry with MID %" PRIu64
4802 " and QID %u and prefix %s\n",
4803 qe->mid,
4804 queue->qid,
4805 queue->tc->details.communicator.address_prefix);
4806 queue->mid_gen++;
4807 qe->queue = queue;
4808 if (NULL != pm)
4809 {
4810 qe->pm = pm;
4811 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4812 // GNUNET_assert (NULL == pm->qe);
4813 if (NULL != pm->qe)
4814 {
4816 "Retransmitting message <%" PRIu64
4817 "> remove pm from qe with MID: %llu \n",
4818 pm->logging_uuid,
4819 (unsigned long long) pm->qe->mid);
4820 pm->qe->pm = NULL;
4821 }
4822 pm->qe = qe;
4823 }
4824 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4825 if (0 == queue->q_capacity)
4826 {
4827 // Messages without FC or fragments can get here.
4828 if (NULL != pm)
4829 {
4831 "Message %" PRIu64
4832 " (pm type %u) was not send because queue has no capacity.\n",
4833 pm->logging_uuid,
4834 pm->pmt);
4835 pm->qe = NULL;
4836 }
4837 GNUNET_free (env);
4838 GNUNET_free (qe);
4839 return;
4840 }
4841 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4842 queue->queue_length++;
4843 queue->tc->details.communicator.total_queue_length++;
4844 if (GNUNET_NO == queue->unlimited_length)
4845 queue->q_capacity--;
4847 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4848 queue->address,
4849 queue->qid,
4850 queue->q_capacity);
4852 queue->tc->details.communicator.total_queue_length)
4853 queue->idle = GNUNET_NO;
4854 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4855 queue->idle = GNUNET_NO;
4856 if (0 == queue->q_capacity)
4857 queue->idle = GNUNET_NO;
4858
4859 if (GNUNET_NO == queue->idle)
4860 {
4861 struct TransportClient *tc = queue->tc;
4862
4863 if (NULL == tc->details.communicator.free_queue_entry_task)
4864 tc->details.communicator.free_queue_entry_task =
4866 &
4868 tc);
4869 }
4870 if (NULL != pm && NULL != (pa = pm->pa_head))
4871 {
4872 while (pm != pa->pm)
4873 pa = pa->next_pa;
4874 pa->num_send++;
4875 }
4876 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4878 "Sending message MID %" PRIu64
4879 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4880 PRIu64 "\n",
4881 GNUNET_ntohll (smt->mid),
4882 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4883 ntohs (smt->header.size),
4884 (unsigned long) payload_size,
4885 queue->tc->mq,
4886 queue->address,
4887 queue->qid,
4888 (NULL == pm) ? 0 : pm->logging_uuid);
4889 GNUNET_MQ_send (queue->tc->mq, env);
4890 }
4891}
4892
4893
4904static struct GNUNET_TIME_Relative
4906 const struct GNUNET_MessageHeader *hdr,
4908{
4909 struct GNUNET_TIME_Absolute now;
4910 unsigned int candidates;
4911 unsigned int sel1;
4912 unsigned int sel2;
4913 struct GNUNET_TIME_Relative rtt;
4914
4915 /* Pick one or two 'random' queues from n (under constraints of options) */
4916 now = GNUNET_TIME_absolute_get ();
4917 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4918 weight in the future; weight could be assigned by observed
4919 bandwidth (note: not sure if we should do this for this type
4920 of control traffic though). */
4921 candidates = 0;
4922 for (struct Queue *pos = n->queue_head; NULL != pos;
4923 pos = pos->next_neighbour)
4924 {
4925 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4926 (pos->validated_until.abs_value_us > now.abs_value_us))
4927 candidates++;
4928 }
4929 if (0 == candidates)
4930 {
4931 /* This can happen rarely if the last confirmed queue timed
4932 out just as we were beginning to process this message. */
4934 "Could not route message of type %u to %s: no valid queue\n",
4935 ntohs (hdr->type),
4936 GNUNET_i2s (&n->pid));
4938 "# route selection failed (all no valid queue)",
4939 1,
4940 GNUNET_NO);
4942 }
4943
4946 if (0 == (options & RMO_REDUNDANT))
4947 sel2 = candidates; /* picks none! */
4948 else
4950 candidates = 0;
4951 for (struct Queue *pos = n->queue_head; NULL != pos;
4952 pos = pos->next_neighbour)
4953 {
4954 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4955 (pos->validated_until.abs_value_us > now.abs_value_us))
4956 {
4957 if ((sel1 == candidates) || (sel2 == candidates))
4958 {
4960 "Routing message of type %u to %s using %s (#%u)\n",
4961 ntohs (hdr->type),
4962 GNUNET_i2s (&n->pid),
4963 pos->address,
4964 (sel1 == candidates) ? 1 : 2);
4965 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4966 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4967 }
4968 candidates++;
4969 }
4970 }
4971 return rtt;
4972}
4973
4974
4979{
4983 gcry_cipher_hd_t cipher;
4984
4988 struct
4989 {
4994
4998 char aes_key[256 / 8];
4999
5003 char aes_ctr[128 / 8];
5005};
5006
5007
5016static void
5018 const struct GNUNET_ShortHashCode *iv,
5019 struct DVKeyState *key)
5020{
5021 /* must match what we defive from decapsulated key */
5023 GNUNET_CRYPTO_hkdf_expand (&key->material,
5024 sizeof(key->material),
5025 km,
5026 "gnunet-transport-dv-key",
5027 strlen ("gnunet-transport-dv-key")
5028 ,
5029 km,
5030 sizeof(*km),
5031 iv,
5032 sizeof(*iv),
5033 NULL));
5035 "Deriving backchannel key based on KM %s and IV %s\n",
5036 GNUNET_sh2s (km),
5037 GNUNET_sh2s (iv));
5038 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5039 GCRY_CIPHER_AES256 /* low level: go for speed */
5040 ,
5041 GCRY_CIPHER_MODE_CTR,
5042 0 /* flags */));
5043 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5044 &key->material.aes_key,
5045 sizeof(key->material.aes_key)));
5046 gcry_cipher_setctr (key->cipher,
5047 &key->material.aes_ctr,
5048 sizeof(key->material.aes_ctr));
5049}
5050
5051
5061static void
5062dv_hmac (const struct DVKeyState *key,
5063 struct GNUNET_HashCode *hmac,
5064 const void *data,
5065 size_t data_size)
5066{
5067 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5068}
5069
5070
5080static void
5081dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5082{
5083 GNUNET_assert (0 ==
5084 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5085}
5086
5087
5098static enum GNUNET_GenericReturnValue
5100 void *out,
5101 const void *ciph,
5102 size_t out_size)
5103{
5104 return (0 ==
5105 gcry_cipher_decrypt (key->cipher,
5106 out, out_size,
5107 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5108}
5109
5110
5116static void
5118{
5119 gcry_cipher_close (key->cipher);
5120 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5121}
5122
5123
5134typedef void (*DVMessageHandler) (void *cls,
5135 struct Neighbour *next_hop,
5136 const struct GNUNET_MessageHeader *hdr,
5138
5153static struct GNUNET_TIME_Relative
5155 unsigned int num_dvhs,
5156 struct DistanceVectorHop **dvhs,
5157 const struct GNUNET_MessageHeader *hdr,
5158 DVMessageHandler use,
5159 void *use_cls,
5161 enum GNUNET_GenericReturnValue without_fc)
5162{
5163 struct TransportDVBoxMessage box_hdr;
5164 struct TransportDVBoxPayloadP payload_hdr;
5165 uint16_t enc_body_size = ntohs (hdr->size);
5166 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5167 struct DVKeyState *key;
5168 struct GNUNET_TIME_Relative rtt;
5169 struct GNUNET_ShortHashCode km;
5170
5171 key = GNUNET_new (struct DVKeyState);
5172 /* Encrypt payload */
5174 box_hdr.total_hops = htons (0);
5175 box_hdr.without_fc = htons (without_fc);
5176 // update_ephemeral (dv);
5177 if (0 ==
5178 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5179 {
5180 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5181 &dv->ephemeral_key,
5182 &km);
5183 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5184 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5185 sign_ephemeral (dv);
5186 }
5187 box_hdr.ephemeral_key = dv->ephemeral_key;
5188 payload_hdr.sender_sig = dv->sender_sig;
5189
5191 &box_hdr.iv,
5192 sizeof(box_hdr.iv));
5193 // We are creating this key, so this must work.
5194 // FIXME: Possibly also add return values here. We are processing
5195 // Input from other peers...
5196 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5197 payload_hdr.sender = GST_my_identity;
5198 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5199 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5200 dv_encrypt (key,
5201 hdr,
5202 &enc[sizeof(struct TransportDVBoxPayloadP)],
5203 enc_body_size);
5204 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5205 dv_key_clean (key);
5207 /* For each selected path, take the pre-computed header and body
5208 and add the path in the middle of the message; then send it. */
5209 for (unsigned int i = 0; i < num_dvhs; i++)
5210 {
5211 struct DistanceVectorHop *dvh = dvhs[i];
5212 unsigned int num_hops = dvh->distance + 1;
5213 char buf[sizeof(struct TransportDVBoxMessage)
5214 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5215 + sizeof(struct TransportDVBoxPayloadP)
5216 + enc_body_size] GNUNET_ALIGN;
5217 struct GNUNET_PeerIdentity *dhops;
5218
5219 box_hdr.header.size = htons (sizeof(buf));
5220 box_hdr.orig_size = htons (sizeof(buf));
5221 box_hdr.num_hops = htons (num_hops);
5222 memcpy (buf, &box_hdr, sizeof(box_hdr));
5223 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5224 memcpy (dhops,
5225 dvh->path,
5226 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5227 dhops[dvh->distance] = dv->target;
5228 if (GNUNET_EXTRA_LOGGING > 0)
5229 {
5230 char *path;
5231
5233 for (unsigned int j = 0; j < num_hops; j++)
5234 {
5235 char *tmp;
5236
5237 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5238 GNUNET_free (path);
5239 path = tmp;
5240 }
5242 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5243 ntohs (hdr->type),
5244 GNUNET_i2s (&dv->target),
5245 i + 1,
5246 num_dvhs,
5247 path);
5248 GNUNET_free (path);
5249 }
5250 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5251 memcpy (&dhops[num_hops], enc, sizeof(enc));
5252 use (use_cls,
5253 dvh->next_hop,
5254 (const struct GNUNET_MessageHeader *) buf,
5255 options);
5256 GNUNET_free (key);
5257 }
5258 return rtt;
5259}
5260
5261
5271static void
5273 struct Neighbour *next_hop,
5274 const struct GNUNET_MessageHeader *hdr,
5276{
5277 (void) cls;
5278 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5279}
5280
5281
5293static struct GNUNET_TIME_Relative
5295// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5296 const struct GNUNET_MessageHeader *hdr,
5298{
5299 // struct VirtualLink *vl;
5300 struct Neighbour *n;
5301 struct DistanceVector *dv;
5302 struct GNUNET_TIME_Relative rtt1;
5303 struct GNUNET_TIME_Relative rtt2;
5304 const struct GNUNET_PeerIdentity *target = &vl->target;
5305
5307 "Trying to route message of type %u to %s without fc\n",
5308 ntohs (hdr->type),
5309 GNUNET_i2s (target));
5310
5311 // TODO Do this elsewhere. vl should be given as parameter to method.
5312 // vl = lookup_virtual_link (target);
5313 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5314 if (NULL == vl)
5316 n = vl->n;
5317 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5318 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5319 {
5320 /* if confirmed is required, and we do not have anything
5321 confirmed, drop respective options */
5322 if (NULL == n)
5323 n = lookup_neighbour (target);
5324 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5326 }
5327 if ((NULL == n) && (NULL == dv))
5328 {
5330 "Cannot route message of type %u to %s: no route\n",
5331 ntohs (hdr->type),
5332 GNUNET_i2s (target));
5334 "# Messages dropped in routing: no acceptable method",
5335 1,
5336 GNUNET_NO);
5338 }
5340 "Routing message of type %u to %s with options %X\n",
5341 ntohs (hdr->type),
5342 GNUNET_i2s (target),
5343 (unsigned int) options);
5344 /* If both dv and n are possible and we must choose:
5345 flip a coin for the choice between the two; for now 50/50 */
5346 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5347 {
5349 n = NULL;
5350 else
5351 dv = NULL;
5352 }
5353 if ((NULL != n) && (NULL != dv))
5354 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5355 enough for redundancy, so clear the flag. */
5358 if (NULL != n)
5359 {
5361 "Try to route message of type %u to %s without fc via neighbour\n",
5362 ntohs (hdr->type),
5363 GNUNET_i2s (target));
5364 rtt1 = route_via_neighbour (n, hdr, options);
5365 }
5366 if (NULL != dv)
5367 {
5368 struct DistanceVectorHop *hops[2];
5369 unsigned int res;
5370
5372 options,
5373 hops,
5374 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5375 if (0 == res)
5376 {
5378 "Failed to route message, could not determine DV path\n");
5379 return rtt1;
5380 }
5382 "encapsulate_for_dv 1\n");
5383 rtt2 = encapsulate_for_dv (dv,
5384 res,
5385 hops,
5386 hdr,
5388 NULL,
5390 GNUNET_YES);
5391 }
5392 return GNUNET_TIME_relative_min (rtt1, rtt2);
5393}
5394
5395
5396static void
5397consider_sending_fc (void *cls);
5398
5405static void
5407{
5408 struct VirtualLink *vl = cls;
5409 vl->fc_retransmit_task = NULL;
5410 consider_sending_fc (cls);
5411}
5412
5413
5414static char *
5415get_address_without_port (const char *address);
5416
5417
5419{
5420 size_t off;
5421 char *tgnas;
5422};
5423
5424
5425static enum GNUNET_GenericReturnValue
5427 const struct GNUNET_PeerIdentity *pid,
5428 void *value)
5429{
5430 struct AddGlobalAddressesContext *ctx = cls;
5431 struct TransportGlobalNattedAddress *tgna = value;
5432 char *addr = (char *) &tgna[1];
5433
5435 "sending address %s length %u\n",
5436 addr,
5437 ntohl (tgna->address_length));
5438 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5440 + ntohl (tgna->address_length));
5441 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5443
5444 return GNUNET_OK;
5445}
5446
5447
5448static struct GNUNET_TIME_Relative
5449calculate_rtt (struct DistanceVector *dv);
5450
5451
5458static void
5460{
5461 struct VirtualLink *vl = cls;
5462 struct GNUNET_TIME_Absolute monotime;
5463 struct TransportFlowControlMessage *fc;
5465 struct GNUNET_TIME_Relative rtt;
5466 struct GNUNET_TIME_Relative rtt_average;
5467 struct Neighbour *n = vl->n;
5468
5469 if (NULL != n && 0 < n->number_of_addresses)
5470 {
5471 size_t addresses_size =
5472 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5473 ->size_of_global_addresses;
5474 char *tgnas = GNUNET_malloc (addresses_size);
5476 ctx.off = 0;
5477 ctx.tgnas = tgnas;
5478
5479 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage)
5480 + addresses_size);
5481 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5482 + addresses_size);
5483 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5484 fc->number_of_addresses = htonl (n->number_of_addresses);
5485 GNUNET_CONTAINER_multipeermap_iterate (n->natted_addresses,
5487 &ctx);
5488 GNUNET_memcpy (&fc[1], tgnas, addresses_size);
5490 }
5491 else
5492 {
5493 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5494 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5495 }
5496
5498 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5499 it always! */
5500 /* For example, we should probably ONLY do this if a bit more than
5501 an RTT has passed, or if the window changed "significantly" since
5502 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5503 need an estimate for the bandwidth-delay-product for the entire
5504 VL, as that determines "significantly". We have the delay, but
5505 the bandwidth statistics need to be added for the VL!*/(void) duration;
5506
5507 if (NULL != vl->dv)
5508 rtt_average = calculate_rtt (vl->dv);
5509 else
5510 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5511 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5513 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5514 (unsigned int) vl->fc_seq_gen,
5515 GNUNET_i2s (&vl->target),
5516 (unsigned long long) vl->incoming_fc_window_size,
5517 (unsigned long) rtt_average.rel_value_us,
5518 vl->sync_ready);
5520 vl->last_fc_transmission = monotime;
5521 fc->sync_ready = vl->sync_ready;
5523 fc->seq = htonl (vl->fc_seq_gen++);
5529 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5531 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5532 {
5535 "FC retransmission to %s failed, will retry in %s\n",
5536 GNUNET_i2s (&vl->target),
5539 }
5540 else
5541 {
5542 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5543 vl->last_fc_rtt = rtt;
5544 }
5545 if (NULL != vl->fc_retransmit_task)
5548 {
5550 vl->fc_retransmit_count = 0;
5551 }
5552 vl->fc_retransmit_task =
5554 vl->fc_retransmit_count++;
5555 GNUNET_free (fc);
5556}
5557
5558
5575static void
5577{
5578 struct Neighbour *n = vl->n;
5579 struct DistanceVector *dv = vl->dv;
5580 struct GNUNET_TIME_Absolute now;
5581 struct VirtualLink *vl_next_hop;
5582 int elig;
5583
5585 "check_vl_transmission to target %s\n",
5586 GNUNET_i2s (&vl->target));
5587 /* Check that we have an eligible pending message!
5588 (cheaper than having #transmit_on_queue() find out!) */
5589 elig = GNUNET_NO;
5590 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5591 pm = pm->next_vl)
5592 {
5594 "check_vl_transmission loop\n");
5595 if (NULL != pm->qe)
5596 continue; /* not eligible, is in a queue! */
5597 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5599 {
5601 "Stalled message %" PRIu64
5602 " transmission on VL %s due to flow control: %llu < %llu\n",
5603 pm->logging_uuid,
5604 GNUNET_i2s (&vl->target),
5605 (unsigned long long) vl->outbound_fc_window_size,
5606 (unsigned long long) (pm->bytes_msg
5609 return; /* We have a message, but flow control says "nope" */
5610 }
5612 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5613 GNUNET_i2s (&vl->target));
5614 /* Notify queues at direct neighbours that we are interested */
5615 now = GNUNET_TIME_absolute_get ();
5616 if (NULL != n)
5617 {
5618 for (struct Queue *queue = n->queue_head; NULL != queue;
5619 queue = queue->next_neighbour)
5620 {
5621 if ((GNUNET_YES == queue->idle) &&
5622 (queue->validated_until.abs_value_us > now.abs_value_us))
5623 {
5625 "Direct neighbour %s not stalled\n",
5626 GNUNET_i2s (&n->pid));
5628 queue,
5630 elig = GNUNET_YES;
5631 }
5632 else
5634 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5635 queue->qid,
5636 queue->idle);
5637 }
5638 }
5639 /* Notify queues via DV that we are interested */
5640 if (NULL != dv)
5641 {
5642 /* Do DV with lower scheduler priority, which effectively means that
5643 IF a neighbour exists and is available, we prefer it. */
5644 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5645 pos = pos->next_dv)
5646 {
5647 struct Neighbour *nh_iter = pos->next_hop;
5648
5649
5650 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5651 continue; /* skip this one: path not validated */
5652 else
5653 {
5654 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5655 GNUNET_assert (NULL != vl_next_hop);
5656 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5657 vl_next_hop->outbound_fc_window_size)
5658 {
5660 "Stalled message %" PRIu64
5661 " transmission on next hop %s due to flow control: %llu < %llu\n",
5662 pm->logging_uuid,
5663 GNUNET_i2s (&vl_next_hop->target),
5664 (unsigned long
5665 long) vl_next_hop->outbound_fc_window_size,
5666 (unsigned long long) (pm->bytes_msg
5667 + vl_next_hop->
5668 outbound_fc_window_size_used));
5669 consider_sending_fc (vl_next_hop);
5670 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5671 }
5672 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5673 queue = queue->next_neighbour)
5674 if ((GNUNET_YES == queue->idle) &&
5675 (queue->validated_until.abs_value_us > now.abs_value_us))
5676 {
5678 "Next hop neighbour %s not stalled\n",
5679 GNUNET_i2s (&nh_iter->pid));
5681 queue,
5683 elig = GNUNET_YES;
5684 }
5685 else
5687 "DV Queue QID: %u (%u) busy or invalid\n",
5688 queue->qid,
5689 queue->idle);
5690 }
5691 }
5692 }
5693 if (GNUNET_YES == elig)
5695 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5696 pm->logging_uuid,
5697 pm->bytes_msg,
5698 GNUNET_i2s (&vl->target),
5699 (unsigned long long) vl->outbound_fc_window_size,
5700 (unsigned long long) (pm->bytes_msg
5702 break;
5703 }
5704}
5705
5706
5713static void
5714handle_client_send (void *cls, const struct OutboundMessage *obm)
5715{
5716 struct TransportClient *tc = cls;
5717 struct PendingMessage *pm;
5718 const struct GNUNET_MessageHeader *obmm;
5719 uint32_t bytes_msg;
5720 struct VirtualLink *vl;
5722
5723 GNUNET_assert (CT_CORE == tc->type);
5724 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5725 bytes_msg = ntohs (obmm->size);
5726 pp = ntohl (obm->priority);
5727 vl = lookup_virtual_link (&obm->peer);
5728 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5729 {
5731 "Don't have %s as a neighbour (anymore).\n",
5732 GNUNET_i2s (&obm->peer));
5733 /* Failure: don't have this peer as a neighbour (anymore).
5734 Might have gone down asynchronously, so this is NOT
5735 a protocol violation by CORE. Still count the event,
5736 as this should be rare. */
5739 "# messages dropped (neighbour unknown)",
5740 1,
5741 GNUNET_NO);
5742 return;
5743 }
5744
5745 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5747 "1 created pm %p storing vl %p\n",
5748 pm,
5749 vl);
5750 pm->logging_uuid = logging_uuid_gen++;
5751 pm->prefs = pp;
5752 pm->client = tc;
5753 pm->vl = vl;
5754 pm->bytes_msg = bytes_msg;
5755 memcpy (&pm[1], obmm, bytes_msg);
5757 "Sending message of type %u with %u bytes as <%" PRIu64
5758 "> to %s\n",
5759 ntohs (obmm->type),
5760 bytes_msg,
5761 pm->logging_uuid,
5762 GNUNET_i2s (&obm->peer));
5764 tc->details.core.pending_msg_head,
5765 tc->details.core.pending_msg_tail,
5766 pm);
5768 vl->pending_msg_head,
5769 vl->pending_msg_tail,
5770 pm);
5773}
5774
5775
5785static void
5787 void *cls,
5789{
5790 struct Neighbour *n;
5791 struct VirtualLink *vl;
5792 struct TransportClient *tc = cls;
5793 const struct GNUNET_MessageHeader *inbox =
5794 (const struct GNUNET_MessageHeader *) &cb[1];
5795 uint16_t isize = ntohs (inbox->size);
5796 const char *is = ((const char *) &cb[1]) + isize;
5797 size_t slen = strlen (is) + 1;
5798 char
5799 mbuf[slen + isize
5800 + sizeof(struct
5804
5805 /* 0-termination of 'is' was checked already in
5806 #check_communicator_backchannel() */
5808 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5809 GNUNET_i2s (&cb->pid),
5810 is,
5811 ntohs (inbox->type),
5812 ntohs (inbox->size));
5813 /* encapsulate and encrypt message */
5814 be->header.type =
5816 be->header.size = htons (sizeof(mbuf));
5817 memcpy (&be[1], inbox, isize);
5818 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5819 + isize],
5820 is,
5821 strlen (is) + 1);
5822 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5823 vl = lookup_virtual_link (&cb->pid);
5824 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5825 {
5827 }
5828 else
5829 {
5830 /* Use route via neighbour */
5831 n = lookup_neighbour (&cb->pid);
5832 if (NULL != n)
5834 n,
5835 &be->header,
5836 RMO_NONE);
5837 }
5839}
5840
5841
5849static int
5851 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5852{
5853 struct TransportClient *tc = cls;
5854
5855 if (CT_COMMUNICATOR != tc->type)
5856 {
5857 GNUNET_break (0);
5858 return GNUNET_SYSERR;
5859 }
5861 return GNUNET_OK;
5862}
5863
5864
5870static void
5871store_pi (void *cls);
5872
5873
5880static void
5881peerstore_store_own_cb (void *cls, int success)
5882{
5883 struct AddressListEntry *ale = cls;
5884
5885 ale->sc = NULL;
5886 if (GNUNET_YES != success)
5888 "Failed to store our own address `%s' in peerstore!\n",
5889 ale->address);
5890 else
5892 "Successfully stored our own address `%s' in peerstore!\n",
5893 ale->address);
5894 /* refresh period is 1/4 of expiration time, that should be plenty
5895 without being excessive. */
5896 ale->st =
5898 4ULL),
5899 &store_pi,
5900 ale);
5901}
5902
5903
5904static void
5905shc_cont (void *cls, int success)
5906{
5907 struct AddressListEntry *ale = cls;
5909
5912 "transport",
5915 ale->signed_address,
5916 ale->signed_address_len,
5917 expiration,
5920 ale);
5921 if (NULL == ale->sc)
5922 {
5924 "Failed to store our address `%s' with peerstore\n",
5925 ale->address);
5927 &store_pi,
5928 ale);
5929 }
5930}
5931
5932
5938static void
5939store_pi (void *cls)
5940{
5941 struct AddressListEntry *ale = cls;
5942 struct GNUNET_MQ_Envelope *env;
5943 const struct GNUNET_MessageHeader *msg;
5944 const char *dash;
5945 char *address_uri;
5947 unsigned int add_success;
5948
5949 dash = strchr (ale->address, '-');
5950 GNUNET_assert (NULL != dash);
5951 dash++;
5952 GNUNET_asprintf (&address_uri,
5953 "%s://%s",
5954 prefix,
5955 dash);
5957 ale->st = NULL;
5959 "Storing our address `%s' in peerstore until %s!\n",
5960 ale->address,
5963 address_uri);
5964 if (GNUNET_OK != add_success)
5965 {
5967 "Storing our address `%s' %s\n",
5968 address_uri,
5969 GNUNET_NO == add_success ? "not done" : "failed");
5970 GNUNET_free (address_uri);
5971 return;
5972 }
5973 else
5974 {
5975
5977 "Storing our address `%s'\n",
5978 address_uri);
5979 }
5980 // FIXME hello_mono_time used here?? What about expiration in ale?
5982 ale->nt,
5985 &ale->signed_address,
5986 &ale->signed_address_len);
5987 GNUNET_free (address_uri);
5993 "store_pi 1\n");
5995 msg,
5996 shc_cont,
5997 ale);
5998 GNUNET_free (env);
5999}
6000
6001
6002static struct AddressListEntry *
6006 const char *address,
6007 uint32_t aid,
6008 size_t slen)
6009{
6010 struct AddressListEntry *ale;
6011 char *address_without_port;
6012
6013 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6014 ale->tc = tc;
6015 ale->address = (const char *) &ale[1];
6016 ale->expiration = expiration;
6017 ale->aid = aid;
6018 ale->nt = nt;
6019 memcpy (&ale[1], address, slen);
6020 address_without_port = get_address_without_port (ale->address);
6022 "Is this %s a local address (%s)\n",
6023 address_without_port,
6024 ale->address);
6025 if (0 != strcmp ("127.0.0.1", address_without_port))
6026 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6027 GNUNET_free (address_without_port);
6028
6029 return ale;
6030}
6031
6032
6039static void
6041 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6042{
6043 struct TransportClient *tc = cls;
6044 struct AddressListEntry *ale;
6045 size_t slen;
6046 char *address;
6047
6048 /* 0-termination of &aam[1] was checked in #check_add_address */
6050 "Communicator added address `%s'!\n",
6051 (const char *) &aam[1]);
6052 slen = ntohs (aam->header.size) - sizeof(*aam);
6053 address = GNUNET_malloc (slen);
6054 memcpy (address, &aam[1], slen);
6055 ale = create_address_entry (tc,
6057 ntohl (aam->nt),
6058 address,
6059 aam->aid,
6060 slen);
6061 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6062 tc->details.communicator.addr_tail,
6063 ale);
6066}
6067
6068
6075static void
6077 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6078{
6079 struct TransportClient *tc = cls;
6080 struct AddressListEntry *alen;
6081
6082 if (CT_COMMUNICATOR != tc->type)
6083 {
6084 GNUNET_break (0);
6086 return;
6087 }
6088 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6089 NULL != ale;
6090 ale = alen)
6091 {
6092 alen = ale->next;
6093 if (dam->aid != ale->aid)
6094 continue;
6095 GNUNET_assert (ale->tc == tc);
6097 "Communicator deleted address `%s'!\n",
6098 ale->address);
6101 return;
6102 }
6104 "Communicator removed address we did not even have.\n");
6106 // GNUNET_SERVICE_client_drop (tc->client);
6107}
6108
6109
6117static void
6119
6120
6128static void
6130{
6131 struct CoreSentContext *ctx = cls;
6132 struct VirtualLink *vl = ctx->vl;
6133
6134 if (NULL == vl)
6135 {
6136 /* lost the link in the meantime, ignore */
6137 GNUNET_free (ctx);
6138 return;
6139 }
6142 vl->incoming_fc_window_size_ram -= ctx->size;
6143 vl->incoming_fc_window_size_used += ctx->isize;
6145 GNUNET_free (ctx);
6146}
6147
6148
6149static void
6151 const struct GNUNET_MessageHeader *mh,
6152 struct CommunicatorMessageContext *cmc,
6153 unsigned int free_cmc)
6154{
6155 uint16_t size = ntohs (mh->size);
6156 int have_core;
6157
6158 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6159 {
6161 "# CORE messages dropped (FC arithmetic overflow)",
6162 1,
6163 GNUNET_NO);
6165 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6166 (unsigned int) ntohs (mh->type),
6167 (unsigned int) ntohs (mh->size));
6168 if (GNUNET_YES == free_cmc)
6170 return;
6171 }
6173 {
6175 "# CORE messages dropped (FC window overflow)",
6176 1,
6177 GNUNET_NO);
6179 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6180 (unsigned int) ntohs (mh->type),
6181 (unsigned int) ntohs (mh->size));
6182 if (GNUNET_YES == free_cmc)
6184 return;
6185 }
6186
6187 /* Forward to all CORE clients */
6188 have_core = GNUNET_NO;
6189 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6190 {
6191 struct GNUNET_MQ_Envelope *env;
6192 struct InboundMessage *im;
6193 struct CoreSentContext *ctx;
6194
6195 if (CT_CORE != tc->type)
6196 continue;
6199 ctx = GNUNET_new (struct CoreSentContext);
6200 ctx->vl = vl;
6201 ctx->size = size;
6202 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6203 have_core = GNUNET_YES;
6206 im->peer = cmc->im.sender;
6207 memcpy (&im[1], mh, size);
6208 GNUNET_MQ_send (tc->mq, env);
6210 }
6211 if (GNUNET_NO == have_core)
6212 {
6214 "Dropped message to CORE: no CORE client connected!\n");
6215 /* Nevertheless, count window as used, as it is from the
6216 perspective of the other peer! */
6218 /* TODO-M1 */
6220 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6221 (unsigned int) ntohs (mh->type),
6222 (unsigned int) ntohs (mh->size));
6223 if (GNUNET_YES == free_cmc)
6225 return;
6226 }
6228 "Delivered message from %s of type %u to CORE recv window %d\n",
6229 GNUNET_i2s (&cmc->im.sender),
6230 ntohs (mh->type),
6232 if (vl->core_recv_window > 0)
6233 {
6234 if (GNUNET_YES == free_cmc)
6236 return;
6237 }
6238 /* Wait with calling #finish_cmc_handling(cmc) until the message
6239 was processed by CORE MQs (for CORE flow control)! */
6240 if (GNUNET_YES == free_cmc)
6242}
6243
6244
6253static void
6255{
6256 struct CommunicatorMessageContext *cmc = cls;
6257 // struct CommunicatorMessageContext *cmc_copy =
6258 // GNUNET_new (struct CommunicatorMessageContext);
6259 struct GNUNET_MessageHeader *mh_copy;
6260 struct RingBufferEntry *rbe;
6261 struct VirtualLink *vl;
6262 uint16_t size = ntohs (mh->size);
6263
6265 "Handling raw message of type %u with %u bytes\n",
6266 (unsigned int) ntohs (mh->type),
6267 (unsigned int) ntohs (mh->size));
6268
6269 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6270 (size < sizeof(struct GNUNET_MessageHeader)))
6271 {
6272 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6273
6274 GNUNET_break (0);
6275 finish_cmc_handling (cmc);
6277 return;
6278 }
6279 vl = lookup_virtual_link (&cmc->im.sender);
6280 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6281 {
6282 /* FIXME: sender is giving us messages for CORE but we don't have
6283 the link up yet! I *suspect* this can happen right now (i.e.
6284 sender has verified us, but we didn't verify sender), but if
6285 we pass this on, CORE would be confused (link down, messages
6286 arrive). We should investigate more if this happens often,
6287 or in a persistent manner, and possibly do "something" about
6288 it. Thus logging as error for now. */
6289
6290 mh_copy = GNUNET_malloc (size);
6291 rbe = GNUNET_new (struct RingBufferEntry);
6292 rbe->cmc = cmc;
6293 /*cmc_copy->tc = cmc->tc;
6294 cmc_copy->im = cmc->im;*/
6295 GNUNET_memcpy (mh_copy, mh, size);
6296
6297 rbe->mh = mh_copy;
6298
6300 {
6301 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6302 GNUNET_free (rbe_old->cmc);
6303 GNUNET_free (rbe_old->mh);
6304 GNUNET_free (rbe_old);
6305 }
6306 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6307 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6308 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6310 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6311 GNUNET_i2s (&cmc->im.sender),
6312 (unsigned int) ntohs (mh->type),
6313 (unsigned int) ntohs (mh_copy->type),
6317 {
6318 ring_buffer_head = 0;
6320 }
6321 else
6323
6325 "%u items stored in ring buffer\n",
6328
6329 /*GNUNET_break_op (0);
6330 GNUNET_STATISTICS_update (GST_stats,
6331 "# CORE messages dropped (virtual link still down)",
6332 1,
6333 GNUNET_NO);
6334
6335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6336 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6337 (unsigned int) ntohs (mh->type),
6338 (unsigned int) ntohs (mh->size));
6339 finish_cmc_handling (cmc);*/
6342 // GNUNET_free (cmc);
6343 return;
6344 }
6346}
6347
6348
6356static int
6358{
6359 uint16_t size = ntohs (fb->header.size);
6360 uint16_t bsize = size - sizeof(*fb);
6361
6362 (void) cls;
6363 if (0 == bsize)
6364 {
6365 GNUNET_break_op (0);
6366 return GNUNET_SYSERR;
6367 }
6368 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6369 {
6370 GNUNET_break_op (0);
6371 return GNUNET_SYSERR;
6372 }
6373 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6374 {
6375 GNUNET_break_op (0);
6376 return GNUNET_SYSERR;
6377 }
6378 return GNUNET_YES;
6379}
6380
6381
6387static void
6389{
6390 struct AcknowledgementCummulator *ac = cls;
6391
6392 ac->task = NULL;
6393 GNUNET_assert (0 == ac->num_acks);
6395 GNUNET_YES ==
6397 GNUNET_free (ac);
6398}
6399
6400
6406static void
6408{
6409 struct Neighbour *n;
6410 struct VirtualLink *vl;
6411 struct AcknowledgementCummulator *ac = cls;
6412 char buf[sizeof(struct TransportReliabilityAckMessage)
6413 + ac->num_acks
6415 struct TransportReliabilityAckMessage *ack =
6416 (struct TransportReliabilityAckMessage *) buf;
6418
6419 ac->task = NULL;
6421 "Sending ACK with %u components to %s\n",
6422 ac->num_acks,
6423 GNUNET_i2s (&ac->target));
6424 GNUNET_assert (0 < ac->num_acks);
6426 ack->header.size =
6427 htons (sizeof(*ack)
6428 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6429 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6430 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6431 for (unsigned int i = 0; i < ac->num_acks; i++)
6432 {
6433 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6436 }
6437 /*route_control_message_without_fc (
6438 &ac->target,
6439 &ack->header,
6440 RMO_DV_ALLOWED);*/
6441 vl = lookup_virtual_link (&ac->target);
6442 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6443 {
6445 vl,
6446 &ack->header,
6448 }
6449 else
6450 {
6451 /* Use route via neighbour */
6452 n = lookup_neighbour (&ac->target);
6453 if (NULL != n)
6455 n,
6456 &ack->header,
6457 RMO_NONE);
6458 }
6459 ac->num_acks = 0;
6462 ac);
6463}
6464
6465
6474static void
6476 const struct AcknowledgementUUIDP *ack_uuid,
6477 struct GNUNET_TIME_Absolute max_delay)
6478{
6479 struct AcknowledgementCummulator *ac;
6480
6482 "Scheduling ACK %s for transmission to %s\n",
6483 GNUNET_uuid2s (&ack_uuid->value),
6484 GNUNET_i2s (pid));
6486 if (NULL == ac)
6487 {
6489 ac->target = *pid;
6490 ac->min_transmission_time = max_delay;
6494 &ac->target,
6495 ac,
6497 }
6498 else
6499 {
6500 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6501 {
6502 /* must run immediately, ack buffer full! */
6504 }
6508 }
6511 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6512 ac->num_acks++;
6515 ac);
6516}
6517
6518
6523{
6528
6533};
6534
6535
6545static int
6546find_by_message_uuid (void *cls, uint32_t key, void *value)
6547{
6548 struct FindByMessageUuidContext *fc = cls;
6549 struct ReassemblyContext *rc = value;
6550
6551 (void) key;
6552 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6553 {
6554 fc->rc = rc;
6555 return GNUNET_NO;
6556 }
6557 return GNUNET_YES;
6558}
6559
6560
6568static void
6570{
6571 struct CommunicatorMessageContext *cmc = cls;
6572 struct VirtualLink *vl;
6573 struct ReassemblyContext *rc;
6574 const struct GNUNET_MessageHeader *msg;
6575 uint16_t msize;
6576 uint16_t fsize;
6577 uint16_t frag_off;
6578 char *target;
6579 struct GNUNET_TIME_Relative cdelay;
6580 struct FindByMessageUuidContext fc;
6581
6582 vl = lookup_virtual_link (&cmc->im.sender);
6583 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6584 {
6585 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6586
6588 "No virtual link for %s to handle fragment\n",
6589 GNUNET_i2s (&cmc->im.sender));
6590 GNUNET_break (0);
6591 finish_cmc_handling (cmc);
6593 return;
6594 }
6595 if (NULL == vl->reassembly_map)
6596 {
6598 vl->reassembly_heap =
6603 vl);
6604 }
6605 msize = ntohs (fb->msg_size);
6606 fc.message_uuid = fb->msg_uuid;
6607 fc.rc = NULL;
6609 fb->msg_uuid.uuid,
6611 &fc);
6612 fsize = ntohs (fb->header.size) - sizeof(*fb);
6613 if (NULL == (rc = fc.rc))
6614 {
6615 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6616 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6617 rc->msg_uuid = fb->msg_uuid;
6618 rc->virtual_link = vl;
6619 rc->msg_size = msize;
6620 rc->reassembly_timeout =
6624 rc,
6628 vl->reassembly_map,
6629 rc->msg_uuid.uuid,
6630 rc,
6632 target = (char *) &rc[1];
6633 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6634 if (fsize != rc->msg_size)
6635 rc->msg_missing = rc->msg_size;
6636 else
6637 rc->msg_missing = 0;
6639 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6640 PRIu64 "\n",
6641 fsize,
6642 ntohs (fb->frag_off),
6643 msize,
6644 rc->msg_missing,
6645 GNUNET_i2s (&cmc->im.sender),
6646 fb->msg_uuid.uuid);
6647 }
6648 else
6649 {
6650 target = (char *) &rc[1];
6652 "Received fragment at offset %u/%u from %s for message %u\n",
6653 ntohs (fb->frag_off),
6654 msize,
6655 GNUNET_i2s (&cmc->im.sender),
6656 (unsigned int) fb->msg_uuid.uuid);
6657 }
6658 if (msize != rc->msg_size)
6659 {
6660 GNUNET_break (0);
6661 finish_cmc_handling (cmc);
6662 return;
6663 }
6664
6665 /* reassemble */
6666 if (0 == fsize)
6667 {
6668 GNUNET_break (0);
6669 finish_cmc_handling (cmc);
6670 return;
6671 }
6672 frag_off = ntohs (fb->frag_off);
6673 if (frag_off + fsize > msize)
6674 {
6675 /* Fragment (plus fragment size) exceeds message size! */
6676 GNUNET_break_op (0);
6677 finish_cmc_handling (cmc);
6678 return;
6679 }
6680 memcpy (&target[frag_off], &fb[1], fsize);
6681 /* update bitfield and msg_missing */
6682 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6683 {
6684 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6685 {
6686 rc->bitfield[i / 8] |= (1 << (i % 8));
6687 rc->msg_missing--;
6688 }
6689 }
6690
6691 /* Compute cumulative ACK */
6693 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6694 if (0 == rc->msg_missing)
6695 cdelay = GNUNET_TIME_UNIT_ZERO;
6696 cummulative_ack (&cmc->im.sender,
6697 &fb->ack_uuid,
6700 /* is reassembly complete? */
6701 if (0 != rc->msg_missing)
6702 {
6703 finish_cmc_handling (cmc);
6704 return;
6705 }
6706 /* reassembly is complete, verify result */
6707 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6708 if (ntohs (msg->size) != rc->msg_size)
6709 {
6710 GNUNET_break (0);
6712 finish_cmc_handling (cmc);
6713 return;
6714 }
6715 /* successful reassembly */
6717 "Fragment reassembly complete for message %u\n",
6718 (unsigned int) fb->msg_uuid.uuid);
6719 /* FIXME: check that the resulting msg is NOT a
6720 DV Box or Reliability Box, as that is NOT allowed! */
6721 cmc->mh = msg;
6723 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6724 en-route and we forget that we finished this reassembly immediately!
6725 -> keep around until timeout?
6726 -> shorten timeout based on ACK? */
6728}
6729
6730
6738static int
6740 const struct TransportReliabilityBoxMessage *rb)
6741{
6742 const struct GNUNET_MessageHeader *box = (const struct
6743 GNUNET_MessageHeader *) &rb[1];
6744 (void) cls;
6745
6747 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6748 ntohs (rb->header.size),
6749 ntohs (box->type),
6750 ntohs (box->size),
6751 sizeof (struct TransportReliabilityBoxMessage),
6752 sizeof (struct GNUNET_MessageHeader));
6754 return GNUNET_YES;
6755}
6756
6757
6765static void
6767 const struct TransportReliabilityBoxMessage *rb)
6768{
6769 struct CommunicatorMessageContext *cmc = cls;
6770 const struct GNUNET_MessageHeader *inbox =
6771 (const struct GNUNET_MessageHeader *) &rb[1];
6772 struct GNUNET_TIME_Relative rtt;
6773
6775 "Received reliability box from %s with UUID %s of type %u\n",
6776 GNUNET_i2s (&cmc->im.sender),
6778 (unsigned int) ntohs (inbox->type));
6779 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6780 do not really have an RTT for the
6781 * incoming* queue (should we have
6782 the sender add it to the rb message?) */
6784 &cmc->im.sender,
6785 &rb->ack_uuid,
6786 (0 == ntohl (rb->ack_countdown))
6789 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6790 /* continue with inner message */
6791 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6792 reliability box (not allowed!) */
6793 cmc->mh = inbox;
6795}
6796
6797
6806static void
6807update_pd_age (struct PerformanceData *pd, unsigned int age)
6808{
6809 unsigned int sage;
6810
6811 if (age == pd->last_age)
6812 return; /* nothing to do */
6813 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6814 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6815 {
6816 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6817
6818 the->bytes_sent = 0;
6819 the->bytes_received = 0;
6820 }
6821 pd->last_age = age;
6822}
6823
6824
6833static void
6835 struct GNUNET_TIME_Relative rtt,
6836 uint16_t bytes_transmitted_ok)
6837{
6838 uint64_t nval = rtt.rel_value_us;
6839 uint64_t oval = pd->aged_rtt.rel_value_us;
6840 unsigned int age = get_age ();
6841 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
6842
6843 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
6844 pd->aged_rtt = rtt;
6845 else
6846 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
6847 update_pd_age (pd, age);
6848 the->bytes_received += bytes_transmitted_ok;
6849}
6850
6851
6859static void
6861 struct GNUNET_TIME_Relative rtt,
6862 uint16_t bytes_transmitted_ok)
6863{
6864 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
6865}
6866
6867
6875static void
6877 struct GNUNET_TIME_Relative rtt,
6878 uint16_t bytes_transmitted_ok)
6879{
6880 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
6881}
6882
6883
6891static void
6893{
6894 struct PendingMessage *pos;
6895
6897 "Complete transmission of message %" PRIu64 " %u\n",
6898 pm->logging_uuid,
6899 pm->pmt);
6900 switch (pm->pmt)
6901 {
6902 case PMT_CORE:
6904 /* Full message sent, we are done */
6906 return;
6907
6908 case PMT_FRAGMENT_BOX:
6909 /* Fragment sent over reliable channel */
6910 pos = pm->frag_parent;
6914 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
6915 (unsigned long) pos->frag_off,
6916 (unsigned long) pos->bytes_msg,
6917 pos->pmt,
6918 NULL == pos->frag_parent ? 1 : 0);
6919 /* check if subtree is done */
6920 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
6921 - sizeof(struct
6923 &&
6924 (NULL != pos->frag_parent))
6925 {
6926 pm = pos;
6927 pos = pm->frag_parent;
6928 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
6929 {
6931 return;
6932 }
6933 else if (PMT_DV_BOX == pm->pmt)
6934 {
6936 return;
6937 }
6940 }
6941
6942 /* Was this the last applicable fragment? */
6943 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
6944 pos->pmt) &&
6945 (pos->frag_off == pos->bytes_msg))
6947 return;
6948
6949 case PMT_DV_BOX:
6951 "Completed transmission of message %" PRIu64 " (DV Box)\n",
6952 pm->logging_uuid);
6953 if (NULL != pm->frag_parent)
6954 {
6955 pos = pm->frag_parent;
6957 pos->bpm = NULL;
6959 }
6960 else
6962 return;
6963 }
6964}
6965
6966
6974static void
6976 struct GNUNET_TIME_Relative ack_delay)
6977{
6978 struct GNUNET_TIME_Relative delay;
6979
6981 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
6982 if (NULL != pa->queue && 1 == pa->num_send)
6984 if (NULL != pa->dvh && 1 == pa->num_send)
6985 update_dvh_performance (pa->dvh, delay, pa->message_size);
6986 if (NULL != pa->pm)
6989}
6990
6991
6999static int
7001 const struct TransportReliabilityAckMessage *ra)
7002{
7003 unsigned int n_acks;
7004
7005 (void) cls;
7006 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7007 / sizeof(struct TransportCummulativeAckPayloadP);
7008 if (0 == n_acks)
7009 {
7010 GNUNET_break_op (0);
7011 return GNUNET_SYSERR;
7012 }
7013 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7014 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7015 {
7016 GNUNET_break_op (0);
7017 return GNUNET_SYSERR;
7018 }
7019 return GNUNET_OK;
7020}
7021
7022
7030static void
7032 const struct TransportReliabilityAckMessage *ra)
7033{
7034 struct CommunicatorMessageContext *cmc = cls;
7035 const struct TransportCummulativeAckPayloadP *ack;
7036 unsigned int n_acks;
7037 uint32_t ack_counter;
7038
7039 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7040 / sizeof(struct TransportCummulativeAckPayloadP);
7041 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7042 for (unsigned int i = 0; i < n_acks; i++)
7043 {
7044 struct PendingAcknowledgement *pa =
7046 if (NULL == pa)
7047 {
7049 "Received ACK from %s with UUID %s which is unknown to us!\n",
7050 GNUNET_i2s (&cmc->im.sender),
7051 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7053 GST_stats,
7054 "# FRAGMENT_ACKS dropped, no matching pending message",
7055 1,
7056 GNUNET_NO);
7057 continue;
7058 }
7060 "Received ACK from %s with UUID %s\n",
7061 GNUNET_i2s (&cmc->im.sender),
7062 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7063 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7064 }
7065
7066 ack_counter = htonl (ra->ack_counter);
7067 (void) ack_counter; /* silence compiler warning for now */
7068 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7069 // (DV and/or Neighbour?)
7070 finish_cmc_handling (cmc);
7071}
7072
7073
7081static int
7083 void *cls,
7085{
7086 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7087 const struct GNUNET_MessageHeader *inbox =
7088 (const struct GNUNET_MessageHeader *) &be[1];
7089 const char *is;
7090 uint16_t isize;
7091
7092 (void) cls;
7093 if (ntohs (inbox->size) >= size)
7094 {
7095 GNUNET_break_op (0);
7096 return GNUNET_SYSERR;
7097 }
7098 isize = ntohs (inbox->size);
7099 is = ((const char *) inbox) + isize;
7100 size -= isize;
7101 if ('\0' != is[size - 1])
7102 {
7103 GNUNET_break_op (0);
7104 return GNUNET_SYSERR;
7105 }
7106 return GNUNET_YES;
7107}
7108
7109
7118static void
7120 void *cls,
7122{
7123 struct CommunicatorMessageContext *cmc = cls;
7125 struct GNUNET_MQ_Envelope *env;
7126 struct TransportClient *tc;
7127 const struct GNUNET_MessageHeader *inbox =
7128 (const struct GNUNET_MessageHeader *) &be[1];
7129 uint16_t isize = ntohs (inbox->size);
7130 const char *target_communicator = ((const char *) inbox) + isize;
7131 char *sender;
7132 char *self;
7133
7134 GNUNET_asprintf (&sender,
7135 "%s",
7136 GNUNET_i2s (&cmc->im.sender));
7137 GNUNET_asprintf (&self,
7138 "%s",
7140
7141 /* Find client providing this communicator */
7142 for (tc = clients_head; NULL != tc; tc = tc->next)
7143 if ((CT_COMMUNICATOR == tc->type) &&
7144 (0 ==
7145 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7146 break;
7147 if (NULL == tc)
7148 {
7149 char *stastr;
7150
7152 &stastr,
7153 "# Backchannel message dropped: target communicator `%s' unknown",
7154 target_communicator);
7156 GNUNET_free (stastr);
7157 finish_cmc_handling (cmc);
7158 return;
7159 }
7160 /* Finally, deliver backchannel message to communicator */
7162 "Delivering backchannel message from %s to %s of type %u to %s\n",
7163 sender,
7164 self,
7165 ntohs (inbox->type),
7166 target_communicator);
7168 cbi,
7169 isize,
7171 cbi->pid = cmc->im.sender;
7172 memcpy (&cbi[1], inbox, isize);
7173 GNUNET_MQ_send (tc->mq, env);
7174 finish_cmc_handling (cmc);
7175}
7176
7177
7187static void
7189{
7190 struct DistanceVector *dv = cls;
7191 struct DistanceVectorHop *pos;
7192
7193 dv->timeout_task = NULL;
7194 while (NULL != (pos = dv->dv_head))
7195 {
7196 GNUNET_assert (dv == pos->dv);
7198 break;
7200 }
7201 if (NULL == pos)
7202 {
7203 free_dv_route (dv);
7204 return;
7205 }
7206 dv->timeout_task =
7208}
7209
7210
7211static void
7213{
7214
7215 const struct GNUNET_PeerIdentity target = vl->target;
7216
7217
7219 {
7220 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7221 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7222 0;
7223 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7226 struct CommunicatorMessageContext *cmc;
7227 struct RingBufferEntry *rbe;
7228 struct GNUNET_MessageHeader *mh;
7229
7231 "Sending from ring buffer, which has %u items\n",
7232 head);
7233
7234 ring_buffer_head = 0;
7235 for (unsigned int i = 0; i < head; i++)
7236 {
7237 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7238 cmc = rbe->cmc;
7239 mh = rbe->mh;
7240
7241 im = cmc->im;
7242 // mh = cmc->mh;
7244 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7245 mh->type,
7246 GNUNET_i2s (&im.sender),
7247 GNUNET_i2s2 (&target),
7248 (i + tail) % RING_BUFFER_SIZE);
7249 if (0 == GNUNET_memcmp (&target, &im.sender))
7250 {
7252 "Finish handling message of type %u and size %u\n",
7253 (unsigned int) ntohs (mh->type),
7254 (unsigned int) ntohs (mh->size));
7256 GNUNET_free (mh);
7257 GNUNET_free (rbe->cmc);
7258 GNUNET_free (rbe);
7259 }
7260 else
7261 {
7262 ring_buffer_copy[ring_buffer_head] = rbe;
7264 }
7265 }
7266
7269 {
7271 }
7272
7273 for (unsigned int i = 0; i < ring_buffer_head; i++)
7274 {
7275 ring_buffer[i] = ring_buffer_copy[i];
7277 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7278 i,
7279 ring_buffer_copy[i]->mh->type);
7281 "ring_buffer[i]->mh->type for i %u %u\n",
7282 i,
7283 ring_buffer[i]->mh->type);
7284 }
7285
7287 "%u items still in ring buffer\n",
7289 }
7290
7292 {
7293 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7294 struct PendingMessage *pm;
7295 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7297 0;
7298 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7301
7303 "Sending from ring buffer dv, which has %u items\n",
7304 head);
7305
7307 for (unsigned int i = 0; i < head; i++)
7308 {
7309 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7310
7312 "Sending to ring buffer target %s using vl target %s\n",
7313 GNUNET_i2s (&pm->target),
7314 GNUNET_i2s2 (&target));
7315 if (0 == GNUNET_memcmp (&target, &pm->target))
7316 {
7318 "Adding PendingMessage to vl, checking transmission.\n");
7319 pm->vl = vl;
7323 pm);
7324
7326 }
7327 else
7328 {
7329 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7331 }
7332 }
7333
7335 {
7337 }
7338
7339 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7340 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7341
7343 "%u items still in ring buffer dv.\n",
7345
7346 }
7347}
7348
7349
7357static void
7359{
7360 struct DistanceVector *dv = hop->dv;
7361 struct VirtualLink *vl;
7362
7363 vl = lookup_virtual_link (&dv->target);
7364 if (NULL == vl)
7365 {
7366
7367 vl = GNUNET_new (struct VirtualLink);
7369 "Creating new virtual link %p to %s using DV!\n",
7370 vl,
7371 GNUNET_i2s (&dv->target));
7372 vl->burst_addr = NULL;
7373 vl->confirmed = GNUNET_YES;
7374 vl->message_uuid_ctr =
7376 vl->target = dv->target;
7382 links,
7383 &vl->target,
7384 vl,
7386 vl->dv = dv;
7387 dv->vl = vl;
7388 vl->visibility_task =
7391 /* We lacked a confirmed connection to the target
7392 before, so tell CORE about it (finally!) */
7395 }
7396 else
7397 {
7398 /* Link was already up, remember dv is also now available and we are done */
7399 vl->dv = dv;
7400 dv->vl = vl;
7401 if (GNUNET_NO == vl->confirmed)
7402 {
7403 vl->confirmed = GNUNET_YES;
7404 vl->visibility_task =
7407 /* We lacked a confirmed connection to the target
7408 before, so tell CORE about it (finally!) */
7411 }
7412 else
7414 "Virtual link to %s could now also use DV!\n",
7415 GNUNET_i2s (&dv->target));
7416 }
7417}
7418
7419
7445static int
7447 unsigned int path_len,
7448 struct GNUNET_TIME_Relative network_latency,
7449 struct GNUNET_TIME_Absolute path_valid_until)
7450{
7451 struct DistanceVectorHop *hop;
7452 struct DistanceVector *dv;
7453 struct Neighbour *next_hop;
7454 unsigned int shorter_distance;
7455
7456 if (path_len < 3)
7457 {
7458 /* what a boring path! not allowed! */
7459 GNUNET_break (0);
7460 return GNUNET_SYSERR;
7461 }
7462 GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
7463 next_hop = lookup_neighbour (&path[1]);
7464 if (NULL == next_hop)
7465 {
7466 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7467 GNUNET_break (0);
7468 return GNUNET_SYSERR;
7469 }
7470 for (unsigned int i = 2; i < path_len; i++)
7471 {
7472 struct Neighbour *n = lookup_neighbour (&path[i]);
7473 struct GNUNET_TIME_Absolute q_timeout;
7474
7475 if (NULL != n)
7476 {
7477 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7478 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7479 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7481 "remaining %lu to %s\n",
7482 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7483 .rel_value_us,
7484 GNUNET_i2s (&n->pid));
7485 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7486 {
7487 /* Useless path: we have a direct active connection to some hop
7488 in the middle of the path, so this one is not even
7489 terribly useful for redundancy */
7491 "Path of %u hops useless: directly link to hop %u (%s)\n",
7492 path_len,
7493 i,
7494 GNUNET_i2s (&path[i]));
7496 "# Useless DV path ignored: hop is neighbour",
7497 1,
7498 GNUNET_NO);
7499 return GNUNET_SYSERR;
7500 }
7501 }
7502 }
7503 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7504 if (NULL == dv)
7505 {
7506 dv = GNUNET_new (struct DistanceVector);
7507 dv->target = path[path_len - 1];
7510 dv);
7513 dv_routes,
7514 &dv->target,
7515 dv,
7517 }
7518 /* Check if we have this path already! */
7519 shorter_distance = 0;
7520 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7521 pos = pos->next_dv)
7522 {
7523 if (pos->distance < path_len - 3)
7524 shorter_distance++;
7525 /* Note that the distances in 'pos' excludes us (path[0]),
7526 the next_hop (path[1]) and the target so we need to subtract three
7527 and check next_hop explicitly */
7528 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7529 {
7530 int match = GNUNET_YES;
7531
7532 for (unsigned int i = 0; i < pos->distance; i++)
7533 {
7534 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7535 {
7536 match = GNUNET_NO;
7537 break;
7538 }
7539 }
7540 if (GNUNET_YES == match)
7541 {
7542 struct GNUNET_TIME_Relative last_timeout;
7543
7544 /* Re-discovered known path, update timeout */
7546 "# Known DV path refreshed",
7547 1,
7548 GNUNET_NO);
7549 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7550 pos->timeout =
7552 pos->path_valid_until =
7553 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7554 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7555 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7556 if (0 <
7559 if (last_timeout.rel_value_us <
7562 .rel_value_us)
7563 {
7564 /* Some peer send DV learn messages too often, we are learning
7565 the same path faster than it would be useful; do not forward! */
7567 "Rediscovered path too quickly, not forwarding further\n")
7568 ;
7569 return GNUNET_NO;
7570 }
7572 "Refreshed known path to %s valid until %s, forwarding further\n",
7573 GNUNET_i2s (&dv->target),
7575 pos->path_valid_until));
7576 return GNUNET_YES;
7577 }
7578 }
7579 }
7580 /* Count how many shorter paths we have (incl. direct
7581 neighbours) before simply giving up on this one! */
7582 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7583 {
7584 /* We have a shorter path already! */
7586 "Have many shorter DV paths %s, not forwarding further\n",
7587 GNUNET_i2s (&dv->target));
7588 return GNUNET_NO;
7589 }
7590 /* create new DV path entry */
7592 "Discovered new DV path to %s valid until %s\n",
7593 GNUNET_i2s (&dv->target),
7594 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7595 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7596 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7597 hop->next_hop = next_hop;
7598 hop->dv = dv;
7599 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7600 memcpy (&hop[1],
7601 &path[2],
7602 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7604 hop->path_valid_until = path_valid_until;
7605 hop->distance = path_len - 3;
7606 hop->pd.aged_rtt = network_latency;
7607 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7609 next_hop->dv_head,
7610 next_hop->dv_tail,
7611 hop);
7612 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7614 return GNUNET_YES;
7615}
7616
7617
7625static int
7626check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7627{
7628 uint16_t size = ntohs (dvl->header.size);
7629 uint16_t num_hops = ntohs (dvl->num_hops);
7630 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7631
7632 (void) cls;
7633 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7634 {
7635 GNUNET_break_op (0);
7636 return GNUNET_SYSERR;
7637 }
7638 if (num_hops > MAX_DV_HOPS_ALLOWED)
7639 {
7640 GNUNET_break_op (0);
7641 return GNUNET_SYSERR;
7642 }
7643 for (unsigned int i = 0; i < num_hops; i++)
7644 {
7645 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7646 {
7647 GNUNET_break_op (0);
7648 return GNUNET_SYSERR;
7649 }
7650 if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
7651 {
7652 GNUNET_break_op (0);
7653 return GNUNET_SYSERR;
7654 }
7655 }
7656 return GNUNET_YES;
7657}
7658
7659
7671static void
7673 const struct TransportDVLearnMessage *msg,
7674 uint16_t bi_history,
7675 uint16_t nhops,
7676 const struct DVPathEntryP *hops,
7677 struct GNUNET_TIME_Absolute in_time)
7678{
7679 struct Neighbour *n;
7680 struct VirtualLink *vl;
7681 struct DVPathEntryP *dhops;
7682 char buf[sizeof(struct TransportDVLearnMessage)
7683 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7684 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7685 struct GNUNET_TIME_Relative nnd;
7686
7687 /* compute message for forwarding */
7689 "Forwarding DV learn message originating from %s to %s\n",
7690 GNUNET_i2s (&msg->initiator),
7691 GNUNET_i2s2 (next_hop));
7694 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7695 + (nhops + 1) * sizeof(struct DVPathEntryP));
7696 fwd->num_hops = htons (nhops + 1);
7697 fwd->bidirectional = htons (bi_history);
7700 msg->non_network_delay));
7702 fwd->init_sig = msg->init_sig;
7703 fwd->initiator = msg->initiator;
7704 fwd->challenge = msg->challenge;
7705 fwd->monotonic_time = msg->monotonic_time;
7706 dhops = (struct DVPathEntryP *) &fwd[1];
7707 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7708 dhops[nhops].hop = GST_my_identity;
7709 {
7710 struct DvHopPS dhp = {
7712 .purpose.size = htonl (sizeof(dhp)),
7713 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7714 .succ = *next_hop,
7715 .challenge = msg->challenge
7716 };
7718 &dhp,
7719 &dhops[nhops].hop_sig);
7720 }
7721 /*route_control_message_without_fc (next_hop,
7722 &fwd->header,
7723 RMO_UNCONFIRMED_ALLOWED);*/
7724 vl = lookup_virtual_link (next_hop);
7725 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7726 {
7728 &fwd->header,
7730 }
7731 else
7732 {
7733 /* Use route via neighbour */
7734 n = lookup_neighbour (next_hop);
7735 if (NULL != n)
7737 n,
7738 &fwd->header,
7740 }
7741}
7742
7743
7753static int
7755 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
7756 const struct GNUNET_PeerIdentity *init,
7758 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
7759{
7760 struct DvInitPS ip = { .purpose.purpose = htonl (
7762 .purpose.size = htonl (sizeof(ip)),
7763 .monotonic_time = sender_monotonic_time,
7764 .challenge = *challenge };
7765
7766 if (
7767 GNUNET_OK !=
7769 &ip,
7770 init_sig,
7771 &init->public_key))
7772 {
7773 GNUNET_break_op (0);
7774 return GNUNET_SYSERR;
7775 }
7776 return GNUNET_OK;
7777}
7778
7779
7784{
7789
7793 const struct DVPathEntryP *hops;
7794
7799
7804
7808 unsigned int num_eligible;
7809
7813 unsigned int num_selections;
7814
7818 uint16_t nhops;
7819
7823 uint16_t bi_history;
7824};
7825
7826
7835static int
7837 const struct GNUNET_PeerIdentity *pid,
7838 void *value)
7839{
7840 struct NeighbourSelectionContext *nsc = cls;
7841
7842 (void) value;
7843 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7844 return GNUNET_YES; /* skip initiator */
7845 for (unsigned int i = 0; i < nsc->nhops; i++)
7846 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7847 return GNUNET_YES;
7848 /* skip peers on path */
7849 nsc->num_eligible++;
7850 return GNUNET_YES;
7851}
7852
7853
7864static int
7866 const struct GNUNET_PeerIdentity *pid,
7867 void *value)
7868{
7869 struct NeighbourSelectionContext *nsc = cls;
7870
7872 "transmission %s\n",
7873 GNUNET_i2s (pid));
7874 (void) value;
7875 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
7876 return GNUNET_YES; /* skip initiator */
7877 for (unsigned int i = 0; i < nsc->nhops; i++)
7878 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
7879 return GNUNET_YES;
7880 /* skip peers on path */
7881 for (unsigned int i = 0; i < nsc->num_selections; i++)
7882 {
7883 if (nsc->selections[i] == nsc->num_eligible)
7884 {
7886 nsc->dvl,
7887 nsc->bi_history,
7888 nsc->nhops,
7889 nsc->hops,
7890 nsc->in_time);
7891 break;
7892 }
7893 }
7894 nsc->num_eligible++;
7895 return GNUNET_YES;
7896}
7897
7898
7942static unsigned int
7943calculate_fork_degree (unsigned int hops_taken,
7944 unsigned int neighbour_count,
7945 unsigned int eligible_count)
7946{
7947 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
7948 double eligible_ratio =
7949 ((double) eligible_count) / ((double) neighbour_count);
7950 double boost_factor = eligible_ratio * eligible_ratio;
7951 unsigned int rnd;
7952 double left;
7953
7954 if (hops_taken >= 64)
7955 {
7956 GNUNET_break (0);
7957 return 0; /* precaution given bitshift below */
7958 }
7959 for (unsigned int i = 1; i < hops_taken; i++)
7960 {
7961 /* For each hop, subtract the expected number of targets
7962 reached at distance d (so what remains divided by 2^d) */
7963 target_total -= (target_total * boost_factor / (1LLU << i));
7964 }
7965 rnd =
7966 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
7967 /* round up or down probabilistically depending on how close we were
7968 when floor()ing to rnd */
7969 left = target_total - (double) rnd;
7970 if (UINT32_MAX * left >
7972 rnd++; /* round up */
7974 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
7975 hops_taken,
7976 rnd,
7977 eligible_count,
7978 neighbour_count);
7979 return rnd;
7980}
7981
7982
7989static void
7990neighbour_store_dvmono_cb (void *cls, int success)
7991{
7992 struct Neighbour *n = cls;
7993
7994 n->sc = NULL;
7995 if (GNUNET_YES != success)
7997 "Failed to store other peer's monotonic time in peerstore!\n");
7998}
7999
8000
8001static struct GNUNET_TIME_Relative
8003{
8004 struct GNUNET_TIME_Relative host_latency_sum;
8005 struct GNUNET_TIME_Relative latency;
8006 struct GNUNET_TIME_Relative network_latency;
8007 uint16_t nhops = ntohs (dvl->num_hops);;
8008
8009 /* We initiated this, learn the forward path! */
8010 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8011
8012 // Need also something to lookup initiation time
8013 // to compute RTT! -> add RTT argument here?
8015 dvl->monotonic_time));
8016 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8017 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8018 // (based on dvl->challenge, we can identify time of origin!)
8019
8020 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8021 /* assumption: latency on all links is the same */
8022 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8023
8024 return network_latency;
8025}
8026
8027
8035static void
8036handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8037{
8038 struct CommunicatorMessageContext *cmc = cls;
8040 int bi_hop;
8041 uint16_t nhops;
8042 uint16_t bi_history;
8043 const struct DVPathEntryP *hops;
8044 int do_fwd;
8045 int did_initiator;
8046 struct GNUNET_TIME_Absolute in_time;
8047 struct Neighbour *n;
8048
8049 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8050 bi_history = ntohs (dvl->bidirectional);
8051 hops = (const struct DVPathEntryP *) &dvl[1];
8052 if (0 == nhops)
8053 {
8054 /* sanity check */
8055 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8056 {
8057 GNUNET_break (0);
8058 finish_cmc_handling (cmc);
8059 return;
8060 }
8061 }
8062 else
8063 {
8065 "handle dv learn message last hop %s\n",
8066 GNUNET_i2s (&hops[nhops - 1].hop));
8067 /* sanity check */
8068 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8069 {
8070 GNUNET_break (0);
8071 finish_cmc_handling (cmc);
8072 return;
8073 }
8074 }
8075
8077 cc = cmc->tc->details.communicator.cc;
8078 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8079 cc); // FIXME: add bi-directional flag to cc?
8080 in_time = GNUNET_TIME_absolute_get ();
8081
8082 /* continue communicator here, everything else can happen asynchronous! */
8083 finish_cmc_handling (cmc);
8084
8085 n = lookup_neighbour (&dvl->initiator);
8086 if (NULL != n)
8087 {
8088 if ((n->dv_monotime_available == GNUNET_YES) &&
8091 {
8093 "DV learn from %s discarded due to time travel",
8094 GNUNET_i2s (&dvl->initiator));
8096 "# DV learn discarded due to time travel",
8097 1,
8098 GNUNET_NO);
8099 return;
8100 }
8102 &dvl->initiator,
8103 &dvl->challenge,
8104 &dvl->init_sig))
8105 {
8107 "DV learn signature from %s invalid\n",
8108 GNUNET_i2s (&dvl->initiator));
8109 GNUNET_break_op (0);
8110 return;
8111 }
8114 {
8115 if (NULL != n->sc)
8116 {
8118 "store cancel\n");
8120 }
8121 n->sc =
8123 "transport",
8124 &dvl->initiator,
8126 &dvl->monotonic_time,
8127 sizeof(dvl->monotonic_time),
8131 n);
8132 }
8133 }
8134 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8135 If signature verification load too high, implement random drop strategy */
8136 for (unsigned int i = 0; i < nhops; i++)
8137 {
8138 struct DvHopPS dhp = { .purpose.purpose =
8140 .purpose.size = htonl (sizeof(dhp)),
8141 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8142 .succ = (nhops == i + 1) ? GST_my_identity
8143 : hops[i + 1].hop,
8144 .challenge = dvl->challenge };
8145
8146 if (GNUNET_OK !=
8148 &dhp,
8149 &hops[i].hop_sig,
8150 &hops[i].hop.public_key))
8151 {
8153 "DV learn from %s signature of hop %u invalid\n",
8154 GNUNET_i2s (&dvl->initiator),
8155 i);
8157 "signature of hop %s invalid\n",
8158 GNUNET_i2s (&hops[i].hop));
8160 "pred %s\n",
8161 GNUNET_i2s (&dhp.pred));
8163 "succ %s\n",
8164 GNUNET_i2s (&dhp.succ));
8166 "hash %s\n",
8167 GNUNET_sh2s (&dhp.challenge.value));
8168 GNUNET_break_op (0);
8169 return;
8170 }
8171 }
8172 if (GNUNET_EXTRA_LOGGING > 0)
8173 {
8174 char *path;
8175
8176 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8177 for (unsigned int i = 0; i < nhops; i++)
8178 {
8179 char *tmp;
8180
8181 GNUNET_asprintf (&tmp,
8182 "%s%s%s",
8183 path,
8184 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8185 GNUNET_i2s (&hops[i].hop));
8186 GNUNET_free (path);
8187 path = tmp;
8188 }
8190 "Received DVInit via %s%s%s\n",
8191 path,
8192 bi_hop ? "<->" : "-->",
8194 GNUNET_free (path);
8195 }
8196 do_fwd = GNUNET_YES;
8197 if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
8198 {
8199 struct GNUNET_PeerIdentity path[nhops + 1];
8200 struct GNUNET_TIME_Relative network_latency;
8201
8202 /* We initiated this, learn the forward path! */
8203 path[0] = GST_my_identity;
8204 path[1] = hops[0].hop;
8205
8206 network_latency = get_network_latency (dvl);
8207
8208 for (unsigned int i = 2; i <= nhops; i++)
8209 {
8210 struct GNUNET_TIME_Relative ilat;
8211
8212 /* assumption: linear latency increase per hop */
8213 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8214 path[i] = hops[i - 1].hop;
8216 "Learned path with %u hops to %s with latency %s\n",
8217 i,
8218 GNUNET_i2s (&path[i]),
8220 learn_dv_path (path,
8221 i + 1,
8222 ilat,
8225 }
8226 /* as we initiated, do not forward again (would be circular!) */
8227 do_fwd = GNUNET_NO;
8228 return;
8229 }
8230 if (bi_hop)
8231 {
8232 /* last hop was bi-directional, we could learn something here! */
8233 struct GNUNET_PeerIdentity path[nhops + 2];
8234 struct GNUNET_TIME_Relative ilat;
8235 struct GNUNET_TIME_Relative network_latency;
8236
8237 path[0] = GST_my_identity;
8238 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8239 for (unsigned int i = 0; i < nhops; i++)
8240 {
8241 int iret;
8242
8243 if (0 == (bi_history & (1 << i)))
8244 break; /* i-th hop not bi-directional, stop learning! */
8245 if (i == nhops - 1)
8246 {
8247 path[i + 2] = dvl->initiator;
8248 }
8249 else
8250 {
8251 path[i + 2] = hops[nhops - i - 2].hop;
8252 }
8253
8255 "Learned inverse path with %u hops to %s\n",
8256 i + 2,
8257 GNUNET_i2s (&path[i + 2]));
8258 network_latency = get_network_latency (dvl);
8259 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8260 iret = learn_dv_path (path,
8261 i + 3,
8262 ilat,
8265 if (GNUNET_SYSERR == iret)
8266 {
8267 /* path invalid or too long to be interesting for US, thus should also
8268 not be interesting to our neighbours, cut path when forwarding to
8269 'i' hops, except of course for the one that goes back to the
8270 initiator */
8272 "# DV learn not forwarded due invalidity of path",
8273 1,
8274 GNUNET_NO);
8275 do_fwd = GNUNET_NO;
8276 break;
8277 }
8278 if ((GNUNET_NO == iret) && (nhops == i + 1))
8279 {
8280 /* we have better paths, and this is the longest target,
8281 so there cannot be anything interesting later */
8283 "# DV learn not forwarded, got better paths",
8284 1,
8285 GNUNET_NO);
8286 do_fwd = GNUNET_NO;
8287 break;
8288 }
8289 }
8290 }
8291 if (MAX_DV_HOPS_ALLOWED == nhops)
8292 {
8293 /* At limit, we're out of here! */
8294 return;
8295 }
8296
8297 /* Forward to initiator, if path non-trivial and possible */
8298 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8299 did_initiator = GNUNET_NO;
8300 if ((1 <= nhops) &&
8301 (GNUNET_YES ==
8303 {
8304 /* send back to origin! */
8306 "Sending DVL back to initiator %s\n",
8307 GNUNET_i2s (&dvl->initiator));
8308 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8309 did_initiator = GNUNET_YES;
8310 }
8311 /* We forward under two conditions: either we still learned something
8312 ourselves (do_fwd), or the path was darn short and thus the initiator is
8313 likely to still be very interested in this (and we did NOT already
8314 send it back to the initiator) */
8315 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8316 (GNUNET_NO == did_initiator)))
8317 {
8318 /* Pick random neighbours that are not yet on the path */
8319 struct NeighbourSelectionContext nsc;
8320 unsigned int n_cnt;
8321
8323 nsc.nhops = nhops;
8324 nsc.dvl = dvl;
8325 nsc.bi_history = bi_history;
8326 nsc.hops = hops;
8327 nsc.in_time = in_time;
8328 nsc.num_eligible = 0;
8331 &nsc);
8332 if (0 == nsc.num_eligible)
8333 return; /* done here, cannot forward to anyone else */
8335 nsc.num_selections =
8338 "Forwarding DVL to %u other peers\n",
8339 nsc.num_selections);
8340 for (unsigned int i = 0; i < nsc.num_selections; i++)
8341 nsc.selections[i] =
8342 (nsc.num_selections == n_cnt)
8343 ? i /* all were selected, avoid collisions by chance */
8345 nsc.num_eligible = 0;
8348 &nsc);
8349 }
8350}
8351
8352
8360static int
8361check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8362{
8363 uint16_t size = ntohs (dvb->header.size);
8364 uint16_t num_hops = ntohs (dvb->num_hops);
8365 const struct GNUNET_PeerIdentity *hops =
8366 (const struct GNUNET_PeerIdentity *) &dvb[1];
8367
8368 (void) cls;
8369 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8370 + sizeof(struct GNUNET_MessageHeader))
8371 {
8372 GNUNET_break_op (0);
8373 return GNUNET_SYSERR;
8374 }
8375 /* This peer must not be on the path */
8376 for (unsigned int i = 0; i < num_hops; i++)
8377 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8378 {
8379 GNUNET_break_op (0);
8380 return GNUNET_SYSERR;
8381 }
8382 return GNUNET_YES;
8383}
8384
8385
8398static void
8399forward_dv_box (struct Neighbour *next_hop,
8400 struct TransportDVBoxMessage *hdr,
8401 uint16_t total_hops,
8402 uint16_t num_hops,
8403 const struct GNUNET_PeerIdentity *hops,
8404 const void *enc_payload,
8405 uint16_t enc_payload_size)
8406{
8407 struct VirtualLink *vl = next_hop->vl;
8408 struct PendingMessage *pm;
8409 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8410 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8411 + enc_payload_size;
8412 char *buf;
8413 char msg_buf[msg_size] GNUNET_ALIGN;
8414 struct GNUNET_PeerIdentity *dhops;
8415
8416 hdr->num_hops = htons (num_hops);
8417 hdr->total_hops = htons (total_hops);
8418 hdr->header.size = htons (msg_size);
8419 memcpy (msg_buf, hdr, sizeof(*hdr));
8420 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8422 ;
8423 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8424 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8425
8426 if (GNUNET_YES == ntohs (hdr->without_fc))
8427 {
8429 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8430 enc_payload_size,
8431 GNUNET_i2s (&next_hop->pid),
8432 (unsigned int) num_hops,
8433 (unsigned int) total_hops);
8434 route_via_neighbour (next_hop, (const struct
8435 GNUNET_MessageHeader *) msg_buf,
8437 }
8438 else
8439 {
8440 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8442 "2 created pm %p storing vl %p \n",
8443 pm,
8444 vl);
8445 pm->pmt = PMT_DV_BOX;
8446 pm->vl = vl;
8447 pm->target = next_hop->pid;
8449 pm->logging_uuid = logging_uuid_gen++;
8451 pm->bytes_msg = msg_size;
8452 buf = (char *) &pm[1];
8453 memcpy (buf, msg_buf, msg_size);
8454
8456 "Created pending message %" PRIu64
8457 " for DV Box with next hop %s (%u/%u)\n",
8458 pm->logging_uuid,
8459 GNUNET_i2s (&next_hop->pid),
8460 (unsigned int) num_hops,
8461 (unsigned int) total_hops);
8462
8463 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8464 {
8466 vl->pending_msg_head,
8467 vl->pending_msg_tail,
8468 pm);
8469
8471 }
8472 else
8473 {
8475 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8476
8478 {
8480
8481 GNUNET_free (pm_old);
8482 }
8485 {
8488 }
8489 else
8491
8493 "%u items stored in DV ring buffer\n",
8496 }
8497 }
8498}
8499
8500
8506static void
8508{
8509 if (NULL != b->get)
8510 {
8512 b->get = NULL;
8513 GNUNET_assert (NULL != b->cmc);
8515 b->cmc = NULL;
8516 }
8517 if (NULL != b->task)
8518 {
8520 b->task = NULL;
8521 }
8522 if (NULL != b->sc)
8523 {
8525 "store cancel\n");
8527 b->sc = NULL;
8528 }
8530 "Removing backtalker for %s\n",
8531 GNUNET_i2s (&b->pid));
8533 GNUNET_YES ==
8535 GNUNET_free (b);
8536}
8537
8538
8547static int
8549 const struct GNUNET_PeerIdentity *pid,
8550 void *value)
8551{
8552 struct Backtalker *b = value;
8553
8554 (void) cls;
8555 (void) pid;
8556 free_backtalker (b);
8557 return GNUNET_OK;
8558}
8559
8560
8566static void
8568{
8569 struct Backtalker *b = cls;
8570
8572 "backtalker timeout.\n");
8573 b->task = NULL;
8575 {
8577 return;
8578 }
8579 GNUNET_assert (NULL == b->sc);
8580 free_backtalker (b);
8581}
8582
8583
8592static void
8594 const struct GNUNET_PEERSTORE_Record *record,
8595 const char *emsg)
8596{
8597 struct Backtalker *b = cls;
8598 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8599 struct GNUNET_TIME_Absolute mt;
8600
8601 (void) emsg;
8602 if (NULL == record)
8603 {
8604 /* we're done with #backtalker_monotime_cb() invocations,
8605 continue normal processing */
8606 b->get = NULL;
8607 GNUNET_assert (NULL != b->cmc);
8608 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8609 if (0 != b->body_size)
8611 else
8613 b->cmc = NULL;
8614 return;
8615 }
8616 if (sizeof(*mtbe) != record->value_size)
8617 {
8619 GNUNET_break (0);
8620 return;
8621 }
8622 mtbe = record->value;
8623 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8625 {
8627 "Backtalker message from %s dropped, monotime in the past\n",
8628 GNUNET_i2s (&b->pid));
8630 GST_stats,
8631 "# Backchannel messages dropped: monotonic time not increasing",
8632 1,
8633 GNUNET_NO);
8634 b->monotonic_time = mt;
8635 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8636 */
8637 b->body_size = 0;
8638 }
8640}
8641
8642
8650static void
8651backtalker_monotime_store_cb (void *cls, int success)
8652{
8653 struct Backtalker *b = cls;
8654
8655 if (GNUNET_OK != success)
8656 {
8658 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8659 }
8660 b->sc = NULL;
8661 if (NULL != b->task)
8662 {
8664 b->task = NULL;
8665 }
8667}
8668
8669
8675static void
8677{
8678 struct GNUNET_TIME_AbsoluteNBO mtbe;
8679
8680 if (NULL != b->sc)
8681 {
8683 "store cancel before store with sc %p\n",
8684 b->sc);
8685 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8686 b->sc = NULL;*/
8688 "store cancel before store with sc %p is null\n",
8689 b->sc);
8690 }
8691 else
8692 {
8694 b->task = NULL;
8695 }
8697 b->sc =
8699 "transport",
8700 &b->pid,
8702 &mtbe,
8703 sizeof(mtbe),
8707 b);
8708}
8709
8710
8718static void
8719handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8720{
8721 struct CommunicatorMessageContext *cmc = cls;
8722 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
8723 uint16_t num_hops = ntohs (dvb->num_hops);
8724 const struct GNUNET_PeerIdentity *hops =
8725 (const struct GNUNET_PeerIdentity *) &dvb[1];
8726 const char *enc_payload = (const char *) &hops[num_hops];
8727 uint16_t enc_payload_size =
8728 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
8729 struct DVKeyState key;
8730 struct GNUNET_HashCode hmac;
8731 const char *hdr;
8732 size_t hdr_len;
8733
8734 if (GNUNET_EXTRA_LOGGING > 0)
8735 {
8736 char *path;
8737
8739 for (unsigned int i = 0; i < num_hops; i++)
8740 {
8741 char *tmp;
8742
8743 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
8744 GNUNET_free (path);
8745 path = tmp;
8746 }
8748 "Received DVBox with remaining path %s\n",
8749 path);
8750 GNUNET_free (path);
8751 }
8752
8753 if (num_hops > 0)
8754 {
8755 /* We're trying from the end of the hops array, as we may be
8756 able to find a shortcut unknown to the origin that way */
8757 for (int i = num_hops - 1; i >= 0; i--)
8758 {
8759 struct Neighbour *n;
8760
8761 if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
8762 {
8763 GNUNET_break_op (0);
8764 finish_cmc_handling (cmc);
8765 return;
8766 }
8767 n = lookup_neighbour (&hops[i]);
8768 if (NULL == n)
8769 continue;
8771 "Skipping %u/%u hops ahead while routing DV Box\n",
8772 i,
8773 num_hops);
8774
8775 forward_dv_box (n,
8776 (struct TransportDVBoxMessage *) dvb,
8777 ntohs (dvb->total_hops) + 1,
8778 num_hops - i - 1, /* number of hops left */
8779 &hops[i + 1], /* remaining hops */
8780 enc_payload,
8781 enc_payload_size);
8783 "# DV hops skipped routing boxes",
8784 i,
8785 GNUNET_NO);
8787 "# DV boxes routed (total)",
8788 1,
8789 GNUNET_NO);
8790 finish_cmc_handling (cmc);
8791 return;
8792 }
8793 /* Woopsie, next hop not in neighbours, drop! */
8795 "# DV Boxes dropped: next hop unknown",
8796 1,
8797 GNUNET_NO);
8798 finish_cmc_handling (cmc);
8799 return;
8800 }
8801 /* We are the target. Unbox and handle message. */
8803 "# DV boxes opened (ultimate target)",
8804 1,
8805 GNUNET_NO);
8806 cmc->total_hops = ntohs (dvb->total_hops);
8807
8808 // DH key derivation with received DV, could be garbage.
8809 {
8810 struct GNUNET_ShortHashCode km;
8811
8813 &dvb->ephemeral_key,
8814 &km))
8815 {
8816 GNUNET_break_op (0);
8817 finish_cmc_handling (cmc);
8818 return;
8819 }
8820 dv_setup_key_state_from_km (&km, &dvb->iv, &key);
8821 }
8822 hdr = (const char *) &dvb[1];
8823 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8825 * ntohs (dvb->total_hops);
8826
8827 dv_hmac (&key, &hmac, hdr, hdr_len);
8828 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
8829 {
8830 /* HMAC mismatch, discard! */
8831 GNUNET_break_op (0);
8832 finish_cmc_handling (cmc);
8833 return;
8834 }
8835 /* begin actual decryption */
8836 {
8837 struct Backtalker *b;
8838 struct GNUNET_TIME_Absolute monotime;
8839 struct TransportDVBoxPayloadP ppay;
8840 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
8841 const struct GNUNET_MessageHeader *mh;
8842
8843 GNUNET_assert (hdr_len >=
8844 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
8845 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
8846 {
8848 "Error decrypting DV payload header\n");
8849 GNUNET_break_op (0);
8850 finish_cmc_handling (cmc);
8851 return;
8852 }
8853 if (GNUNET_OK != dv_decrypt (&key, body,
8854 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
8855 {
8857 "Error decrypting DV payload\n");
8858 GNUNET_break_op (0);
8859 finish_cmc_handling (cmc);
8860 return;
8861 }
8862 mh = (const struct GNUNET_MessageHeader *) body;
8863 dv_key_clean (&key);
8864 if (ntohs (mh->size) != sizeof(body))
8865 {
8866 GNUNET_break_op (0);
8867 finish_cmc_handling (cmc);
8868 return;
8869 }
8870 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
8871 switch (ntohs (mh->type))
8872 {
8874 GNUNET_break_op (0);
8875 finish_cmc_handling (cmc);
8876 return;
8877
8879 GNUNET_break_op (0);
8880 finish_cmc_handling (cmc);
8881 return;
8882
8883 default:
8884 /* permitted, continue */
8885 break;
8886 }
8887 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
8889 "Decrypted backtalk from %s\n",
8890 GNUNET_i2s (&ppay.sender));
8892 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
8893 {
8895 GST_stats,
8896 "# Backchannel messages dropped: monotonic time not increasing",
8897 1,
8898 GNUNET_NO);
8899 finish_cmc_handling (cmc);
8900 return;
8901 }
8902 if ((NULL == b) ||
8903 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
8904 {
8905 /* Check signature */
8906 struct EphemeralConfirmationPS ec;
8907
8910 ec.ephemeral_key = dvb->ephemeral_key;
8911 ec.purpose.size = htonl (sizeof(ec));
8913 if (
8914 GNUNET_OK !=
8917 &ec,
8918 &ppay.sender_sig,
8919 &ppay.sender.public_key))
8920 {
8921 /* Signature invalid, discard! */
8922 GNUNET_break_op (0);
8923 finish_cmc_handling (cmc);
8924 return;
8925 }
8926 }
8927 /* Update sender, we now know the real origin! */
8929 "DVBox received for me from %s via %s\n",
8930 GNUNET_i2s2 (&ppay.sender),
8931 GNUNET_i2s (&cmc->im.sender));
8932 cmc->im.sender = ppay.sender;
8933
8934 if (NULL != b)
8935 {
8936 /* update key cache and mono time */
8937 b->last_ephemeral = dvb->ephemeral_key;
8938 b->monotonic_time = monotime;
8940 b->timeout =
8942 cmc->mh = mh;
8944 return;
8945 }
8946 /* setup data structure to cache signature AND check
8947 monotonic time with PEERSTORE before forwarding backchannel payload */
8948 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
8949 b->pid = ppay.sender;
8950 b->body_size = sizeof(body);
8951 memcpy (&b[1], body, sizeof(body));
8955 &b->pid,
8956 b,
8958 b->monotonic_time = monotime; /* NOTE: to be checked still! */
8959 b->cmc = cmc;
8960 b->timeout =
8963 b->get =
8965 "transport",
8966 &b->pid,
8969 b);
8970 } /* end actual decryption */
8971}
8972
8973
8981static int
8983 const struct GNUNET_TRANSPORT_IncomingMessage *im)
8984{
8985 struct TransportClient *tc = cls;
8986
8987 if (CT_COMMUNICATOR != tc->type)
8988 {
8989 GNUNET_break (0);
8990 return GNUNET_SYSERR;
8991 }
8993 return GNUNET_OK;
8994}
8995
8996
9001{
9005 const char *address;
9006
9011};
9012
9013
9023static int
9025 const struct GNUNET_PeerIdentity *pid,
9026 void *value)
9027{
9028 struct CheckKnownAddressContext *ckac = cls;
9029 struct ValidationState *vs = value;
9030
9031 (void) pid;
9032 if (0 != strcmp (vs->address, ckac->address))
9033 return GNUNET_OK;
9034 ckac->vs = vs;
9035 return GNUNET_NO;
9036}
9037
9038
9044static void
9045validation_start_cb (void *cls);
9046
9047
9055static void
9057 struct GNUNET_TIME_Absolute new_time)
9058{
9060
9061 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9062 return; /* be lazy */
9063 vs->next_challenge = new_time;
9064 if (NULL == vs->hn)
9065 vs->hn =
9067 else
9070 (NULL != validation_task))
9071 return;
9072 if (NULL != validation_task)
9074 /* randomize a bit */
9077 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9078 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9081}
9082
9083
9090static void
9092 const char *address)
9093{
9094 struct GNUNET_TIME_Absolute now;
9095 struct ValidationState *vs;
9096 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9097
9099 pid,
9101 &ckac);
9102 if (NULL != (vs = ckac.vs))
9103 {
9104 /* if 'vs' is not currently valid, we need to speed up retrying the
9105 * validation */
9106 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9107 {
9108 /* reduce backoff as we got a fresh advertisement */
9109 vs->challenge_backoff =
9112 vs->challenge_backoff,
9113 2));
9116 vs->challenge_backoff));
9117 }
9118 return;
9119 }
9121 vs = GNUNET_new (struct ValidationState);
9122 vs->pid = *pid;
9123 vs->valid_until =
9125 vs->first_challenge_use = now;
9126 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9128 &vs->challenge,
9129 sizeof(vs->challenge));
9130 vs->address = GNUNET_strdup (address);
9131 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9133 "Starting address validation `%s' of peer %s using challenge %s\n",
9134 address,
9135 GNUNET_i2s (pid),
9136 GNUNET_sh2s (&vs->challenge.value));
9140 &vs->pid,
9141 vs,
9144}
9145
9146
9147static struct Queue *
9148find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9149
9150
9151static void
9152suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9153
9154
9155static void
9157 const struct GNUNET_PeerIdentity *pid,
9158 const char *uri)
9159{
9160 struct Queue *q;
9161 int pfx_len;
9162 const char *eou;
9163 char *address;
9164 (void) cls;
9165
9166 eou = strstr (uri,
9167 "://");
9168 pfx_len = eou - uri;
9169 eou += 3;
9171 "%.*s-%s",
9172 pfx_len,
9173 uri,
9174 eou);
9175
9177 "helo for client %s\n",
9178 address);
9179 q = find_queue (pid, address);
9180 if (NULL == q)
9181 {
9183 }
9184 else
9187}
9188
9189
9197static void
9199 const struct GNUNET_PEERSTORE_Record *record,
9200 const char *emsg)
9201{
9202 struct IncomingRequest *ir = cls;
9204 struct GNUNET_MessageHeader *hello;
9205
9206 if (NULL != emsg)
9207 {
9209 "Got failure from PEERSTORE: %s\n",
9210 emsg);
9211 return;
9212 }
9213 hello = record->value;
9214 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
9215 {
9217 return;
9218 }
9222 NULL);
9224}
9225
9226
9227static void
9229{
9231 "Error in PEERSTORE monitoring\n");
9232}
9233
9234
9235static void
9237{
9239 "Done with initial PEERSTORE iteration during monitoring\n");
9240}
9241
9242
9251static void
9253 void *cls,
9254 const struct TransportValidationChallengeMessage *tvc)
9255{
9256 struct CommunicatorMessageContext *cmc = cls;
9258 struct VirtualLink *vl;
9259 struct GNUNET_TIME_RelativeNBO validity_duration;
9260 struct IncomingRequest *ir;
9261 struct Neighbour *n;
9262 struct GNUNET_PeerIdentity sender;
9263
9264 /* DV-routed messages are not allowed for validation challenges */
9265 if (cmc->total_hops > 0)
9266 {
9267 GNUNET_break_op (0);
9268 finish_cmc_handling (cmc);
9269 return;
9270 }
9271 validity_duration = cmc->im.expected_address_validity;
9273 "Received address validation challenge %s\n",
9274 GNUNET_sh2s (&tvc->challenge.value));
9275 /* If we have a virtual link, we use this mechanism to signal the
9276 size of the flow control window, and to allow the sender
9277 to ask for increases. If for us the virtual link is still down,
9278 we will always give a window size of zero. */
9279 tvr.header.type =
9281 tvr.header.size = htons (sizeof(tvr));
9282 tvr.reserved = htonl (0);
9283 tvr.challenge = tvc->challenge;
9284 tvr.origin_time = tvc->sender_time;
9285 tvr.validity_duration = validity_duration;
9286 {
9287 /* create signature */
9288 struct TransportValidationPS tvp = {
9290 .purpose.size = htonl (sizeof(tvp)),
9291 .validity_duration = validity_duration,
9292 .challenge = tvc->challenge
9293 };
9294
9296 &tvp,
9297 &tvr.signature);
9298 }
9299 sender = cmc->im.sender;
9300 vl = lookup_virtual_link (&sender);
9301 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9302 {
9303 // route_control_message_without_fc (&cmc->im.sender,
9305 &tvr.header,
9307 }
9308 else
9309 {
9310 /* Use route via neighbour */
9311 n = lookup_neighbour (&sender);
9312 if (NULL != n)
9313 route_via_neighbour (n, &tvr.header,
9316 }
9317
9318 finish_cmc_handling (cmc);
9319 if (NULL != vl)
9320 return;
9321
9322 /* For us, the link is still down, but we need bi-directional
9323 connections (for flow-control and for this to be useful for
9324 CORE), so we must try to bring the link up! */
9325
9326 /* (1) Check existing queues, if any, we may be lucky! */
9327 n = lookup_neighbour (&sender);
9328 if (NULL != n)
9329 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9330 start_address_validation (&sender, q->address);
9331 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9332 we could use */
9333 for (ir = ir_head; NULL != ir; ir = ir->next)
9334 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9335 return;
9336 /* we are already trying */
9337 ir = GNUNET_new (struct IncomingRequest);
9338 ir->pid = sender;
9340
9342 GNUNET_YES,
9343 "peerstore",
9344 NULL,
9347 NULL,
9349 NULL,
9351 ir);
9352 ir_total++;
9353 /* Bound attempts we do in parallel here, might otherwise get excessive */
9356}
9357
9358
9363{
9368
9373};
9374
9375
9385static int
9387 const struct GNUNET_PeerIdentity *pid,
9388 void *value)
9389{
9390 struct CheckKnownChallengeContext *ckac = cls;
9391 struct ValidationState *vs = value;
9392
9393 (void) pid;
9394 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9395 return GNUNET_OK;
9396 ckac->vs = vs;
9397 return GNUNET_NO;
9398}
9399
9400
9408static void
9409peerstore_store_validation_cb (void *cls, int success)
9410{
9411 struct ValidationState *vs = cls;
9412
9413 vs->sc = NULL;
9414 if (GNUNET_YES == success)
9415 return;
9417 "# Peerstore failed to store foreign address",
9418 1,
9419 GNUNET_NO);
9420}
9421
9422
9430static struct Queue *
9431find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9432{
9433 struct Neighbour *n;
9434
9435 n = lookup_neighbour (pid);
9436 if (NULL == n)
9437 return NULL;
9438 for (struct Queue *pos = n->queue_head; NULL != pos;
9439 pos = pos->next_neighbour)
9440 {
9441 if (0 == strcmp (pos->address, address))
9442 return pos;
9443 }
9444 return NULL;
9445}
9446
9447
9448static void
9450
9451static void
9453{
9454 struct ValidationState *vs = cls;
9455 struct Queue *q;
9456 struct GNUNET_TIME_Absolute now;
9457
9458 vs->revalidation_task = NULL;
9459 q = find_queue (&vs->pid, vs->address);
9460 if (NULL == q)
9461 {
9462 now = GNUNET_TIME_absolute_get ();
9463 vs->awaiting_queue = GNUNET_YES;
9464 suggest_to_connect (&vs->pid, vs->address);
9466 }
9467 else
9469}
9470
9471
9472static enum GNUNET_GenericReturnValue
9474 void *cls,
9475 const struct GNUNET_HashCode *key,
9476 void *value)
9477{
9478 (void) cls;
9480 "Key in revalidate map %s \n",
9481 GNUNET_h2s (key));
9482 return GNUNET_YES;
9483}
9484
9485
9494static void
9496 void *cls,
9497 const struct TransportValidationResponseMessage *tvr)
9498{
9499 struct CommunicatorMessageContext *cmc = cls;
9500 struct ValidationState *vs;
9501 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9502 .vs = NULL};
9503 struct GNUNET_TIME_Absolute origin_time;
9504 struct Queue *q;
9505 struct Neighbour *n;
9506 struct VirtualLink *vl;
9508 GST_cfg);
9509
9510 /* check this is one of our challenges */
9512 &cmc->im.sender,
9514 &ckac);
9515 if (NULL == (vs = ckac.vs))
9516 {
9517 /* This can happen simply if we 'forgot' the challenge by now,
9518 i.e. because we received the validation response twice */
9520 "# Validations dropped, challenge unknown",
9521 1,
9522 GNUNET_NO);
9524 "Validation response %s dropped, challenge unknown\n",
9525 GNUNET_sh2s (&tvr->challenge.value));
9526 finish_cmc_handling (cmc);
9527 return;
9528 }
9529
9530 /* sanity check on origin time */
9531 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9532 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9533 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9534 {
9536 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9537 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9538 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9539 GNUNET_break_op (0);
9540 finish_cmc_handling (cmc);
9541 return;
9542 }
9543
9544 {
9545 /* check signature */
9546 struct TransportValidationPS tvp = {
9548 .purpose.size = htonl (sizeof(tvp)),
9549 .validity_duration = tvr->validity_duration,
9550 .challenge = tvr->challenge
9551 };
9552
9553 if (
9554 GNUNET_OK !=
9556 &tvp,
9557 &tvr->signature,
9558 &cmc->im.sender.public_key))
9559 {
9560 GNUNET_break_op (0);
9561 finish_cmc_handling (cmc);
9562 return;
9563 }
9564 }
9565
9566 /* validity is capped by our willingness to keep track of the
9567 validation entry and the maximum the other peer allows */
9570 tvr->validity_duration),
9572 vs->validated_until =
9576 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9577 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9579 &vs->challenge,
9580 sizeof(vs->challenge));
9581 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9582 vs->validated_until,
9583 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9585 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9586 {
9588 "First challenge use is now %" PRIu64 " %s \n",
9589 vs->first_challenge_use.abs_value_us,
9590 GNUNET_sh2s (&vs->challenge.value));
9591 vs->first_challenge_use = now;
9592 }
9593 else
9595 "First challenge use is later %" PRIu64 " %s \n",
9596 vs->first_challenge_use.abs_value_us,
9597 GNUNET_sh2s (&vs->challenge.value));
9598 vs->last_challenge_use =
9599 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
9600 update_next_challenge_time (vs, vs->first_challenge_use);
9602 "Validation response %s from %s accepted, address valid until %s\n",
9603 GNUNET_sh2s (&tvr->challenge.value),
9604 GNUNET_i2s (&cmc->im.sender),
9606 /*memcpy (&hkey,
9607 &hc,
9608 sizeof (hkey));*/
9610 "Key %s for address %s map size %u contains %u\n",
9611 GNUNET_h2s (&vs->hc),
9612 vs->address,
9615 &vs->hc));
9619 &vs->hc,
9620 vs,
9624 NULL);
9625 vs->revalidation_task =
9630 "transport",
9631 &cmc->im.sender,
9633 vs->address,
9634 strlen (vs->address) + 1,
9635 vs->valid_until,
9638 vs);
9639 finish_cmc_handling (cmc);
9640
9641 /* Finally, we now possibly have a confirmed (!) working queue,
9642 update queue status (if queue still is around) */
9643 q = find_queue (&vs->pid, vs->address);
9644 if (NULL == q)
9645 {
9647 "# Queues lost at time of successful validation",
9648 1,
9649 GNUNET_NO);
9650 return;
9651 }
9652 q->validated_until = vs->validated_until;
9653 q->pd.aged_rtt = vs->validation_rtt;
9654 n = q->neighbour;
9655 vl = lookup_virtual_link (&vs->pid);
9656 if (NULL == vl)
9657 {
9658 vl = GNUNET_new (struct VirtualLink);
9660 "Creating new virtual link %p to %s using direct neighbour!\n",
9661 vl,
9662 GNUNET_i2s (&vs->pid));
9663 vl->burst_addr = NULL;
9664 vl->confirmed = GNUNET_YES;
9665 vl->message_uuid_ctr =
9667 vl->target = n->pid;
9673 links,
9674 &vl->target,
9675 vl,
9677 vl->n = n;
9678 n->vl = vl;
9679 q->idle = GNUNET_YES;
9680 vl->visibility_task =
9681 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9683 /* We lacked a confirmed connection to the target
9684 before, so tell CORE about it (finally!) */
9687 }
9688 else
9689 {
9690 /* Link was already up, remember n is also now available and we are done */
9691 if (NULL == vl->n)
9692 {
9693 vl->n = n;
9694 n->vl = vl;
9695 if (GNUNET_YES == vl->confirmed)
9697 "Virtual link to %s could now also use direct neighbour!\n",
9698 GNUNET_i2s (&vs->pid));
9699 }
9700 else
9701 {
9702 GNUNET_assert (n == vl->n);
9703 }
9704 if (GNUNET_NO == vl->confirmed)
9705 {
9706 vl->confirmed = GNUNET_YES;
9707 q->idle = GNUNET_YES;
9708 vl->visibility_task =
9709 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9711 /* We lacked a confirmed connection to the target
9712 before, so tell CORE about it (finally!) */
9715 }
9716 }
9717}
9718
9719
9725static void
9727 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9728{
9729 struct TransportClient *tc = cls;
9730 struct CommunicatorMessageContext *cmc =
9732
9733 cmc->tc = tc;
9734 cmc->im = *im;
9736 "Received message with size %u and flow control id %" PRIu64
9737 " via communicator from peer %s\n",
9738 ntohs (im->header.size),
9739 im->fc_id,
9740 GNUNET_i2s (&im->sender));
9741 cmc->im.neighbour_sender = cmc->im.sender;
9742 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
9744}
9745
9746
9755static int
9757{
9758 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
9759 (void) cls;
9760
9762 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
9763 ntohs (fc->header.size),
9764 ntohl (fc->size_of_addresses),
9765 ntohl (fc->number_of_addresses),
9766 sizeof(struct TransportFlowControlMessage),
9767 sizeof (struct TransportGlobalNattedAddress));
9768
9769 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
9771 + ntohl (fc->number_of_addresses) * sizeof (struct
9773 + ntohl (fc->size_of_addresses))
9774 return GNUNET_OK;
9775 else
9776 {
9777 GNUNET_break_op (0);
9778 return GNUNET_SYSERR;
9779 }
9780}
9781
9782
9783static struct GNUNET_TIME_Relative
9785{
9787 unsigned int n_hops = 0;
9788
9790 "calculate_rtt\n");
9791 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
9792 pos = pos->next_dv)
9793 {
9795 "calculate_rtt %lu\n",
9796 (unsigned long) pos->pd.aged_rtt.rel_value_us);
9797 n_hops++;
9799 aged_rtt, pos
9800 ->distance
9801 + 2), ret);
9802 }
9803
9804 GNUNET_assert (0 != n_hops);
9805
9806 return ret;
9807}
9808
9809
9810static void
9812 const struct GNUNET_PeerIdentity *pid,
9813 const char *uri)
9814{
9815 struct VirtualLink *vl = cls;
9816 const char *slash;
9817 char *address_uri;
9818 char *prefix;
9819 char *uri_without_port;
9820
9821 slash = strrchr (uri, '/');
9822 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
9823 GNUNET_assert (NULL != slash);
9824 slash++;
9825 GNUNET_asprintf (&address_uri,
9826 "%s-%s",
9827 prefix,
9828 slash);
9829
9830 uri_without_port = get_address_without_port (address_uri);
9832 "iterate_address_start_burst %s %s %s %s\n",
9833 uri_without_port,
9834 uri,
9835 address_uri,
9836 slash);
9837 if (0 == strcmp (uri_without_port, slash))
9838 {
9839 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
9840 );
9841 }
9842 else
9843 vl->burst_addr = NULL;
9844
9846 GNUNET_free (uri_without_port);
9847}
9848
9849
9850static void
9852 const struct GNUNET_PEERSTORE_Record *record,
9853 const char *emsg)
9854{
9855 struct GNUNET_StartBurstCls *sb_cls = cls;
9856 struct VirtualLink *vl = sb_cls->vl;
9857 struct GNUNET_MessageHeader *hello;
9859
9860 if (NULL != emsg)
9861 {
9863 "Got failure from PEERSTORE: %s\n",
9864 emsg);
9865 return;
9866 }
9867 if (NULL == record)
9868 {
9870 "Hello iteration end for %s\n",
9871 GNUNET_i2s (&vl->target));
9872 vl->ic = NULL;
9873 GNUNET_free (sb_cls);
9874 return;
9875 }
9876
9878 "check_for_burst_address\n");
9879 hello = record->value;
9883 vl);
9885
9887 GNUNET_free (sb_cls);
9888}
9889
9890
9891static void
9892burst_timeout (void *cls)
9893{
9895}
9896
9897
9898static void
9899start_burst (void *cls)
9900{
9901 struct GNUNET_StartBurstCls *sb_cls = cls;
9902 struct VirtualLink *vl = sb_cls->vl;
9903 struct GNUNET_TRANSPORT_StartBurst *sb;
9904 struct GNUNET_MQ_Envelope *env;
9905 char *uri_without_port = vl->burst_addr;
9906
9907 burst_task = NULL;
9908 /*char buf[strlen (uri_without_port) + 1];
9909
9910 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
9911 buf[strlen (uri_without_port)] = '\0';*/
9912 env =
9914 strlen (uri_without_port) + 1,
9916 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
9917 sb->pid = vl->target;
9918 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
9919 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
9920 {
9922 "iterate_address_start_burst client tc prefix %s\n",
9923 tc->details.communicator.address_prefix);
9924 if (CT_COMMUNICATOR != tc->type)
9925 continue;
9926 if (GNUNET_YES == tc->details.communicator.can_burst)
9927 {
9929 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
9930 uri_without_port,
9931 strlen (uri_without_port),
9932 ntohs (sb->header.size),
9933 (unsigned long) sb_cls->rtt.rel_value_us);
9934 GNUNET_MQ_send (tc->mq, env);
9938 60),
9940 NULL);
9941 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
9942 break;
9943 }
9944 }
9945 GNUNET_free (env);
9946 GNUNET_free (sb_cls);
9947}
9948
9949
9950static void
9951queue_burst (void *cls)
9952{
9953 struct GNUNET_StartBurstCls *sb_cls = cls;
9954 struct VirtualLink *vl = sb_cls->vl;
9955
9956 if (GNUNET_YES != use_burst)
9957 return;
9959 "burst_task %p ready %s burst addr %s (%p)\n",
9960 burst_task,
9961 sb_cls->sync_ready ? "yes" : "no",
9962 vl->burst_addr,
9963 vl->burst_addr);
9964 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
9965 {
9967 burst_task = NULL;
9969 return;
9970 }
9971 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
9972 )
9973 {
9975 &start_burst,
9976 sb_cls);
9977 }
9978 else if (NULL == vl->burst_addr)
9979 {
9981 "peerstore",
9982 &vl->target,
9985 sb_cls);
9986 }
9987}
9988
9989
9998static void
10000{
10001 struct CommunicatorMessageContext *cmc = cls;
10002 struct VirtualLink *vl;
10004 uint32_t seq;
10005 struct GNUNET_TIME_Absolute st;
10006 uint64_t os;
10007 uint64_t wnd;
10008 uint32_t random;
10009
10011 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10012 vl = lookup_virtual_link (&cmc->im.sender);
10013 if (NULL == vl)
10014 {
10015 vl = GNUNET_new (struct VirtualLink);
10017 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10018 vl,
10019 GNUNET_i2s (&cmc->im.sender));
10020 vl->burst_addr = NULL;
10021 vl->confirmed = GNUNET_NO;
10022 vl->message_uuid_ctr =
10024 vl->target = cmc->im.sender;
10030 links,
10031 &vl->target,
10032 vl,
10034 }
10035 if (NULL != vl->n)
10036 {
10037 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10038 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10039 }
10040
10042 "remaining %lu timeout for neighbour %p\n",
10043 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10044 rel_value_us,
10045 vl->n);
10046 if (NULL == vl->n ||
10047 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10048 {
10049 struct GNUNET_TIME_Relative rtt;
10050 struct GNUNET_BurstSync burst_sync;
10051 struct GNUNET_StartBurstCls *bcls;
10052
10053 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10054 bcls->vl = vl;
10055 vl->sb_cls = bcls;
10056 if (NULL != vl->dv)
10057 rtt = calculate_rtt (vl->dv);
10058 else
10060 burst_sync.rtt_average = fc->rtt;
10061 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10062 burst_sync.sync_ready = fc->sync_ready;
10063
10065 &burst_sync,
10066 &queue_burst,
10067 bcls);
10068 }
10069 if (0 != ntohl (fc->number_of_addresses))
10070 {
10071 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10072 const char *tgnas;
10073 unsigned int off = 0;
10074
10075 tgnas = (const char *) &fc[1];
10076
10077 for (int i = 1; i <= number_of_addresses; i++)
10078 {
10079 struct TransportGlobalNattedAddress *tgna;
10080 char *addr;
10081 unsigned int address_length;
10082
10083 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10084 addr = (char *) &tgna[1];
10085 address_length = ntohl (tgna->address_length);
10086 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10087
10089 "received address %s length %u\n",
10090 addr,
10091 ntohl (tgna->address_length));
10092
10093 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10094 }
10095 }
10097 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10098 {
10100 "FC dropped: Message out of order\n");
10101 /* out of order, drop */
10103 "# FC dropped: message out of order",
10104 1,
10105 GNUNET_NO);
10106 finish_cmc_handling (cmc);
10107 return;
10108 }
10109 seq = ntohl (fc->seq);
10110 if (seq < vl->last_fc_seq)
10111 {
10112 /* Wrap-around/reset of other peer; start all counters from zero */
10114 }
10115 vl->last_fc_seq = seq;
10116 vl->last_fc_timestamp = st;
10120 (int64_t) (os - vl->incoming_fc_window_size_used);
10122 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10123 GNUNET_i2s (&vl->target),
10124 (unsigned int) seq,
10125 (unsigned long long) vl->outbound_fc_window_size,
10126 (long long) vl->incoming_fc_window_size_loss);
10129 UINT32_MAX);
10130 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10134 != wnd) ||
10135 (0 == random
10137 {
10139 "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",
10140 (unsigned long long) wnd,
10141 (unsigned long long) vl->incoming_fc_window_size,
10142 (unsigned long long) vl->last_outbound_window_size_received,
10145 }
10146 if ((wnd == vl->incoming_fc_window_size
10150 (NULL != vl->fc_retransmit_task))
10151 {
10153 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10154 GNUNET_i2s (&vl->target),
10155 (unsigned long long) wnd);
10157 vl->fc_retransmit_task = NULL;
10158 vl->fc_retransmit_count = 0;
10159 }
10161 /* FC window likely increased, check transmission possibilities! */
10163 finish_cmc_handling (cmc);
10164}
10165
10166
10174static void
10176{
10178 { GNUNET_MQ_hd_var_size (fragment_box,
10181 cmc),
10182 GNUNET_MQ_hd_var_size (reliability_box,
10185 cmc),
10186 GNUNET_MQ_hd_var_size (reliability_ack,
10189 cmc),
10190 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10193 cmc),
10194 GNUNET_MQ_hd_var_size (dv_learn,
10197 cmc),
10198 GNUNET_MQ_hd_var_size (dv_box,
10200 struct TransportDVBoxMessage,
10201 cmc),
10202 GNUNET_MQ_hd_var_size (flow_control,
10205 cmc),
10207 validation_challenge,
10210 cmc),
10212 validation_response,
10215 cmc),
10217 int ret;
10218 const struct GNUNET_MessageHeader *msg = cmc->mh;
10219
10221 "Handling message of type %u with %u bytes\n",
10222 (unsigned int) ntohs (msg->type),
10223 (unsigned int) ntohs (msg->size));
10225 if (GNUNET_SYSERR == ret)
10226 {
10227 GNUNET_break (0);
10229 GNUNET_free (cmc);
10230 return;
10231 }
10232 if (GNUNET_NO == ret)
10233 {
10234 /* unencapsulated 'raw' message */
10235 handle_raw_message (cmc, msg);
10236 }
10237}
10238
10239
10246static int
10248 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10249{
10250 struct TransportClient *tc = cls;
10251
10252 if (CT_COMMUNICATOR != tc->type)
10253 {
10254 GNUNET_break (0);
10255 return GNUNET_SYSERR;
10256 }
10258 return GNUNET_OK;
10259}
10260
10261
10267static void
10269{
10270 if (pm->msg_uuid_set)
10271 return;
10272 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10273 pm->msg_uuid_set = GNUNET_YES;
10274}
10275
10276
10285static struct PendingAcknowledgement *
10287 struct DistanceVectorHop *dvh,
10288 struct PendingMessage *pm)
10289{
10290 struct PendingAcknowledgement *pa;
10291
10292 pa = GNUNET_new (struct PendingAcknowledgement);
10293 pa->queue = queue;
10294 pa->dvh = dvh;
10295 pa->pm = pm;
10296 do
10297 {
10299 &pa->ack_uuid,
10300 sizeof(pa->ack_uuid));
10301 }
10304 &pa->ack_uuid.value,
10305 pa,
10307 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10308 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10309 if (NULL != dvh)
10312 pa->message_size = pm->bytes_msg;
10314 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10316 pm->logging_uuid);
10317 return pa;
10318}
10319
10320
10332static struct PendingMessage *
10334 struct DistanceVectorHop *dvh,
10335 struct PendingMessage *pm)
10336{
10337 struct PendingAcknowledgement *pa;
10338 struct PendingMessage *ff;
10339 uint16_t mtu;
10340 uint16_t msize;
10341
10342 mtu = (UINT16_MAX == queue->mtu)
10343 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10344 : queue->mtu;
10346 "Fragmenting message <%" PRIu64
10347 "> with size %u to %s for MTU %u\n",
10348 pm->logging_uuid,
10349 pm->bytes_msg,
10350 GNUNET_i2s (&pm->vl->target),
10351 (unsigned int) mtu);
10354 "Fragmenting message %" PRIu64 " <%" PRIu64
10355 "> with size %u to %s for MTU %u\n",
10356 pm->msg_uuid.uuid,
10357 pm->logging_uuid,
10358 pm->bytes_msg,
10359 GNUNET_i2s (&pm->vl->target),
10360 (unsigned int) mtu);
10361
10362 /* This invariant is established in #handle_add_queue_message() */
10363 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10364
10365 /* select fragment for transmission, descending the tree if it has
10366 been expanded until we are at a leaf or at a fragment that is small
10367 enough
10368 */
10369 ff = pm;
10370 msize = ff->bytes_msg;
10371
10372 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10373 (ff->frag_off == msize) && (NULL != ff->head_frag))
10374 {
10375 ff = ff->head_frag; /* descent into fragmented fragments */
10376 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10377 }
10378
10379 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10380 {
10381 /* Did not yet calculate all fragments, calculate next fragment */
10382 struct PendingMessage *frag;
10383 struct TransportFragmentBoxMessage tfb;
10384 const char *orig;
10385 char *msg;
10386 uint16_t fragmax;
10387 uint16_t fragsize;
10388 uint16_t msize_ff;
10389 uint16_t xoff = 0;
10390 pm->frag_count++;
10391
10392 orig = (const char *) &ff[1];
10393 msize_ff = ff->bytes_msg;
10394 if (pm != ff)
10395 {
10396 const struct TransportFragmentBoxMessage *tfbo;
10397
10398 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10399 orig += sizeof(struct TransportFragmentBoxMessage);
10400 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10401 xoff = ntohs (tfbo->frag_off);
10402 }
10403 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10404 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10405 frag =
10406 GNUNET_malloc (sizeof(struct PendingMessage)
10407 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10409 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10410 frag,
10411 ff,
10412 pm->vl,
10413 pm);
10415 frag->vl = pm->vl;
10416 frag->frag_parent = ff;
10417 frag->timeout = pm->timeout;
10418 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10419 frag->pmt = PMT_FRAGMENT_BOX;
10420 msg = (char *) &frag[1];
10422 tfb.header.size =
10423 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10424 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10425 tfb.ack_uuid = pa->ack_uuid;
10426 tfb.msg_uuid = pm->msg_uuid;
10427 tfb.frag_off = htons (ff->frag_off + xoff);
10428 tfb.msg_size = htons (pm->bytes_msg);
10429 memcpy (msg, &tfb, sizeof(tfb));
10430 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10432 ff->tail_frag, frag);
10433 ff->frag_off += fragsize;
10434 ff = frag;
10435 }
10436
10437 /* Move head to the tail and return it */
10441 ff);
10445 ff);
10446
10447 return ff;
10448}
10449
10450
10463static struct PendingMessage *
10465 struct DistanceVectorHop *dvh,
10466 struct PendingMessage *pm)
10467{
10469 struct PendingAcknowledgement *pa;
10470 struct PendingMessage *bpm;
10471 char *msg;
10472
10473 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10474 return pm; /* already fragmented or reliability boxed, or control message:
10475 do nothing */
10476 if (NULL != pm->bpm)
10477 return pm->bpm; /* already computed earlier: do nothing */
10478 // TODO I guess we do not need this assertion. We might have a DLL with
10479 // fragments, because the MTU changed, and we do not need to fragment anymore.
10480 // But we should keep the fragments until message was completed, because
10481 // the MTU might change again.
10482 // GNUNET_assert (NULL == pm->head_frag);
10483 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10484 {
10485 /* failed hard */
10486 GNUNET_break (0);
10488 return NULL;
10489 }
10490
10492
10493 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10494 + pm->bytes_msg);
10496 "4 created pm %p storing vl %p from pm %p\n",
10497 bpm,
10498 pm->vl,
10499 pm);
10501 bpm->vl = pm->vl;
10502 bpm->frag_parent = pm;
10503 // Why was this needed?
10504 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10505 bpm->timeout = pm->timeout;
10507 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10510 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10511 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10512
10513 rbox.ack_uuid = pa->ack_uuid;
10514 msg = (char *) &bpm[1];
10515 memcpy (msg, &rbox, sizeof(rbox));
10516 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10517 pm->bpm = bpm;
10519 "Preparing reliability box for message <%" PRIu64
10520 "> of size %d (%d) to %s on queue %s\n",
10521 pm->logging_uuid,
10522 pm->bytes_msg,
10523 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10524 GNUNET_i2s (&pm->vl->target),
10525 queue->address);
10526 return bpm;
10527}
10528
10529
10530static void
10533{
10534 struct VirtualLink *vl = pm->vl;
10535 struct PendingMessage *pos;
10536
10537 /* re-insert sort in neighbour list */
10541 pm);
10542 pos = vl->pending_msg_tail;
10543 while ((NULL != pos) &&
10545 pos = pos->prev_vl;
10549 pos,
10550 pm);
10551}
10552
10553
10554static unsigned int
10556{
10557 struct PendingMessage *pos;
10559
10560 pos = pm->head_frag;
10561 while (NULL != pos)
10562 {
10563 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10564 GNUNET_NO == check_next_attempt_tree (pos, root))
10566 else
10567 {
10569 break;
10570 }
10571 pos = pos->next_frag;
10572 }
10573
10574 return frags_in_flight;
10575}
10576
10577
10578static void
10580{
10581 struct PendingMessage *pos;
10582
10583 pos = pm->head_frag;
10584 while (NULL != pos)
10585 {
10586 pos->frags_in_flight_round = pm->frags_in_flight_round;
10588 pos = pos->next_frag;
10589 }
10590}
10591
10592
10601static void
10604{
10605 if (NULL == pm->frag_parent)
10606 {
10607 pm->next_attempt = next_attempt;
10609 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
10610 pm->logging_uuid,
10613 }
10614 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
10615 {
10616 struct PendingMessage *root = pm->frag_parent;
10617
10618 while (NULL != root->frag_parent)
10619 root = root->frag_parent;
10621 "Next attempt for root message <%" PRIu64 "> set to %s\n",
10622 root->logging_uuid,
10624 root->next_attempt = next_attempt;
10626 }
10627 else
10628 {
10629 struct PendingMessage *root = pm->frag_parent;
10630
10631 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10632 root = root->frag_parent;
10633
10635 "frag_count next attempt %u\n",
10636 root->frag_count);
10637
10638 if (GNUNET_NO == root->frags_in_flight)
10639 {
10640 root->next_attempt = next_attempt;
10642 root->frags_in_flight_round++;
10644 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
10645 ">)set to %" PRIu64 "\n",
10646 pm->logging_uuid,
10647 root->logging_uuid,
10649 }
10650
10651 pm->next_attempt = root->next_attempt;
10652 pm->frags_in_flight_round = root->frags_in_flight_round;
10654
10655 if (root->bytes_msg == root->frag_off)
10656 root->frags_in_flight = check_next_attempt_tree (root, root);
10657 else
10659
10660 if (GNUNET_NO == root->frags_in_flight)
10661 {
10663 "We have no fragments in flight for message %" PRIu64
10664 ", reorder root! Next attempt is %" PRIu64 "\n",
10665 root->logging_uuid,
10667 if (PMT_DV_BOX == root->pmt)
10668 root = root->frag_parent;
10669 reorder_root_pm (root, root->next_attempt);
10670 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
10671 }
10672 else
10673 {
10674 double factor = ((double) root->frag_count - 1)
10675 / (double) root->frag_count;
10676 struct GNUNET_TIME_Relative s1;
10677 struct GNUNET_TIME_Relative s2;
10678 struct GNUNET_TIME_Relative plus_mean =
10681 next_attempt);
10682
10684 "frag_count %u after factor\n",
10685 root->frag_count);
10687 factor);
10688 s2 = GNUNET_TIME_relative_divide (plus,
10689 root->frag_count);
10690 plus_mean = GNUNET_TIME_relative_add (s1, s2);
10693 "We have fragments in flight for message %" PRIu64
10694 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
10695 root->logging_uuid,
10697 }
10698 }
10699}
10700
10701
10706{
10711
10716
10721
10726
10730 int frag;
10731
10735 int relb;
10736
10741
10745 unsigned int frags_in_flight;
10746
10751};
10752
10753
10765static void
10767 struct Queue *queue,
10768 struct VirtualLink *vl,
10769 struct DistanceVectorHop *dvh,
10770 size_t overhead)
10771{
10772 struct GNUNET_TIME_Absolute now;
10773
10774 now = GNUNET_TIME_absolute_get ();
10775 sc->to_early = GNUNET_NO;
10776 sc->frags_in_flight = GNUNET_NO;
10777 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
10778 pos = pos->next_vl)
10779 {
10780 size_t real_overhead = overhead;
10781 int frag;
10782 int relb;
10783
10784 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
10785 {
10787 "DV messages must not be DV-routed to next hop!\n");
10788 continue; /* DV messages must not be DV-routed to next hop! */
10789 }
10790 if (pos->next_attempt.abs_value_us > now.abs_value_us)
10791 {
10792 if (GNUNET_YES == pos->frags_in_flight)
10793 {
10794 sc->frags_in_flight = GNUNET_YES;
10796 "Fragments in flight for message %" PRIu64 "\n",
10797 pos->logging_uuid);
10798 }
10799 else
10800 {
10802 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
10803 PRIu64 "\n",
10804 pos->logging_uuid);
10805 sc->to_early = GNUNET_YES;
10806 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
10807 pos->next_attempt);
10808 continue;
10809 }
10810 // break; /* too early for all messages, they are sorted by next_attempt */
10811 }
10812 if (NULL != pos->qe)
10813 {
10815 "not eligible\n");
10816 continue; /* not eligible */
10817 }
10818 sc->consideration_counter++;
10819 /* determine if we have to fragment, if so add fragmentation
10820 overhead! */
10822 "check %" PRIu64 " for sc->best\n",
10823 pos->logging_uuid);
10824 frag = GNUNET_NO;
10825 if (((0 != queue->mtu) &&
10826 (pos->bytes_msg + real_overhead > queue->mtu)) ||
10827 (pos->bytes_msg > UINT16_MAX - sizeof(struct
10829 ||
10830 (NULL != pos->head_frag /* fragments already exist, should
10831 respect that even if MTU is UINT16_MAX for
10832 this queue */))
10833 {
10835 "fragment msg with size %u, realoverhead is %lu\n",
10836 pos->bytes_msg,
10837 real_overhead);
10838 frag = GNUNET_YES;
10839 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
10840 {
10841 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
10842 header without the ACK UUID when using a *reliable* channel! */
10843 }
10844 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10845 }
10846 /* determine if we have to reliability-box, if so add reliability box
10847 overhead */
10848 relb = GNUNET_NO;
10849 if ((GNUNET_NO == frag) &&
10850 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
10851 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
10852 {
10853 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
10854
10855 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
10856 {
10857 frag = GNUNET_YES;
10858 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
10859 }
10860 else
10861 {
10862 relb = GNUNET_YES;
10863 }
10865 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
10866 pos->bytes_msg,
10867 real_overhead,
10868 queue->mtu,
10869 frag,
10870 relb);
10871 }
10872
10873 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
10874 message would beat it! */
10875 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
10876 {
10877 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
10878 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
10879 experimentally validated. There may be some huge potential for
10880 improvement here. Also, we right now only compare how well the
10881 given message fits _this_ queue, and do not consider how well other
10882 queues might suit the message. Taking other queues into consideration
10883 may further improve the result, but could also be expensive
10884 in terms of CPU time. */
10885 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
10886 long long pm_score = frag * 40 + relb * 20 + real_overhead;
10887 long long time_delta =
10888 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
10889 / 1000LL;
10890
10891 /* "time_delta" considers which message has been 'ready' for transmission
10892 for longer, if a message has a preference for low latency, increase
10893 the weight of the time_delta by 10x if it is favorable for that message */
10894 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10895 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
10896 time_delta *= 10; /* increase weight (always, both are low latency) */
10897 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10898 (time_delta > 0))
10899 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
10900 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
10901 (time_delta < 0))
10902 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
10903 if (0 != queue->mtu)
10904 {
10905 /* Grant bonus if we are below MTU, larger bonus the closer we will
10906 be to the MTU */
10907 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
10908 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
10909 if (queue->mtu > real_overhead + pos->bytes_msg)
10910 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
10911 }
10912 if (sc_score + time_delta > pm_score)
10913 {
10915 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
10916 "\n",
10917 pos->logging_uuid,
10918 sc->best->logging_uuid);
10919 continue; /* sc_score larger, keep sc->best */
10920 }
10921 }
10922 sc->best = pos;
10923 sc->dvh = dvh;
10924 sc->frag = frag;
10925 sc->relb = relb;
10926 sc->real_overhead = real_overhead;
10927 }
10928}
10929
10930
10941static void
10943 struct Neighbour *next_hop,
10944 const struct GNUNET_MessageHeader *hdr,
10946{
10947 struct PendingMessageScoreContext *sc = cls;
10948 struct PendingMessage *pm = sc->best;
10949 struct PendingMessage *bpm;
10950 uint16_t bsize = ntohs (hdr->size);
10951
10952 GNUNET_assert (NULL == pm->bpm);
10953 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
10955 "5 created pm %p storing vl %p from pm %p\n",
10956 bpm,
10957 pm->vl,
10958 pm);
10960 bpm->pmt = PMT_DV_BOX;
10961 bpm->vl = pm->vl;
10962 bpm->timeout = pm->timeout;
10963 bpm->bytes_msg = bsize;
10964 bpm->frag_parent = pm;
10967 "Creating DV Box %" PRIu64 " for original message %" PRIu64
10968 " (next hop is %s)\n",
10970 pm->logging_uuid,
10971 GNUNET_i2s (&next_hop->pid));
10972 memcpy (&bpm[1], hdr, bsize);
10973 pm->bpm = bpm;
10974}
10975
10976
10992static void
10994{
10995 struct Queue *queue = cls;
10996 struct Neighbour *n = queue->neighbour;
10998 struct PendingMessage *pm;
10999
11000 queue->transmit_task = NULL;
11001 if (NULL == n->vl)
11002 {
11004 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11005 GNUNET_i2s (&n->pid),
11006 queue->address);
11007 queue->idle = GNUNET_YES;
11008 return;
11009 }
11010 memset (&sc, 0, sizeof(sc));
11011 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11012 if (NULL == sc.best)
11013 {
11014 /* Also look at DVH that have the n as first hop! */
11015 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11016 dvh = dvh->next_neighbour)
11017 {
11019 queue,
11020 dvh->dv->vl,
11021 dvh,
11022 sizeof(struct GNUNET_PeerIdentity)
11023 * (1 + dvh->distance)
11024 + sizeof(struct TransportDVBoxMessage)
11025 + sizeof(struct TransportDVBoxPayloadP));
11026 }
11027 }
11028 if (NULL == sc.best)
11029 {
11030 /* no message pending, nothing to do here! */
11032 "No pending messages, queue `%s' to %s now idle\n",
11033 queue->address,
11034 GNUNET_i2s (&n->pid));
11035 if (GNUNET_YES == sc.to_early)
11036 schedule_transmit_on_queue (sc.to_early_retry_delay,
11037 queue,
11039 queue->idle = GNUNET_YES;
11040 return;
11041 }
11042 /* There is a message pending, we are certainly not idle */
11043 queue->idle = GNUNET_NO;
11044
11045 /* Given selection in `sc`, do transmission */
11046 pm = sc.best;
11048 "Selected message <%" PRIu64 ">\n",
11049 pm->logging_uuid);
11050 if (NULL != sc.dvh)
11051 {
11053 "Is this %u a DV box?\n",
11054 pm->pmt);
11055 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11056 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11057 {
11059 "Discard old box, because we have a new DV path.\n");
11060 free_pending_message (sc.best->bpm);
11061 sc.best->bpm = NULL;
11062 }
11063
11064 if (NULL == sc.best->bpm)
11065 {
11067 "encapsulate_for_dv 2\n");
11068 encapsulate_for_dv (sc.dvh->dv,
11069 1,
11070 &sc.dvh,
11071 (const struct GNUNET_MessageHeader *) &sc.best[1],
11073 &sc,
11074 RMO_NONE,
11075 GNUNET_NO);
11076 GNUNET_assert (NULL != sc.best->bpm);
11078 "%lu %lu %lu %lu %u\n",
11079 sizeof(struct GNUNET_PeerIdentity),
11080 sizeof(struct TransportDVBoxMessage),
11081 sizeof(struct TransportDVBoxPayloadP),
11082 sizeof(struct TransportFragmentBoxMessage),
11083 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11084 sc.best->bpm->used_dvh = sc.dvh;
11085 }
11086 pm = sc.best->bpm;
11087 }
11088 if (GNUNET_YES == sc.frag)
11089 {
11090 pm = fragment_message (queue, sc.dvh, pm);
11091 if (NULL == pm)
11092 {
11094 "Fragmentation failed queue %s to %s for <%" PRIu64
11095 ">, trying again\n",
11096 queue->address,
11097 GNUNET_i2s (&n->pid),
11098 sc.best->logging_uuid);
11100 queue,
11102 return;
11103 }
11104 }
11105 else if (GNUNET_YES == sc.relb)
11106 {
11108 if (NULL == pm)
11109 {
11110 /* Reliability boxing failed, try next message... */
11111 GNUNET_log (
11113 "Reliability boxing failed queue %s to %s for <%" PRIu64
11114 ">, trying again\n",
11115 queue->address,
11116 GNUNET_i2s (&n->pid),
11117 sc.best->logging_uuid);
11119 queue,
11121 return;
11122 }
11123 }
11124
11125 /* Pass 'pm' for transission to the communicator */
11126 GNUNET_log (
11128 "Passing message <%" PRIu64
11129 "> to queue %s for peer %s (considered %u others)\n",
11130 pm->logging_uuid,
11131 queue->address,
11132 GNUNET_i2s (&n->pid),
11133 sc.consideration_counter);
11134
11135 /* Flow control: increment amount of traffic sent; if we are routing
11136 via DV (and thus the ultimate target of the pending message is for
11137 a different virtual link than the one of the queue), then we need
11138 to use up not only the window of the direct link but also the
11139 flow control window for the DV link! */
11140 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11141
11142 if (pm->vl != queue->neighbour->vl)
11143 {
11144 /* If the virtual link of the queue differs, this better be distance
11145 vector routing! */
11146 GNUNET_assert (NULL != sc.dvh);
11147 /* If we do distance vector routing, we better not do this for a
11148 message that was itself DV-routed */
11149 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11150 /* We use the size of the unboxed message here, to avoid counting
11151 the DV-Box header which is eaten up on the way by intermediaries */
11152 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11153 }
11154 else
11155 {
11156 GNUNET_assert (NULL == sc.dvh);
11157 }
11158
11159 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11160
11161 /* Check if this transmission somehow conclusively finished handing 'pm'
11162 even without any explicit ACKs */
11163 if ((PMT_CORE == pm->pmt) ||
11164 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11165 {
11167 }
11168 else
11169 {
11170 struct GNUNET_TIME_Relative wait_duration;
11171 unsigned int wait_multiplier;
11172
11173 if (PMT_FRAGMENT_BOX == pm->pmt)
11174 {
11175 struct PendingMessage *root;
11176
11177 root = pm->frag_parent;
11178 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11179 root = root->frag_parent;
11180
11181 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11182 / ((double) root->frag_off
11183 / (double) root->frag_count))
11184 * 4;
11185 }
11186 else
11187 {
11188 // No fragments, we use 4 RTT before retransmitting.
11189 wait_multiplier = 4;
11190 }
11191
11192 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11193 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11194
11196 "Wait multiplier %u\n",
11197 wait_multiplier);
11198
11199 /* Message not finished, waiting for acknowledgement.
11200 Update time by which we might retransmit 's' based on queue
11201 characteristics (i.e. RTT); it takes one RTT for the message to
11202 arrive and the ACK to come back in the best case; but the other
11203 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11204 retransmitting.
11205
11206 OPTIMIZE: Note that in the future this heuristic should likely
11207 be improved further (measure RTT stability, consider message
11208 urgency and size when delaying ACKs, etc.) */
11209
11210 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11211 queue->pd.aged_rtt.rel_value_us)
11212 wait_duration = queue->pd.aged_rtt;
11213 else
11214 {
11215 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11216 wait_multiplier = 4;
11217 }
11218 {
11221 wait_duration, wait_multiplier));
11223 wait_duration, wait_multiplier);
11225 "Waiting %s for ACK until %s\n",
11230 GNUNET_TIME_relative_multiply (wait_duration,
11231 wait_multiplier))
11232 );
11233 }
11234 }
11235 /* finally, re-schedule queue transmission task itself */
11237 queue,
11239}
11240
11241
11248static void
11250 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11251{
11252 struct TransportClient *tc = cls;
11253
11254 if (CT_COMMUNICATOR != tc->type)
11255 {
11256 GNUNET_break (0);
11258 return;
11259 }
11260 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11261 queue = queue->next_client)
11262 {
11263 struct Neighbour *neighbour = queue->neighbour;
11264
11265 if ((ntohl (dqm->qid) != queue->qid) ||
11266 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11267 continue;
11269 "Dropped queue %s to peer %s\n",
11270 queue->address,
11271 GNUNET_i2s (&neighbour->pid));
11272 free_queue (queue);
11274 return;
11275 }
11276 GNUNET_break (0);
11278}
11279
11280
11281static void
11283 struct TransportClient *tc)
11284{
11285 struct PendingMessage *pm;
11286
11287 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11288 qe->queue->queue_tail,
11289 qe);
11290 qe->queue->queue_length--;
11291 tc->details.communicator.total_queue_length--;
11293 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11294 qe->queue->address,
11295 qe->queue->qid,
11296 GNUNET_i2s (&qe->queue->neighbour->pid),
11297 qe->queue->queue_length,
11298 tc->details.communicator.total_queue_length);
11299
11300 /* if applicable, resume transmissions that waited on ACK */
11302 tc->details.communicator.total_queue_length)
11303 {
11304 /* Communicator dropped below threshold, resume all queues
11305 incident with this client! */
11307 GST_stats,
11308 "# Transmission throttled due to communicator queue limit",
11309 -1,
11310 GNUNET_NO);
11311 for (struct Queue *queue = tc->details.communicator.queue_head;
11312 NULL != queue;
11313 queue = queue->next_client)
11314 {
11316 queue,
11318 }
11319 }
11320 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11321 {
11322 /* queue dropped below threshold; only resume this one queue */
11324 "# Transmission throttled due to queue queue limit",
11325 -1,
11326 GNUNET_NO);
11328 qe->queue,
11330 }
11331 else if (1 == qe->queue->q_capacity)
11332 {
11333 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11335 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11336 PRIu64 ".\n",
11337 qe->queue->qid,
11338 qe->queue->q_capacity);
11339 /* message queue has capacity; only resume this one queue */
11340 /* queue dropped below threshold; only resume this one queue */
11342 "# Transmission throttled due to message queue capacity",
11343 -1,
11344 GNUNET_NO);
11346 qe->queue,
11348 }
11349
11350 if (NULL != (pm = qe->pm))
11351 {
11352 struct VirtualLink *vl;
11353
11354 // GNUNET_assert (qe == pm->qe);
11355 pm->qe = NULL;
11356 /* If waiting for this communicator may have blocked transmission
11357 of pm on other queues for this neighbour, force schedule
11358 transmit on queue for queues of the neighbour */
11359 if (NULL == pm->frag_parent)
11360 {
11361 vl = pm->vl;
11362 if ((NULL != vl) &&
11363 (NULL != vl->pending_msg_head) &&
11364 (vl->pending_msg_head == pm))
11366 }
11367 }
11368 GNUNET_free (qe);
11369}
11370
11371
11378static void
11380 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11381{
11382 struct TransportClient *tc = cls;
11383 struct QueueEntry *qe;
11384
11385 if (CT_COMMUNICATOR != tc->type)
11386 {
11387 GNUNET_break (0);
11389 return;
11390 }
11391
11392 /* find our queue entry matching the ACK */
11393 qe = NULL;
11395 "Looking for queue for PID %s\n",
11396 GNUNET_i2s (&sma->receiver));
11397 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11398 queue = queue->next_client)
11399 {
11400 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11401 continue;
11403 "Found PID %s\n",
11404 GNUNET_i2s (&queue->neighbour->pid));
11405
11406
11407 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11408 qep = qep->next)
11409 {
11410 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11411 sma->qid))
11412 continue;
11414 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11415 PRIu64 " Ack QID %u\n",
11416 qep->mid,
11417 queue->qid,
11418 GNUNET_ntohll (sma->mid),
11419 ntohl (sma->qid));
11420 qe = qep;
11421 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11423 "For pending message %" PRIu64 " we had retransmissions.\n",
11424 qe->pm->logging_uuid);
11425 break;
11426 }
11427 }
11428 if (NULL == qe)
11429 {
11431 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11432 GNUNET_ntohll (sma->mid),
11433 ntohl (sma->qid));
11434 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11435 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11436 /* this should never happen */
11437 // GNUNET_break (0);
11438 // GNUNET_SERVICE_client_drop (tc->client);
11440 return;
11441 }
11444}
11445
11446
11452static void
11454{
11456}
11457
11458
11468static int
11470 const struct GNUNET_PeerIdentity *pid,
11471 void *value)
11472{
11473 struct TransportClient *tc = cls;
11474 struct Neighbour *neighbour = value;
11475
11476 GNUNET_assert (CT_MONITOR == tc->type);
11477 for (struct Queue *q = neighbour->queue_head; NULL != q;
11478 q = q->next_neighbour)
11479 {
11480 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11481 .cs = q->cs,
11482 .num_msg_pending = q->num_msg_pending,
11483 .num_bytes_pending = q->num_bytes_pending };
11484
11485 notify_monitor (tc, pid, q->address, q->nt, &me);
11486 }
11487 return GNUNET_OK;
11488}
11489
11490
11497static void
11500{
11501 struct TransportClient *tc = cls;
11502
11503 if (CT_NONE != tc->type)
11504 {
11505 GNUNET_break (0);
11507 return;
11508 }
11509 tc->type = CT_MONITOR;
11510 tc->details.monitor.peer = start->peer;
11511 tc->details.monitor.one_shot = ntohl (start->one_shot);
11515}
11516
11517
11525static struct TransportClient *
11527{
11528 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11529 {
11530 if (CT_COMMUNICATOR != tc->type)
11531 continue;
11532 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11533 return tc;
11534 }
11535 GNUNET_log (
11537 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11538 prefix);
11539 return NULL;
11540}
11541
11542
11550static void
11552{
11553 static uint32_t idgen;
11554 struct TransportClient *tc;
11555 char *prefix;
11556 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11557 struct GNUNET_MQ_Envelope *env;
11558 size_t alen;
11559
11561 if (NULL == prefix)
11562 {
11563 GNUNET_break (0); /* We got an invalid address!? */
11564 return;
11565 }
11567 if (NULL == tc)
11568 {
11570 "# Suggestions ignored due to missing communicator",
11571 1,
11572 GNUNET_NO);
11574 "Cannot connect to %s at `%s', no matching communicator present\n",
11575 GNUNET_i2s (pid),
11576 address);
11578 return;
11579 }
11580 /* forward suggestion for queue creation to communicator */
11582 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11583 (unsigned int) idgen,
11584 prefix,
11585 GNUNET_i2s (pid),
11586 address);
11588 alen = strlen (address) + 1;
11589 env =
11591 cqm->request_id = htonl (idgen++);
11592 cqm->receiver = *pid;
11593 memcpy (&cqm[1], address, alen);
11594 GNUNET_MQ_send (tc->mq, env);
11595}
11596
11597
11605static void
11607{
11609 struct GNUNET_TIME_Absolute monotonic_time;
11610
11611 if (NULL != vs->revalidation_task)
11612 {
11613 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
11614 vs->revalidation_task = NULL;
11615 }
11616 /*memcpy (&hkey,
11617 &hc,
11618 sizeof (hkey));*/
11620 "Remove key %s for address %s map size %u contains %u\n",
11621 GNUNET_h2s (&vs->hc),
11622 vs->address,
11625 &vs->hc));
11627
11629 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
11630 vs->last_challenge_use.abs_value_us)
11631 {
11632 vs->first_challenge_use = monotonic_time;
11633 }
11634 vs->last_challenge_use = monotonic_time;
11635 tvc.header.type =
11637 tvc.header.size = htons (sizeof(tvc));
11638 tvc.reserved = htonl (0);
11639 tvc.challenge = vs->challenge;
11640 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
11642 "Sending address validation challenge %s to %s\n",
11644 GNUNET_i2s (&q->neighbour->pid));
11645 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
11646}
11647
11648
11654static void
11656{
11657 struct ValidationState *vs;
11658 struct Queue *q;
11660 GST_cfg);
11661
11662 (void) cls;
11663 validation_task = NULL;
11665 /* drop validations past their expiration */
11666 while (
11667 (NULL != vs) &&
11669 {
11671 "Validation response %s cleaned up\n",
11672 GNUNET_sh2s (&vs->challenge.value));
11675 }
11676 if (NULL == vs)
11677 {
11679 "Address validation task not scheduled anymore, nothing to do\n");
11680 return; /* woopsie, no more addresses known, should only
11681 happen if we're really a lonely peer */
11682 }
11683 q = find_queue (&vs->pid, vs->address);
11684 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
11685 {
11687 "To early to start next address validation for challenge %s\n",
11688 GNUNET_sh2s (&vs->challenge.value));
11689 return;
11690 }
11691 if (NULL == q)
11692 {
11693 vs->awaiting_queue = GNUNET_YES;
11694 suggest_to_connect (&vs->pid, vs->address);
11695 }
11696 else
11698 /* Finally, reschedule next attempt */
11699 vs->challenge_backoff =
11700 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
11703 "Address validation task will run again in %s\n",
11704 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
11705 GNUNET_YES));
11708 vs->challenge_backoff));
11709}
11710
11711
11716{
11720 struct Queue *q;
11721
11725 unsigned int quality_count;
11726
11730 unsigned int num_queues;
11731
11736 unsigned int k;
11737};
11738
11739
11751static int
11753 const struct GNUNET_PeerIdentity *pid,
11754 void *value)
11755{
11756 struct QueueQualityContext *ctx = cls;
11757 struct Neighbour *n = value;
11758 int do_inc;
11759
11760 (void) pid;
11761 do_inc = GNUNET_NO;
11762 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
11763 {
11764 ctx->num_queues++;
11765 if (0 == ctx->k--)
11766 ctx->q = q;
11767 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
11768 statistics and consider those as well here? */
11769 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
11770 do_inc = GNUNET_YES;
11771 }
11772 if (GNUNET_YES == do_inc)
11773 ctx->quality_count++;
11774 return GNUNET_OK;
11775}
11776
11777
11789static void
11791{
11792 struct LearnLaunchEntry *lle;
11793 struct QueueQualityContext qqc;
11794 struct TransportDVLearnMessage dvl;
11795
11796 (void) cls;
11797 dvlearn_task = NULL;
11799 return; /* lost all connectivity, cannot do learning */
11800 qqc.quality_count = 0;
11801 qqc.num_queues = 0;
11805 &qqc);
11807 {
11808 struct GNUNET_TIME_Relative delay;
11809 unsigned int factor;
11810
11811 /* scale our retries by how far we are above the threshold */
11815 "At connection quality %u, will launch DV learn in %s\n",
11816 qqc.quality_count,
11819 return;
11820 }
11821 /* remove old entries in #dvlearn_map if it has grown too big */
11822 while (MAX_DV_LEARN_PENDING <=
11824 {
11825 lle = lle_tail;
11828 &lle->challenge.value,
11829 lle));
11831 GNUNET_free (lle);
11832 }
11833 /* setup data structure for learning */
11834 lle = GNUNET_new (struct LearnLaunchEntry);
11836 &lle->challenge,
11837 sizeof(lle->challenge));
11839 "Starting launch DV learn with challenge %s\n",
11840 GNUNET_sh2s (&lle->challenge.value));
11845 &lle->challenge.value,
11846 lle,
11849 dvl.header.size = htons (sizeof(dvl));
11850 dvl.num_hops = htons (0);
11851 dvl.bidirectional = htons (0);
11853 dvl.monotonic_time =
11855 {
11856 struct DvInitPS dvip = {
11857 .purpose.purpose = htonl (
11859 .purpose.size = htonl (sizeof(dvip)),
11860 .monotonic_time = dvl.monotonic_time,
11861 .challenge = lle->challenge
11862 };
11863
11865 &dvip,
11866 &dvl.init_sig);
11867 }
11869 dvl.challenge = lle->challenge;
11870
11871 qqc.quality_count = 0;
11873 qqc.num_queues = 0;
11874 qqc.q = NULL;
11877 &qqc);
11878 GNUNET_assert (NULL != qqc.q);
11879
11880 /* Do this as close to transmission time as possible! */
11882
11883 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
11884 /* reschedule this job, randomizing the time it runs (but no
11885 actual backoff!) */
11889 NULL);
11890}
11891
11892
11900static char *
11902{
11903 const char *colon;
11904 char *colon_rest;
11905 size_t colon_rest_length;
11906 char *address_without_port;
11907
11908 colon = strchr (address,':');
11909 colon_rest = GNUNET_strndup (address, colon - address);
11910 colon_rest_length = strlen (colon_rest);
11911 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
11912 GNUNET_free (colon_rest);
11913
11914 return address_without_port;
11915}
11916
11917
11927static int
11929 const struct GNUNET_PeerIdentity *pid,
11930 void *value)
11931{
11932 struct Queue *q = cls;
11933 struct ValidationState *vs = value;
11934 char *address_without_port_vs;
11935 char *address_without_port_q;
11936 int success = GNUNET_YES;
11937
11938 // TODO Check if this is really necessary.
11939 address_without_port_vs = get_address_without_port (vs->address);
11940 address_without_port_q = get_address_without_port (q->address);
11941
11943 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
11944 GNUNET_i2s (pid),
11945 address_without_port_vs,
11946 address_without_port_q);
11947 (void) pid;
11948 if ((GNUNET_YES == vs->awaiting_queue) &&
11949 (0 == strcmp (address_without_port_vs, address_without_port_q)))
11950 {
11951
11952 vs->awaiting_queue = GNUNET_NO;
11954 success = GNUNET_NO;
11955 }
11956
11957 GNUNET_free (address_without_port_vs);
11958 GNUNET_free (address_without_port_q);
11959 return success;
11960}
11961
11962
11971static void
11973 const struct GNUNET_PEERSTORE_Record *record,
11974 const char *emsg)
11975{
11976 struct Neighbour *n = cls;
11977 struct GNUNET_TIME_AbsoluteNBO *mtbe;
11978
11979 (void) emsg;
11980 if (NULL == record)
11981 {
11982 /* we're done with #neighbour_dv_monotime_cb() invocations,
11983 continue normal processing */
11984 n->get = NULL;
11986 return;
11987 }
11988 if (0 == record->value_size)
11989 {
11991 GNUNET_break (0);
11992 return;
11993 }
11994 mtbe = record->value;
11999}
12000
12001
12002static void
12004 const struct GNUNET_PeerIdentity *pid,
12005 const char *uri)
12006{
12007 struct Queue *queue = cls;
12008 struct sockaddr_in v4;
12009 const char *slash;
12010 char *address_uri;
12011 char *prefix;
12012 char *uri_without_port;
12013 char *address_uri_without_port;
12014
12015 slash = strrchr (uri, '/');
12016 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12017 GNUNET_assert (NULL != slash);
12018 slash++;
12019 GNUNET_asprintf (&address_uri,
12020 "%s-%s",
12021 prefix,
12022 slash);
12023
12025 "1 not global natted_address %u %s %s %s\n",
12026 queue->is_global_natted,
12027 uri,
12028 queue->address,
12029 slash);
12030
12031 uri_without_port = get_address_without_port (address_uri);
12032 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12033 {
12035 GNUNET_free (address_uri);
12036 GNUNET_free (uri_without_port);
12037 return;
12038 }
12039
12041 "2 not global natted_address %u %s %s\n",
12042 queue->is_global_natted,
12043 uri,
12044 queue->address);
12045
12046 if (GNUNET_NO == queue->is_global_natted)
12047 {
12049 GNUNET_free (address_uri);
12050 GNUNET_free (uri_without_port);
12051 return;
12052 }
12053
12055 "3 not global natted_address %u %s %s\n",
12056 queue->is_global_natted,
12057 uri,
12058 queue->address);
12059
12060 if (0 == strcmp (uri_without_port, address_uri))
12061 {
12063 GNUNET_free (address_uri);
12064 GNUNET_free (uri_without_port);
12065 return;
12066 }
12067
12069 "4 not global natted_address %u %s %s\n",
12070 queue->is_global_natted,
12071 uri,
12072 queue->address);
12073
12074 address_uri_without_port = get_address_without_port (queue->address);
12075 if (0 == strcmp (uri_without_port, address_uri_without_port))
12076 {
12077 queue->is_global_natted = GNUNET_NO;
12078 }
12079
12081 "not global natted_address %u %s %s %s %s %s %u\n",
12082 queue->is_global_natted,
12083 uri,
12084 queue->address,
12085 uri_without_port,
12086 address_uri_without_port,
12087 prefix,
12088 GNUNET_NO);
12090 GNUNET_free (address_uri);
12091 GNUNET_free (address_uri_without_port);
12092 GNUNET_free (uri_without_port);
12093}
12094
12095
12097{
12101 char *addr;
12102
12107};
12108
12109
12110static enum GNUNET_GenericReturnValue
12112 const struct GNUNET_PeerIdentity *pid,
12113 void *value)
12114{
12115 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12116 struct TransportGlobalNattedAddress *tgna = value;
12117 char *addr = (char *) &tgna[1];
12118
12120 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12121 tgna,
12122 addr,
12123 ntohl (tgna->address_length),
12124 strlen (tgna_cls->addr));
12125 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12126 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12127 {
12128 tgna_cls->tgna = tgna;
12129 return GNUNET_NO;
12130 }
12131 return GNUNET_YES;
12132}
12133
12134
12135static void
12137{
12139 "Error in PEERSTORE monitoring for checking global natted\n");
12140}
12141
12142
12143static void
12145{
12147 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12148}
12149
12150
12151static void
12153 const struct GNUNET_PEERSTORE_Record *record,
12154 const char *emsg)
12155{
12156 struct Queue *queue = cls;
12157 struct Neighbour *neighbour = queue->neighbour;
12159 struct GNUNET_MessageHeader *hello;
12161 size_t address_len_without_port;
12162
12163 if (NULL != emsg)
12164 {
12166 "Got failure from PEERSTORE: %s\n",
12167 emsg);
12168 return;
12169 }
12170 if (0 == record->value_size)
12171 {
12173 GNUNET_break (0);
12174 return;
12175 }
12176 queue->is_global_natted = GNUNET_YES;
12177 hello = record->value;
12180 "before not global natted %u\n",
12181 queue->is_global_natted);
12184 queue);
12186 "after not global natted %u\n",
12187 queue->is_global_natted);
12189
12190 tgna_cls.addr = get_address_without_port (queue->address);
12191 address_len_without_port = strlen (tgna_cls.addr);
12192 /*{
12193 char buf[address_len_without_port + 1];
12194
12195 GNUNET_memcpy (&buf, addr, address_len_without_port);
12196 buf[address_len_without_port] = '\0';
12197 GNUNET_free (addr);
12198 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12199 }*/
12200 tgna_cls.tgna = NULL;
12202 &neighbour->pid,
12204 &tgna_cls);
12205 if (NULL != tgna_cls.tgna)
12207 " tgna_cls.tgna tgna %p %lu %u %u\n",
12208 tgna_cls.tgna,
12209 neighbour->size_of_global_addresses,
12210 ntohl (tgna_cls.tgna->address_length),
12211 neighbour->number_of_addresses);
12212 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12213 {
12214 struct TransportGlobalNattedAddress *tgna;
12215
12216 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12217 + address_len_without_port);
12218 tgna->address_length = htonl (address_len_without_port);
12219 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12221 &neighbour->pid,
12222 tgna,
12224 neighbour->number_of_addresses++;
12225 neighbour->size_of_global_addresses += address_len_without_port + 1;
12227 "Created tgna %p with address %s and length %lu\n",
12228 tgna,
12229 tgna_cls.addr,
12230 address_len_without_port + 1);
12231 }
12232 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12233 {
12235 &neighbour->pid,
12236 tgna_cls.tgna);
12237 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12239 );
12240 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12241 ;
12242 GNUNET_assert (0 < neighbour->number_of_addresses);
12243 neighbour->number_of_addresses--;
12245 "removed tgna %p\n",
12246 tgna_cls.tgna);
12247 GNUNET_free (tgna_cls.tgna);
12248 }
12250 GNUNET_free (tgna_cls.addr);
12251}
12252
12253
12260static void
12262 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12263{
12264 struct TransportClient *tc = cls;
12265 struct Queue *queue;
12266 struct Neighbour *neighbour;
12267 const char *addr;
12268 uint16_t addr_len;
12269
12270 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12271 {
12272 /* MTU so small as to be useless for transmissions,
12273 required for #fragment_message()! */
12274 GNUNET_break_op (0);
12276 return;
12277 }
12278 /* This may simply be a queue update */
12279 for (queue = tc->details.communicator.queue_head;
12280 NULL != queue;
12281 queue = queue->next_client)
12282 {
12283 if (queue->qid != ntohl (aqm->qid))
12284 continue;
12285 break;
12286 }
12287
12288 if (NULL != queue)
12289 {
12290 neighbour = queue->neighbour;
12291 }
12292 else
12293 {
12294 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12295
12296 neighbour = lookup_neighbour (&aqm->receiver);
12297 if (NULL == neighbour)
12298 {
12299 neighbour = GNUNET_new (struct Neighbour);
12301 GNUNET_YES);
12302 neighbour->pid = aqm->receiver;
12305 neighbours,
12306 &neighbour->pid,
12307 neighbour,
12309 neighbour->get =
12311 "transport",
12312 &neighbour->pid,
12315 neighbour);
12316 }
12317 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12318 addr = (const char *) &aqm[1];
12320 "New queue %s to %s available with QID %u and q_len %" PRIu64
12321 " and mtu %u\n",
12322 addr,
12323 GNUNET_i2s (&aqm->receiver),
12324 ntohl (aqm->qid),
12325 GNUNET_ntohll (aqm->q_len),
12326 ntohl (aqm->mtu));
12327 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12328 queue->tc = tc;
12329 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12330 next_neighbour)
12331 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12332 validated_until);
12333 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12334 {
12336 "New queue with QID %u inherit validated until\n",
12337 ntohl (aqm->qid));
12338 queue->validated_until = validated_until;
12339 }
12340 queue->address = (const char *) &queue[1];
12341 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12342 queue->qid = ntohl (aqm->qid);
12343 queue->neighbour = neighbour;
12345 queue->unlimited_length = GNUNET_YES;
12346 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12347 memcpy (&queue[1], addr, addr_len);
12348 /* notify monitors about new queue */
12349 {
12350 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12351
12352 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12353 }
12355 neighbour->queue_head,
12356 neighbour->queue_tail,
12357 queue);
12359 tc->details.communicator.queue_head,
12360 tc->details.communicator.queue_tail,
12361 queue);
12362
12363 }
12364 queue->mtu = ntohl (aqm->mtu);
12365 queue->nt = ntohl (aqm->nt);
12366 queue->cs = ntohl (aqm->cs);
12367 queue->idle = GNUNET_YES;
12368
12369 {
12370 struct sockaddr_in v4;
12371 char *addr_without = get_address_without_port (queue->address);
12372 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12373 {
12375 "start not global natted\n");
12377 GNUNET_YES,
12378 "peerstore",
12379 &neighbour->pid,
12381 &
12383 NULL,
12384 &
12386 NULL,
12388 queue);
12389 }
12390 GNUNET_free (addr_without);
12391 }
12392 /* check if valdiations are waiting for the queue */
12394 &aqm->receiver))
12395 {
12398 &aqm->
12399 receiver,
12400 &
12402 queue))
12403 start_address_validation (&aqm->receiver, queue->address);
12404 }
12405 else
12406 start_address_validation (&aqm->receiver, queue->address);
12407 /* look for traffic for this queue */
12408 // TODO Check whether this makes any sense at all.
12409 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12410 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12411 /* might be our first queue, try launching DV learning */
12412 if (NULL == dvlearn_task)
12415}
12416
12417
12424static void
12426 const struct
12428{
12429 struct TransportClient *tc = cls;
12430 struct Queue *target_queue = NULL;
12431
12433 "Received queue update message for %u with q_len %llu and mtu %u\n",
12434 ntohl (msg->qid),
12435 (unsigned long long) GNUNET_ntohll (msg->q_len),
12436 ntohl (msg->mtu));
12437 for (target_queue = tc->details.communicator.queue_head;
12438 NULL != target_queue;
12439 target_queue = target_queue->next_client)
12440 {
12441 if (ntohl (msg->qid) == target_queue->qid)
12442 break;
12443 }
12444 if (NULL == target_queue)
12445 {
12447 "Queue to update no longer exists! Discarding update.\n");
12448 return;
12449 }
12450
12451 target_queue->nt = msg->nt;
12452 target_queue->mtu = ntohl (msg->mtu);
12453 target_queue->cs = msg->cs;
12454 target_queue->priority = ntohl (msg->priority);
12455 /* The update message indicates how many messages
12456 * the queue should be able to handle.
12457 */
12459 target_queue->unlimited_length = GNUNET_YES;
12460 else
12461 target_queue->unlimited_length = GNUNET_NO;
12462 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12463 if (0 < target_queue->q_capacity)
12465 target_queue,
12468}
12469
12470
12478static void
12480 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12481{
12482 struct TransportClient *tc = cls;
12483
12484 if (CT_COMMUNICATOR != tc->type)
12485 {
12486 GNUNET_break (0);
12488 return;
12489 }
12491 "# Suggestions succeeded at communicator",
12492 1,
12493 GNUNET_NO);
12495 "Request #%u for communicator to create queue succeeded\n",
12496 (unsigned int) ntohs (cqr->request_id));
12498}
12499
12500
12509static void
12511 void *cls,
12512 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12513{
12514 struct TransportClient *tc = cls;
12515
12516 if (CT_COMMUNICATOR != tc->type)
12517 {
12518 GNUNET_break (0);
12520 return;
12521 }
12523 "Request #%u for communicator to create queue failed\n",
12524 (unsigned int) ntohs (cqr->request_id));
12526 "# Suggestions failed in queue creation at communicator",
12527 1,
12528 GNUNET_NO);
12530}
12531
12532
12540static void
12542{
12543 struct TransportClient *tc = cls;
12544 struct PeerRequest *pr;
12545
12546 if (CT_APPLICATION != tc->type)
12547 {
12548 GNUNET_break (0);
12550 return;
12551 }
12552 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
12553 &msg->peer);
12554 if (NULL == pr)
12555 {
12556 GNUNET_break (0);
12558 return;
12559 }
12560 (void) stop_peer_request (tc, &pr->pid, pr);
12562}
12563
12564
12565static void
12567 const struct GNUNET_PeerIdentity *pid,
12568 const char *uri)
12569{
12570 struct Queue *q;
12571 int pfx_len;
12572 const char *eou;
12573 char *address;
12574 (void) cls;
12575
12576 eou = strstr (uri,
12577 "://");
12578 pfx_len = eou - uri;
12579 eou += 3;
12581 "%.*s-%s",
12582 pfx_len,
12583 uri,
12584 eou);
12585
12587 "hello for client %s\n",
12588 address);
12589
12590 q = find_queue (pid, address);
12591 if (NULL == q)
12592 {
12594 }
12595 else
12598}
12599
12600
12608static void
12610 const struct GNUNET_PEERSTORE_Record *record,
12611 const char *emsg)
12612{
12613 struct PeerRequest *pr = cls;
12615 struct GNUNET_MessageHeader *hello;
12616
12617 if (NULL != emsg)
12618 {
12620 "Got failure from PEERSTORE: %s\n",
12621 emsg);
12622 return;
12623 }
12624 hello = record->value;
12625 if (0 == GNUNET_memcmp (&record->peer, &GST_my_identity))
12626 {
12628 return;
12629 }
12633 NULL);
12635}
12636
12637
12638static void
12640{
12642 "Error in PEERSTORE monitoring\n");
12643}
12644
12645
12646static void
12648{
12650 "Done with initial PEERSTORE iteration during monitoring\n");
12651}
12652
12653
12661static void
12663{
12664 struct TransportClient *tc = cls;
12665 struct PeerRequest *pr;
12666
12667 if (CT_NONE == tc->type)
12668 {
12669 tc->type = CT_APPLICATION;
12670 tc->details.application.requests =
12672 }
12673 if (CT_APPLICATION != tc->type)
12674 {
12675 GNUNET_break (0);
12677 return;
12678 }
12680 "Client suggested we talk to %s with preference %d at rate %u\n",
12681 GNUNET_i2s (&msg->peer),
12682 (int) ntohl (msg->pk),
12683 (int) ntohl (msg->bw.value__));
12684 pr = GNUNET_new (struct PeerRequest);
12685 pr->tc = tc;
12686 pr->pid = msg->peer;
12687 pr->bw = msg->bw;
12688 pr->pk = ntohl (msg->pk);
12690 tc->details.application.requests,
12691 &pr->pid,
12692 pr,
12694 {
12695 GNUNET_break (0);
12696 GNUNET_free (pr);
12698 return;
12699 }
12700 pr->nc =
12702 GNUNET_YES,
12703 "peerstore",
12704 NULL,
12707 NULL,
12709 NULL,
12711 pr);
12713}
12714
12715
12724static int
12726 const struct RequestHelloValidationMessage *m)
12727{
12728 (void) cls;
12730 return GNUNET_OK;
12731}
12732
12733
12741static void
12743 const struct RequestHelloValidationMessage *m)
12744{
12745 struct TransportClient *tc = cls;
12746 struct Queue *q;
12747
12748 q = find_queue (&m->peer, (const char *) &m[1]);
12749 if (NULL == q)
12750 {
12751 suggest_to_connect (&m->peer, (const char *) &m[1]);
12752 }
12753 else
12754 start_address_validation (&m->peer, (const char *) &m[1]);
12756}
12757
12758
12767static int
12769 const struct GNUNET_PeerIdentity *pid,
12770 void *value)
12771{
12772 struct Neighbour *neighbour = value;
12773
12774 (void) cls;
12775 (void) pid;
12776 GNUNET_break (0); // should this ever happen?
12777 free_neighbour (neighbour, GNUNET_YES);
12778
12779 return GNUNET_OK;
12780}
12781
12782
12791static int
12793 const struct GNUNET_PeerIdentity *pid,
12794 void *value)
12795{
12796 struct DistanceVector *dv = value;
12797
12798 (void) cls;
12799 (void) pid;
12800 free_dv_route (dv);
12801
12802 return GNUNET_OK;
12803}
12804
12805
12814static int
12816 const struct GNUNET_PeerIdentity *pid,
12817 void *value)
12818{
12819 struct ValidationState *vs = value;
12820
12821 (void) cls;
12822 (void) pid;
12824 return GNUNET_OK;
12825}
12826
12827
12836static int
12837free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
12838{
12839 struct PendingAcknowledgement *pa = value;
12840
12841 (void) cls;
12842 (void) key;
12844 return GNUNET_OK;
12845}
12846
12847
12856static int
12858 const struct GNUNET_PeerIdentity *pid,
12859 void *value)
12860{
12861 struct AcknowledgementCummulator *ac = value;
12862
12863 (void) cls;
12864 (void) pid;
12866 GNUNET_free (ac);
12867 return GNUNET_OK;
12868}
12869
12870
12877static void
12878do_shutdown (void *cls)
12879{
12880 struct LearnLaunchEntry *lle;
12881 (void) cls;
12882
12884 "shutdown logic\n");
12887 &free_neighbour_cb, NULL);
12888 if (NULL != validation_task)
12889 {
12891 validation_task = NULL;
12892 }
12893 if (NULL != dvlearn_task)
12894 {
12896 dvlearn_task = NULL;
12897 }
12898 if (NULL != GST_stats)
12899 {
12901 GST_stats = NULL;
12902 }
12903 if (NULL != GST_my_hello)
12904 {
12906 GST_my_hello = NULL;
12907 }
12908 if (NULL != GST_my_private_key)
12909 {
12911 GST_my_private_key = NULL;
12912 }
12915 NULL);
12917 ack_cummulators = NULL;
12920 NULL);
12922 pending_acks = NULL;
12925 neighbours = NULL;
12928 links = NULL;
12931 NULL);
12933 backtalkers = NULL;
12936 NULL);
12938 validation_map = NULL;
12940 revalidation_map = NULL;
12941 while (NULL != ir_head)
12943 GNUNET_assert (0 == ir_total);
12944 while (NULL != (lle = lle_head))
12945 {
12947 GNUNET_free (lle);
12948 }
12949 if (NULL != peerstore)
12950 {
12952 "Disconnecting from PEERSTORE service\n");
12954 peerstore = NULL;
12955 }
12957 dvlearn_map = NULL;
12959 validation_heap = NULL;
12962 dv_routes = NULL;
12964}
12965
12966
12967static void
12968shutdown_task (void *cls)
12969{
12971
12973 "Shutdown task executed\n");
12974 if (NULL != clients_head)
12975 {
12976 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
12977 {
12979 "client still connected: %u\n",
12980 tc->type);
12981 }
12982 }
12983 else
12984 do_shutdown (cls);
12985
12986}
12987
12988
12996static void
12997run (void *cls,
12998 const struct GNUNET_CONFIGURATION_Handle *c,
13000{
13001 (void) cls;
13002 (void) service;
13003 /* setup globals */
13006 GST_cfg = c;
13014 GNUNET_YES);
13021 if (NULL == GST_my_private_key)
13022 {
13023 GNUNET_log (
13025 _ (
13026 "Transport service is lacking key configuration settings. Exiting.\n"));
13028 return;
13029 }
13033 "My identity is `%s'\n",
13037 "transport",
13038 "USE_BURST_NAT");
13039 if (GNUNET_SYSERR == use_burst)
13041 "Could not configure burst nat use. Default to no.\n");
13046 "transport",
13047 0,
13048 0,
13049 NULL,
13050 0,
13051 NULL,
13052 NULL,
13053 NULL);
13054 if (NULL == peerstore)
13055 {
13056 GNUNET_break (0);
13058 return;
13059 }
13060}
13061
13062
13068 "transport",
13070 &run,
13073 NULL,
13074 /* communication with applications */
13075 GNUNET_MQ_hd_fixed_size (suggest,
13078 NULL),
13079 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13082 NULL),
13083 GNUNET_MQ_hd_var_size (request_hello_validation,
13086 NULL),
13087 /* communication with core */
13088 GNUNET_MQ_hd_fixed_size (client_start,
13090 struct StartMessage,
13091 NULL),
13092 GNUNET_MQ_hd_var_size (client_send,
13094 struct OutboundMessage,
13095 NULL),
13096 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13098 struct RecvOkMessage,
13099 NULL),
13100 /* communication with communicators */
13101 GNUNET_MQ_hd_var_size (communicator_available,
13104 NULL),
13105 GNUNET_MQ_hd_var_size (communicator_backchannel,
13108 NULL),
13109 GNUNET_MQ_hd_var_size (add_address,
13112 NULL),
13113 GNUNET_MQ_hd_fixed_size (del_address,
13116 NULL),
13117 GNUNET_MQ_hd_var_size (incoming_msg,
13120 NULL),
13121 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13124 NULL),
13125 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13128 NULL),
13129 GNUNET_MQ_hd_var_size (add_queue_message,
13132 NULL),
13133 GNUNET_MQ_hd_fixed_size (update_queue_message,
13136 NULL),
13137 GNUNET_MQ_hd_fixed_size (del_queue_message,
13140 NULL),
13141 GNUNET_MQ_hd_fixed_size (send_message_ack,
13144 NULL),
13145 GNUNET_MQ_hd_fixed_size (burst_finished,
13148 NULL),
13149 /* communication with monitors */
13150 GNUNET_MQ_hd_fixed_size (monitor_start,
13153 NULL),
13155
13156
13157/* 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
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:178
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition: socks.c:330
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE
Signature by a peer affirming that it received a challenge (and stating how long it expects the addre...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
Signature by a peer affirming that the given ephemeral key is currently in use by that peer's transpo...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
Signature by a peer affirming that it originated the DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
Signature by a peer affirming that it is on a DV path.
Data structure in which we track acknowledgements still to be sent to the.
struct GNUNET_SCHEDULER_Task * task
Task scheduled either to transmit the cumulative ACK message, or to clean up this data structure afte...
struct GNUNET_TIME_Absolute min_transmission_time
When is task run (only used if num_acks is non-zero)?
struct TransportCummulativeAckPayload ack_uuids[64]
ACK data being accumulated.
struct GNUNET_PeerIdentity target
Target peer for which we are accumulating ACKs here.
unsigned int num_acks
Number of entries used in ack_uuids.
uint32_t ack_counter
Counter to produce the ack_counter in the struct TransportReliabilityAckMessage.
Unique identifier to map an acknowledgement to a transmission.
struct GNUNET_Uuid value
The UUID value.
One of the addresses of this peer.
struct GNUNET_TIME_Relative expiration
What is a typical lifetime the communicator expects this address to have? (Always from now....
uint32_t aid
Address identifier used by the communicator.
size_t signed_address_len
Signed address length.
enum GNUNET_NetworkType nt
Network type offered by this address.
struct AddressListEntry * prev
Kept in a DLL.
struct TransportClient * tc
Which communicator provides this address?
struct AddressListEntry * next
Kept in a DLL.
struct GNUNET_PEERSTORE_StoreHelloContext * shc
Store hello handle.
void * signed_address
Signed address.
const char * address
The actual address.
struct GNUNET_SCHEDULER_Task * st
Task to periodically do st operation.
struct GNUNET_PEERSTORE_StoreContext * sc
Current context for storing this address in the peerstore.
A Backtalker is a peer sending us backchannel messages.
struct GNUNET_TIME_Absolute timeout
When will this entry time out?
struct CommunicatorMessageContext * cmc
Communicator context waiting on this backchannel's get, or NULL.
struct GNUNET_CRYPTO_HpkeEncapsulation last_ephemeral
Last (valid) ephemeral key received from this sender.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation for this pid's monotonic_time.
struct GNUNET_SCHEDULER_Task * task
Task associated with this backtalker.
size_t body_size
Number of bytes of the original message body that follows after this struct.
struct GNUNET_TIME_Absolute monotonic_time
Last (valid) monotonic time received from this sender.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch monotonic_time information from the PEERSTORE, or NULL.
struct GNUNET_PeerIdentity pid
Peer this is about.
Closure for check_known_address.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const char * address
Set to the address we are looking for.
Closure for check_known_challenge.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const struct GNUNET_CRYPTO_ChallengeNonceP * challenge
Set to the challenge we are looking for.
Context from handle_incoming_msg().
struct CommunicatorMessageContext * next
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
uint16_t total_hops
Number of hops the message has travelled (if DV-routed).
struct GNUNET_TRANSPORT_IncomingMessage im
Additional information for flow control and about the sender.
unsigned int continue_send
Did we already call GNUNET_SERVICE_client_continue and send ACK to communicator?
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
struct CommunicatorMessageContext * prev
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
struct TransportClient * tc
Which communicator provided us with the message.
Message from the transport service to the library informing about neighbors.
Definition: transport.h:88
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition: transport.h:111
Closure for core_env_sent_cb.
uint16_t isize
By how much should we increment vl's incoming_fc_window_size_used once we are done sending to CORE?...
struct CoreSentContext * next
Kept in a DLL to clear vl in case vl is lost.
struct VirtualLink * vl
Virtual link this is about.
struct CoreSentContext * prev
Kept in a DLL to clear vl in case vl is lost.
uint16_t size
How big was the message.
Structure of the key material used to encrypt backchannel messages.
struct GNUNET_CRYPTO_AuthKey hmac_key
Key used for HMAC calculations (via GNUNET_CRYPTO_hmac()).
gcry_cipher_hd_t cipher
State of our block cipher.
struct DVKeyState::@65 material
Actual key material.
char aes_key[256/8]
Symmetric key to use for encryption.
char aes_ctr[128/8]
Counter value to use during setup.
An entry describing a peer on a path in a struct TransportDVLearnMessage message.
struct GNUNET_CRYPTO_EddsaSignature hop_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity hop
Identity of a peer on the path.
Message from the transport service to the library informing about disconnects.
Definition: transport.h:120
One possible hop towards a DV target.
struct PerformanceData pd
Performance data for this transmission possibility.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used our path.
unsigned int distance
Number of hops in total to the target (excluding next_hop and target itself).
struct DistanceVectorHop * next_neighbour
Kept in a MDLL.
struct Neighbour * next_hop
What would be the next hop to target?
struct GNUNET_TIME_Absolute timeout
At what time do we forget about this path unless we see it again while learning?
struct DistanceVector * dv
Distance vector entry this hop belongs with.
const struct GNUNET_PeerIdentity * path
Array of distance hops to the target, excluding next_hop.
struct DistanceVectorHop * next_dv
Kept in a MDLL, sorted by timeout.
struct GNUNET_TIME_Absolute path_valid_until
For how long is the validation of this path considered valid? Set to ZERO if the path is learned by s...
struct DistanceVectorHop * prev_dv
Kept in a MDLL, sorted by timeout.
struct DistanceVectorHop * prev_neighbour
Kept in a MDLL.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used our path.
Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer.
struct DistanceVectorHop * dv_head
Known paths to target.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct GNUNET_TIME_Absolute monotime
What time was sender_sig created.
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature affirming ephemeral_key of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct DistanceVectorHop * dv_tail
Known paths to target.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Our ephemeral key.
struct GNUNET_ShortHashCode * km
Master secret for the setup of the Key material for the backchannel.
struct GNUNET_PeerIdentity target
To which peer is this a route?
struct GNUNET_TIME_Absolute ephemeral_validity
How long is sender_sig valid.
struct GNUNET_SCHEDULER_Task * timeout_task
Task scheduled to purge expired paths from dv_head MDLL.
Content signed by each peer during DV learning.
struct GNUNET_PeerIdentity pred
Identity of the previous peer on the path.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
Body by which a peer confirms that it is using an ephemeral key.
struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time
How long is this signature over the ephemeral key valid?
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_PeerIdentity target
Target's peer identity.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
Application client to TRANSPORT service: we would like to have address suggestions for this peer.
Definition: transport.h: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