GNUnet 0.26.2-114-g7c6b613e3
 
Loading...
Searching...
No Matches
gnunet-service-transport.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018-2019, 2026 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 "gnunet_common.h"
76#include "platform.h"
77#include "gnunet_util_lib.h"
80#include "gnunet_pils_service.h"
82#include "gnunet_nat_service.h"
84#include "gnunet_signatures.h"
85#include "transport.h"
86
90#define RING_BUFFER_SIZE 16
91
95#define MAX_FC_RETRANSMIT_COUNT 1000
96
101#define MAX_CUMMULATIVE_ACKS 64
102
115#define FC_NO_CHANGE_REPLY_PROBABILITY 8
116
121#define IN_PACKET_SIZE_WITHOUT_MTU 128
122
127#define GOODPUT_AGING_SLOTS 4
128
133#define DEFAULT_WINDOW_SIZE (128 * 1024)
134
143#define MAX_INCOMING_REQUEST 16
144
149#define MAX_DV_DISCOVERY_SELECTION 16
150
159#define RECV_WINDOW_SIZE 4
160
168#define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
169
173#define MAX_DV_HOPS_ALLOWED 16
174
179#define MAX_DV_LEARN_PENDING 64
180
184#define MAX_DV_PATHS_TO_TARGET 3
185
192#define PILS_FEED_ADDRESSES_DELAY \
193 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
194
200#define DELAY_WARN_THRESHOLD \
201 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
202
207#define DV_FORWARD_TIMEOUT \
208 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
209
213#define DEFAULT_ACK_WAIT_DURATION \
214 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
215
221#define DV_QUALITY_RTT_THRESHOLD \
222 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
223
228#define DV_PATH_VALIDITY_TIMEOUT \
229 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
230
235#define BACKCHANNEL_INACTIVITY_TIMEOUT \
236 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
237
242#define DV_PATH_DISCOVERY_FREQUENCY \
243 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
244
248#define EPHEMERAL_VALIDITY \
249 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
250
254#define REASSEMBLY_EXPIRATION \
255 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
256
261#define FAST_VALIDATION_CHALLENGE_FREQ \
262 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
263
267#define MAX_VALIDATION_CHALLENGE_FREQ \
268 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
269
275#define ACK_CUMMULATOR_TIMEOUT \
276 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
277
282#define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
283
288#define DV_LEARN_QUALITY_THRESHOLD 100
289
293#define MAX_ADDRESS_VALID_UNTIL \
294 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
295
299#define ADDRESS_VALIDATION_LIFETIME \
300 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
301
308#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
309
316#define VALIDATION_RTT_BUFFER_FACTOR 3
317
324#define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
325
331#define QUEUE_LENGTH_LIMIT 32
332
336#define QUEUE_ENTRY_TIMEOUT \
337 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
338
343#define RTT_DIFF \
344 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
345
347
352{
358};
359
360
371
376{
381
382 /* Followed by *another* message header which is the message to
383 the communicator */
384
385 /* Followed by a 0-terminated name of the communicator */
386};
387
388
426
427
433{
438
444
456
457 /* Followed by a `struct GNUNET_MessageHeader` with a message
458 for the target peer */
459};
460
461
488
489
508
509
518{
523
529
530 /* followed by any number of `struct TransportCummulativeAckPayloadP`
531 messages providing ACKs */
532};
533
534
570
571
615
616
655
656
674
675
690{
695
701
711
718
732
738
743
748
749 /* Followed by @e num_hops `struct DVPathEntryP` values,
750 excluding the initiator of the DV trace; the last entry is the
751 current sender; the current peer must not be included. */
752};
753
754
778{
783
787 unsigned int without_fc;
788
796
803
809
816
823
830
831 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
832 excluding the @e origin and the current peer, the last must be
833 the ultimate target; if @e num_hops is zero, the receiver of this
834 message is the ultimate target. */
835
836 /* Followed by encrypted, variable-size payload, which
837 must begin with a `struct TransportDVBoxPayloadP` */
838
839 /* Followed by the actual message, which itself must not be a
840 a DV_LEARN or DV_BOX message! */
841};
842
843
871
872
895
896
936
938{
942 unsigned int address_length;
943
944 /* Followed by @e address_length bytes of the address. */
945};
946
956{
961
970
976
983
993
1003
1008
1012 unsigned int sync_ready;
1013
1018
1023
1024 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1025};
1026
1028
1029
1034{
1039
1044
1049
1054
1058 CT_APPLICATION = 4
1060
1061
1095
1096
1123
1124
1130{
1134 uint64_t bytes_sent;
1135
1141};
1142
1143
1166
1167
1171struct TransportClient;
1172
1176struct Neighbour;
1177
1182struct DistanceVector;
1183
1188struct Queue;
1189
1193struct PendingMessage;
1194
1198struct DistanceVectorHop;
1199
1208struct VirtualLink;
1209
1210
1255
1256
1272
1273
1278{
1283
1288
1293
1297 uint16_t size;
1298
1305 uint16_t isize;
1306};
1307
1308
1313{
1319
1324
1329
1337 uint8_t *bitfield;
1338
1343
1349
1353 uint16_t msg_size;
1354
1359 uint16_t msg_missing;
1360
1361 /* Followed by @e msg_size bytes of the (partially) defragmented original
1362 * message */
1363
1364 /* Followed by @e bitfield data */
1365};
1366
1367
1377{
1382
1389
1396
1401
1407
1413
1418
1423
1428
1433
1441
1447
1452
1457
1462
1467 unsigned int confirmed;
1468
1472 struct Neighbour *n;
1473
1478
1485
1492
1501
1507
1513
1518
1524
1533
1541
1548
1557
1570
1576
1583
1594
1599 uint32_t fc_seq_gen;
1600
1606 uint32_t last_fc_seq;
1607
1620
1625};
1626
1627
1725
1726
1806
1807
1866
1867
1878{
1883
1888
1892 struct Queue *queue;
1893
1898
1902 uint64_t mid;
1903
1908};
1909
1910
1915struct Queue
1916{
1921
1926
1931
1936
1941
1946
1951
1956
1961
1966
1970 const char *address;
1971
1975 unsigned int unlimited_length;
1976
1982
1991
1996
2002
2007 uint64_t mid_gen;
2008
2012 uint32_t qid;
2013
2017 uint32_t mtu;
2018
2023
2028
2032 unsigned int queue_length;
2033
2037 uint64_t q_capacity;
2038
2042 uint32_t priority;
2043
2048
2053
2058 int idle;
2059
2064};
2065
2066
2149
2150
2177
2178
2182struct PeerRequest
2183{
2188
2193
2198
2205
2210};
2211
2212
2238
2239
2266struct PendingMessage
2267{
2272
2277
2282
2287
2293
2299
2304
2309
2315
2321
2326
2336
2341
2346
2351
2356
2361
2366
2372
2378
2383
2389
2394
2398 uint16_t bytes_msg;
2399
2403 uint16_t frag_off;
2404
2409
2414
2418 uint16_t frag_count;
2419
2424
2425 /* Followed by @e bytes_msg to transmit */
2426};
2427
2428
2445
2446
2487
2488
2555
2556
2561{
2566
2571
2576
2581
2586
2587 union
2588 {
2592 struct
2593 {
2599
2605
2609 struct
2610 {
2617
2623
2624
2628 struct
2629 {
2635
2640
2645
2651
2657
2664
2669
2674
2679
2681
2685 struct
2686 {
2694};
2695
2696
2702{
2708
2716
2722
2729 struct GNUNET_TIME_Absolute first_challenge_use;
2730
2737 struct GNUNET_TIME_Absolute last_challenge_use;
2738
2746 struct GNUNET_TIME_Absolute next_challenge;
2747
2756 struct GNUNET_TIME_Relative challenge_backoff;
2757
2762 struct GNUNET_TIME_Relative validation_rtt;
2763
2771 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2772
2776 struct GNUNET_HashCode hc;
2777
2781 struct GNUNET_SCHEDULER_Task *revalidation_task;
2782
2786 char *address;
2787
2793 struct GNUNET_CONTAINER_HeapNode *hn;
2794
2800
2806 uint32_t last_window_consum_limit;
2807
2812 int awaiting_queue;
2813};
2814
2815
2873
2878
2882static unsigned int ring_buffer_head;
2883
2887static unsigned int is_ring_buffer_full;
2888
2893
2897static unsigned int ring_buffer_dv_head;
2898
2902static unsigned int is_ring_buffer_dv_full;
2903
2908
2913
2918
2923
2928
2934
2940
2946
2952
2958
2964
2970
2976
2981
2985static struct LearnLaunchEntry *lle_head = NULL;
2986
2990static struct LearnLaunchEntry *lle_tail = NULL;
2991
2998
3003
3008
3013
3017struct PilsRequest
3018{
3022 struct PilsRequest *prev;
3023
3027 struct PilsRequest *next;
3028
3032 struct GNUNET_PILS_Operation *op;
3033};
3034
3039
3044
3049
3054
3059
3066
3071
3075static unsigned int ir_total;
3076
3080static unsigned long long logging_uuid_gen;
3081
3086
3096
3101static int in_shutdown;
3102
3107
3109
3111
3122static unsigned int
3124{
3125 struct GNUNET_TIME_Absolute now;
3126
3127 now = GNUNET_TIME_absolute_get ();
3128 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3129}
3130
3131
3137static void
3139{
3141 GNUNET_assert (ir_total > 0);
3142 ir_total--;
3143 if (NULL != ir->nc)
3145 ir->nc = NULL;
3146 GNUNET_free (ir);
3147}
3148
3149
3155static void
3157{
3158 struct Queue *q = pa->queue;
3159 struct PendingMessage *pm = pa->pm;
3160 struct DistanceVectorHop *dvh = pa->dvh;
3161
3163 "free_pending_acknowledgement\n");
3164 if (NULL != q)
3165 {
3166 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3167 pa->queue = NULL;
3168 }
3169 if (NULL != pm)
3170 {
3172 "remove pa from message\n");
3174 "remove pa from message %" PRIu64 "\n",
3175 pm->logging_uuid);
3177 "remove pa from message %u\n",
3178 pm->pmt);
3180 "remove pa from message %s\n",
3182 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3183 pa->pm = NULL;
3184 }
3185 if (NULL != dvh)
3186 {
3187 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3188 pa->queue = NULL;
3189 }
3192 &pa->ack_uuid.value,
3193 pa));
3194 GNUNET_free (pa);
3195}
3196
3197
3206static void
3208{
3209 struct PendingMessage *frag;
3210
3211 while (NULL != (frag = root->head_frag))
3212 {
3213 struct PendingAcknowledgement *pa;
3214
3215 free_fragment_tree (frag);
3216 while (NULL != (pa = frag->pa_head))
3217 {
3218 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3219 pa->pm = NULL;
3220 }
3221 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3222 if (NULL != frag->qe)
3223 {
3224 GNUNET_assert (frag == frag->qe->pm);
3225 frag->qe->pm = NULL;
3226 }
3228 "Free frag %p\n",
3229 frag);
3230 GNUNET_free (frag);
3231 }
3232}
3233
3234
3242static void
3244{
3245 struct TransportClient *tc = pm->client;
3246 struct VirtualLink *vl = pm->vl;
3247 struct PendingAcknowledgement *pa;
3248
3250 "Freeing pm %p\n",
3251 pm);
3252 if (NULL != tc)
3253 {
3255 tc->details.core.pending_msg_head,
3256 tc->details.core.pending_msg_tail,
3257 pm);
3258 }
3259 if ((NULL != vl) && (NULL == pm->frag_parent))
3260 {
3262 "Removing pm %" PRIu64 "\n",
3263 pm->logging_uuid);
3265 vl->pending_msg_head,
3266 vl->pending_msg_tail,
3267 pm);
3268 }
3269 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3270 {
3271 struct PendingMessage *root = pm->frag_parent;
3272
3273 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3274 root = root->frag_parent;
3275
3276 root->frag_count--;
3277 }
3278 while (NULL != (pa = pm->pa_head))
3279 {
3280 if (NULL == pa)
3282 "free pending pa null\n");
3283 if (NULL == pm->pa_tail)
3285 "free pending pa_tail null\n");
3286 if (NULL == pa->prev_pa)
3288 "free pending pa prev null\n");
3289 if (NULL == pa->next_pa)
3291 "free pending pa next null\n");
3292 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3293 pa->pm = NULL;
3294 }
3295
3297 if (NULL != pm->qe)
3298 {
3299 GNUNET_assert (pm == pm->qe->pm);
3300 pm->qe->pm = NULL;
3301 }
3302 if (NULL != pm->bpm)
3303 {
3304 free_fragment_tree (pm->bpm);
3305 if (NULL != pm->bpm->qe)
3306 {
3307 struct QueueEntry *qe = pm->bpm->qe;
3308
3309 qe->pm = NULL;
3310 }
3311 GNUNET_free (pm->bpm);
3312 }
3313
3314 GNUNET_free (pm);
3316 "Freeing pm done\n");
3317}
3318
3319
3325static void
3337
3338
3344static void
3346{
3347 struct VirtualLink *vl = cls;
3348 struct ReassemblyContext *rc;
3349
3350 vl->reassembly_timeout_task = NULL;
3351 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3352 {
3354 .rel_value_us)
3355 {
3357 continue;
3358 }
3363 vl);
3364 return;
3365 }
3366}
3367
3368
3377static int
3378free_reassembly_cb (void *cls, uint32_t key, void *value)
3379{
3380 struct ReassemblyContext *rc = value;
3381
3382 (void) cls;
3383 (void) key;
3385 return GNUNET_OK;
3386}
3387
3388
3394static void
3396{
3397 struct PendingMessage *pm;
3398 struct CoreSentContext *csc;
3399
3401 "free virtual link %p\n",
3402 vl);
3403
3404 if (NULL != vl->reassembly_map)
3405 {
3408 NULL);
3410 vl->reassembly_map = NULL;
3412 vl->reassembly_heap = NULL;
3413 }
3414 if (NULL != vl->reassembly_timeout_task)
3415 {
3418 }
3419 while (NULL != (pm = vl->pending_msg_head))
3423 if (NULL != vl->visibility_task)
3424 {
3426 vl->visibility_task = NULL;
3427 }
3428 if (NULL != vl->fc_retransmit_task)
3429 {
3431 vl->fc_retransmit_task = NULL;
3432 }
3433 while (NULL != (csc = vl->csc_head))
3434 {
3436 GNUNET_assert (vl == csc->vl);
3437 csc->vl = NULL;
3438 }
3439 GNUNET_break (NULL == vl->n);
3440 GNUNET_break (NULL == vl->dv);
3441 GNUNET_free (vl);
3442}
3443
3444
3450static void
3452{
3453 if (NULL != vs->revalidation_task)
3454 {
3455 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3456 vs->revalidation_task = NULL;
3457 }
3458 /*memcpy (&hkey,
3459 &hc,
3460 sizeof (hkey));*/
3462 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3463 GNUNET_h2s (&vs->hc),
3464 vs->address,
3467 &vs->hc));
3470 GNUNET_YES ==
3473 vs->hn = NULL;
3474 if (NULL != vs->sc)
3475 {
3477 "store cancel\n");
3479 vs->sc = NULL;
3480 }
3481 GNUNET_free (vs->address);
3482 GNUNET_free (vs);
3483}
3484
3485
3492static struct Neighbour *
3497
3498
3505static struct VirtualLink *
3510
3511
3544
3545
3554static void
3556{
3557 struct Neighbour *n = dvh->next_hop;
3558 struct DistanceVector *dv = dvh->dv;
3559 struct PendingAcknowledgement *pa;
3560
3561 while (NULL != (pa = dvh->pa_head))
3562 {
3564 pa->dvh = NULL;
3565 }
3566 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3568 GNUNET_free (dvh);
3569}
3570
3571
3578static void
3579check_link_down (void *cls);
3580
3581
3587static void
3589{
3591 "Informing CORE clients about disconnect from %s\n",
3592 GNUNET_i2s (pid));
3593 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3594 {
3595 struct GNUNET_MQ_Envelope *env;
3596 struct DisconnectInfoMessage *dim;
3597
3598 if (CT_CORE != tc->type)
3599 continue;
3601 dim->peer = *pid;
3602 GNUNET_MQ_send (tc->mq, env);
3603 }
3604}
3605
3606
3613static void
3615{
3616 struct DistanceVectorHop *dvh;
3617 struct VirtualLink *vl;
3618
3619 while (NULL != (dvh = dv->dv_head))
3621
3623 GNUNET_YES ==
3625 if (NULL != (vl = dv->vl))
3626 {
3627 GNUNET_assert (dv == vl->dv);
3628 vl->dv = NULL;
3629 if (NULL == vl->n)
3630 {
3632 free_virtual_link (vl);
3633 }
3634 else
3635 {
3638 }
3639 dv->vl = NULL;
3640 }
3641
3642 if (NULL != dv->timeout_task)
3643 {
3645 dv->timeout_task = NULL;
3646 }
3647 GNUNET_free (dv->km);
3648 GNUNET_free (dv);
3649}
3650
3651
3665static void
3667 const struct GNUNET_PeerIdentity *peer,
3668 const char *address,
3670 const struct MonitorEvent *me)
3671{
3672 struct GNUNET_MQ_Envelope *env;
3674 size_t addr_len = strlen (address) + 1;
3675
3677 addr_len,
3679 md->nt = htonl ((uint32_t) nt);
3680 md->peer = *peer;
3681 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3682 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3683 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3684 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3685 md->cs = htonl ((uint32_t) me->cs);
3686 md->num_msg_pending = htonl (me->num_msg_pending);
3687 md->num_bytes_pending = htonl (me->num_bytes_pending);
3688 memcpy (&md[1], address, addr_len);
3689 GNUNET_MQ_send (tc->mq, env);
3690}
3691
3692
3702static void
3704 const char *address,
3706 const struct MonitorEvent *me)
3707{
3708 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3709 {
3710 if (CT_MONITOR != tc->type)
3711 continue;
3712 if (tc->details.monitor.one_shot)
3713 continue;
3714 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3715 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3716 continue;
3718 }
3719}
3720
3721
3731static void *
3733 struct GNUNET_SERVICE_Client *client,
3734 struct GNUNET_MQ_Handle *mq)
3735{
3736 struct TransportClient *tc;
3737
3738 (void) cls;
3739 tc = GNUNET_new (struct TransportClient);
3740 tc->client = client;
3741 tc->mq = mq;
3744 "Client %p of type %u connected\n",
3745 tc,
3746 tc->type);
3747 return tc;
3748}
3749
3750
3751static enum GNUNET_GenericReturnValue
3753 const struct GNUNET_PeerIdentity *pid,
3754 void *value)
3755{
3756 struct TransportGlobalNattedAddress *tgna = value;
3757 (void) cls;
3758
3759 GNUNET_free (tgna);
3760
3761 return GNUNET_OK;
3762}
3763
3764
3771static void
3772free_neighbour (struct Neighbour *neighbour,
3773 enum GNUNET_GenericReturnValue drop_link)
3774{
3775 struct DistanceVectorHop *dvh;
3776 struct VirtualLink *vl;
3777
3778 GNUNET_assert (NULL == neighbour->queue_head);
3781 &neighbour->pid,
3782 neighbour));
3784 "Freeing neighbour\n");
3787 NULL);
3789 while (NULL != (dvh = neighbour->dv_head))
3790 {
3791 struct DistanceVector *dv = dvh->dv;
3792
3794 if (NULL == dv->dv_head)
3795 free_dv_route (dv);
3796 }
3797 if (NULL != neighbour->get)
3798 {
3800 neighbour->get = NULL;
3801 }
3802 if (NULL != neighbour->sc)
3803 {
3805 "store cancel\n");
3806 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3807 neighbour->sc = NULL;
3808 }
3809 if (NULL != (vl = neighbour->vl))
3810 {
3811 GNUNET_assert (neighbour == vl->n);
3812 vl->n = NULL;
3813 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3814 {
3817 }
3818 else
3819 {
3822 }
3823 neighbour->vl = NULL;
3824 }
3825 GNUNET_free (neighbour);
3826}
3827
3828
3835static void
3837 const struct GNUNET_PeerIdentity *pid)
3838{
3839 struct GNUNET_MQ_Envelope *env;
3840 struct ConnectInfoMessage *cim;
3841
3842 GNUNET_assert (CT_CORE == tc->type);
3844 cim->id = *pid;
3845 GNUNET_MQ_send (tc->mq, env);
3846}
3847
3848
3854static void
3856{
3858 "Informing CORE clients about connection to %s\n",
3859 GNUNET_i2s (pid));
3860 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3861 {
3862 if (CT_CORE != tc->type)
3863 continue;
3865 }
3866}
3867
3868
3876static void
3877transmit_on_queue (void *cls);
3878
3879
3883static unsigned int
3885{
3886 for (struct Queue *s = queue_head; NULL != s;
3887 s = s->next_client)
3888 {
3889 if (s->tc->details.communicator.address_prefix !=
3890 queue->tc->details.communicator.address_prefix)
3891 {
3893 "queue address %s qid %u compare with queue: address %s qid %u\n",
3894 queue->address,
3895 queue->qid,
3896 s->address,
3897 s->qid);
3898 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3899 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3900 return GNUNET_YES;
3902 "Lower prio\n");
3903 }
3904 }
3905 return GNUNET_NO;
3906}
3907
3908
3916static void
3918 struct Queue *queue,
3920{
3922
3923 if (queue->validated_until.abs_value_us < now.abs_value_us)
3924 return;
3926 queue->tc->details.communicator.
3927 queue_head))
3928 return;
3929
3930 if (queue->tc->details.communicator.total_queue_length >=
3932 {
3934 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3935 queue->address,
3936 queue->qid);
3938 GST_stats,
3939 "# Transmission throttled due to communicator queue limit",
3940 1,
3941 GNUNET_NO);
3942 queue->idle = GNUNET_NO;
3943 return;
3944 }
3945 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3946 {
3948 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3949 queue->address,
3950 queue->qid);
3952 "# Transmission throttled due to queue queue limit",
3953 1,
3954 GNUNET_NO);
3955 queue->idle = GNUNET_NO;
3956 return;
3957 }
3958 if (0 == queue->q_capacity)
3959 {
3961 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3962 PRIu64 ".\n",
3963 queue->address,
3964 queue->qid,
3965 queue->q_capacity);
3967 "# Transmission throttled due to message queue capacity",
3968 1,
3969 GNUNET_NO);
3970 queue->idle = GNUNET_NO;
3971 return;
3972 }
3973 /* queue might indeed be ready, schedule it */
3974 if (NULL != queue->transmit_task)
3975 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3976 queue->transmit_task =
3978 queue);
3980 "Considering transmission on queue `%s' QID %llu to %s\n",
3981 queue->address,
3982 (unsigned long long) queue->qid,
3983 GNUNET_i2s (&queue->neighbour->pid));
3984}
3985
3986
3993static void
3995{
3996 struct VirtualLink *vl = cls;
3997 struct DistanceVector *dv = vl->dv;
3998 struct Neighbour *n = vl->n;
3999 struct GNUNET_TIME_Absolute dvh_timeout;
4000 struct GNUNET_TIME_Absolute q_timeout;
4001
4003 "Checking if link is down\n");
4004 vl->visibility_task = NULL;
4005 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4006 if (NULL != dv)
4007 {
4008 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4009 pos = pos->next_dv)
4010 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4011 pos->path_valid_until);
4012 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4013 {
4014 vl->dv->vl = NULL;
4015 vl->dv = NULL;
4016 }
4017 }
4018 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4019 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4020 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4022 {
4023 vl->n->vl = NULL;
4024 vl->n = NULL;
4025 }
4026 if ((NULL == vl->n) && (NULL == vl->dv))
4027 {
4029 free_virtual_link (vl);
4030 return;
4031 }
4032 vl->visibility_task =
4033 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4035 vl);
4036}
4037
4038
4044static void
4046{
4047 struct Neighbour *neighbour = queue->neighbour;
4048 struct TransportClient *tc = queue->tc;
4049 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4051 struct QueueEntry *qe;
4052 int maxxed;
4053 struct PendingAcknowledgement *pa;
4054 struct VirtualLink *vl;
4055
4057 "Cleaning up queue %u\n", queue->qid);
4058 if (NULL != queue->mo)
4059 {
4061 queue->mo = NULL;
4062 }
4063 if (NULL != queue->transmit_task)
4064 {
4065 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4066 queue->transmit_task = NULL;
4067 }
4068 while (NULL != (pa = queue->pa_head))
4069 {
4070 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4071 pa->queue = NULL;
4072 }
4073
4075 neighbour->queue_head,
4076 neighbour->queue_tail,
4077 queue);
4079 tc->details.communicator.queue_head,
4080 tc->details.communicator.queue_tail,
4081 queue);
4083 tc->details.communicator.total_queue_length);
4085 "Cleaning up queue with length %u\n",
4086 queue->queue_length);
4087 while (NULL != (qe = queue->queue_head))
4088 {
4089 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4090 queue->queue_length--;
4091 tc->details.communicator.total_queue_length--;
4092 if (NULL != qe->pm)
4093 {
4094 GNUNET_assert (qe == qe->pm->qe);
4095 qe->pm->qe = NULL;
4096 }
4097 GNUNET_free (qe);
4098 }
4099 GNUNET_assert (0 == queue->queue_length);
4100 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4101 tc->details.communicator.total_queue_length))
4102 {
4103 /* Communicator dropped below threshold, resume all _other_ queues */
4105 GST_stats,
4106 "# Transmission throttled due to communicator queue limit",
4107 -1,
4108 GNUNET_NO);
4109 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4110 s = s->next_client)
4112 s,
4114 }
4115 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4117
4118 vl = lookup_virtual_link (&neighbour->pid);
4119 if ((NULL != vl) && (neighbour == vl->n))
4120 {
4122 check_link_down (vl);
4123 }
4124 if (NULL == neighbour->queue_head)
4125 {
4126 free_neighbour (neighbour, GNUNET_NO);
4127 }
4128}
4129
4130
4136static void
4138{
4139 struct TransportClient *tc = ale->tc;
4140
4141 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4142 tc->details.communicator.addr_tail,
4143 ale);
4144 if (NULL != ale->sc)
4145 {
4147 "store cancel\n");
4149 ale->sc = NULL;
4150 }
4151 if (NULL != ale->st)
4152 {
4154 ale->st = NULL;
4155 }
4156 if (NULL != ale->signed_address)
4158 GNUNET_free (ale);
4159}
4160
4161
4170static int
4172 const struct GNUNET_PeerIdentity *pid,
4173 void *value)
4174{
4175 struct TransportClient *tc = cls;
4176 struct PeerRequest *pr = value;
4177
4178 if (NULL != pr->nc)
4180 pr->nc = NULL;
4182 GNUNET_YES ==
4183 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4184 pid,
4185 pr));
4186 GNUNET_free (pr);
4187
4188 return GNUNET_OK;
4189}
4190
4191
4192static void
4193do_shutdown (void *cls);
4194
4203static void
4205 struct GNUNET_SERVICE_Client *client,
4206 void *app_ctx)
4207{
4208 struct TransportClient *tc = app_ctx;
4209
4210 (void) cls;
4211 (void) client;
4213 switch (tc->type)
4214 {
4215 case CT_NONE:
4217 "Unknown Client %p disconnected, cleaning up.\n",
4218 tc);
4219 break;
4220
4221 case CT_CORE: {
4222 struct PendingMessage *pm;
4224 "CORE Client %p disconnected, cleaning up.\n",
4225 tc);
4226
4227
4228 while (NULL != (pm = tc->details.core.pending_msg_head))
4229 {
4231 tc->details.core.pending_msg_head,
4232 tc->details.core.pending_msg_tail,
4233 pm);
4234 pm->client = NULL;
4235 }
4236 }
4237 break;
4238
4239 case CT_MONITOR:
4241 "MONITOR Client %p disconnected, cleaning up.\n",
4242 tc);
4243
4244 break;
4245
4246 case CT_COMMUNICATOR: {
4247 struct Queue *q;
4248 struct AddressListEntry *ale;
4249
4251 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4252 tc);
4253
4254 if (NULL != tc->details.communicator.free_queue_entry_task)
4256 tc->details.communicator.free_queue_entry_task);
4257 while (NULL != (q = tc->details.communicator.queue_head))
4258 free_queue (q);
4259 while (NULL != (ale = tc->details.communicator.addr_head))
4261 GNUNET_free (tc->details.communicator.address_prefix);
4262 }
4263 break;
4264
4265 case CT_APPLICATION:
4267 "APPLICATION Client %p disconnected, cleaning up.\n",
4268 tc);
4269
4270 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4272 tc);
4273 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4274 break;
4275 }
4276 GNUNET_free (tc);
4277 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4278 {
4280 "Our last client disconnected\n");
4281 do_shutdown (cls);
4282 }
4283}
4284
4285
4295static int
4297 const struct GNUNET_PeerIdentity *pid,
4298 void *value)
4299{
4300 struct TransportClient *tc = cls;
4301 struct VirtualLink *vl = value;
4302
4303 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4304 return GNUNET_OK;
4305
4307 "Telling new CORE client about existing connection to %s\n",
4308 GNUNET_i2s (pid));
4310 return GNUNET_OK;
4311}
4312
4313
4319static void
4321 unsigned
4322 int free_cmc);
4323
4324static enum GNUNET_GenericReturnValue
4326 const struct GNUNET_PeerIdentity *pid,
4327 void *value)
4328{
4329 struct VirtualLink *vl = value;
4330 struct CommunicatorMessageContext *cmc;
4331
4332 /* resume communicators */
4333 while (NULL != (cmc = vl->cmc_tail))
4334 {
4336 if (GNUNET_NO == cmc->continue_send)
4338 }
4339 return GNUNET_OK;
4340}
4341
4342
4351static void
4352handle_client_start (void *cls, const struct StartMessage *start)
4353{
4354 // const struct GNUNET_PeerIdentity *my_identity;
4355 struct TransportClient *tc = cls;
4356 // uint32_t options;
4357 //
4358 // my_identity = GNUNET_PILS_get_identity (pils);
4359 // GNUNET_assert (my_identity);
4360 //
4361 // FIXME ignore the check of the peer ids for now.
4362 // (also deprecate the old way of obtaining our own peer ID)
4363 // options = ntohl (start->options);
4364 // if ((0 != (1 & options)) &&
4365 // (0 != GNUNET_memcmp (&start->self, my_identity)))
4366 // {
4367 // /* client thinks this is a different peer, reject */
4368 // GNUNET_break (0);
4369 // GNUNET_SERVICE_client_drop (tc->client);
4370 // return;
4371 // }
4372 if (CT_NONE != tc->type)
4373 {
4374 GNUNET_break (0);
4376 return;
4377 }
4378 tc->type = CT_CORE;
4380 "New CORE client with PID %s registered\n",
4381 GNUNET_i2s (&start->self));
4384 tc);
4387 NULL);
4389}
4390
4391
4398static int
4399check_client_send (void *cls, const struct OutboundMessage *obm)
4400{
4401 struct TransportClient *tc = cls;
4402 uint16_t size;
4403 const struct GNUNET_MessageHeader *obmm;
4404
4405 if (CT_CORE != tc->type)
4406 {
4407 GNUNET_break (0);
4408 return GNUNET_SYSERR;
4409 }
4410 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4411 if (size < sizeof(struct GNUNET_MessageHeader))
4412 {
4413 GNUNET_break (0);
4414 return GNUNET_SYSERR;
4415 }
4416 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4417 if (size != ntohs (obmm->size))
4418 {
4419 GNUNET_break (0);
4420 return GNUNET_SYSERR;
4421 }
4422 return GNUNET_OK;
4423}
4424
4425
4433static void
4435{
4436 struct TransportClient *tc = pm->client;
4437 struct VirtualLink *vl = pm->vl;
4438
4440 "client send response\n");
4441 if (NULL != tc)
4442 {
4443 struct GNUNET_MQ_Envelope *env;
4444 struct SendOkMessage *so_msg;
4445
4447 so_msg->peer = vl->target;
4449 "Confirming transmission of <%" PRIu64 "> to %s\n",
4450 pm->logging_uuid,
4451 GNUNET_i2s (&vl->target));
4452 GNUNET_MQ_send (tc->mq, env);
4453 }
4455}
4456
4457
4467static unsigned int
4470 struct DistanceVectorHop **hops_array,
4471 unsigned int hops_array_length)
4472{
4473 uint64_t choices[hops_array_length];
4474 uint64_t num_dv;
4475 unsigned int dv_count;
4476
4477 /* Pick random vectors, but weighted by distance, giving more weight
4478 to shorter vectors */
4479 num_dv = 0;
4480 dv_count = 0;
4481 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4482 pos = pos->next_dv)
4483 {
4484 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4485 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4486 .rel_value_us == 0))
4487 continue; /* pos unconfirmed and confirmed required */
4488 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4489 dv_count++;
4490 }
4491 if (0 == dv_count)
4492 return 0;
4493 if (dv_count <= hops_array_length)
4494 {
4495 dv_count = 0;
4496 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4497 pos = pos->next_dv)
4498 hops_array[dv_count++] = pos;
4499 return dv_count;
4500 }
4501 for (unsigned int i = 0; i < hops_array_length; i++)
4502 {
4503 int ok = GNUNET_NO;
4504 while (GNUNET_NO == ok)
4505 {
4506 choices[i] =
4508 ok = GNUNET_YES;
4509 for (unsigned int j = 0; j < i; j++)
4510 if (choices[i] == choices[j])
4511 {
4512 ok = GNUNET_NO;
4513 break;
4514 }
4515 }
4516 }
4517 dv_count = 0;
4518 num_dv = 0;
4519 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4520 pos = pos->next_dv)
4521 {
4522 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4523
4524 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4525 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4526 .rel_value_us == 0))
4527 continue; /* pos unconfirmed and confirmed required */
4528 for (unsigned int i = 0; i < hops_array_length; i++)
4529 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4530 hops_array[dv_count++] = pos;
4531 num_dv += delta;
4532 }
4533 return dv_count;
4534}
4535
4536
4543static int
4545 void *cls,
4547{
4548 struct TransportClient *tc = cls;
4549 uint16_t size;
4550
4551 if (CT_NONE != tc->type)
4552 {
4553 GNUNET_break (0);
4554 return GNUNET_SYSERR;
4555 }
4556 tc->type = CT_COMMUNICATOR;
4557 size = ntohs (cam->header.size) - sizeof(*cam);
4558 if (0 == size)
4559 return GNUNET_OK; /* receive-only communicator */
4561 return GNUNET_OK;
4562}
4563
4564
4570static void
4572 unsigned
4573 int free_cmc)
4574{
4575 if (0 != ntohl (cmc->im.fc_on))
4576 {
4577 /* send ACK when done to communicator for flow control! */
4578 struct GNUNET_MQ_Envelope *env;
4580
4582 "Acknowledge message with flow control id %" PRIu64 "\n",
4583 cmc->im.fc_id);
4585 ack->reserved = htonl (0);
4586 ack->fc_id = cmc->im.fc_id;
4587 ack->sender = cmc->im.neighbour_sender;
4588 GNUNET_MQ_send (cmc->tc->mq, env);
4589 }
4590
4592
4593 if (GNUNET_YES == free_cmc)
4594 {
4595 GNUNET_free (cmc);
4596 }
4597}
4598
4599
4600static void
4605
4606
4616static void
4617handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4618{
4619 struct TransportClient *tc = cls;
4620 struct VirtualLink *vl;
4621 uint32_t delta;
4622 struct CommunicatorMessageContext *cmc;
4623
4624 if (CT_CORE != tc->type)
4625 {
4626 GNUNET_break (0);
4628 return;
4629 }
4630 vl = lookup_virtual_link (&rom->peer);
4631 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4632 {
4634 "# RECV_OK dropped: virtual link unknown",
4635 1,
4636 GNUNET_NO);
4638 return;
4639 }
4640 delta = ntohl (rom->increase_window_delta);
4641 vl->core_recv_window += delta;
4643 "CORE ack receiving message, increased CORE recv window to %d\n",
4644 vl->core_recv_window);
4646 if (vl->core_recv_window <= 0)
4647 return;
4648 /* resume communicators */
4649 while (NULL != (cmc = vl->cmc_tail))
4650 {
4652 if (GNUNET_NO == cmc->continue_send)
4654 }
4655}
4656
4657
4664static void
4666 void *cls,
4668{
4669 const struct GNUNET_PeerIdentity *my_identity;
4670 struct TransportClient *tc = cls;
4671 uint16_t size;
4672
4673 size = ntohs (cam->header.size) - sizeof(*cam);
4674 if (0 == size)
4675 {
4677 "Receive-only communicator connected\n");
4678 return; /* receive-only communicator */
4679 }
4680 tc->details.communicator.address_prefix =
4681 GNUNET_strdup ((const char *) &cam[1]);
4682 tc->details.communicator.cc = ntohl (cam->cc);
4683 tc->details.communicator.can_burst = ntohl (cam->can_burst);
4685 if (NULL != my_identity)
4686 {
4688 "Communicator for peer %s with prefix '%s' connected %s\n",
4690 tc->details.communicator.address_prefix,
4691 tc->details.communicator.can_burst ? "can burst" :
4692 "can not burst");
4693 }
4694 else
4695 {
4697 "Communicator for local peer with prefix '%s' connected %s\n",
4698 tc->details.communicator.address_prefix,
4699 tc->details.communicator.can_burst ? "can burst" :
4700 "can not burst");
4701 }
4703}
4704
4705
4713static int
4715 void *cls,
4717{
4718 const struct GNUNET_MessageHeader *inbox;
4719 const char *is;
4720 uint16_t msize;
4721 uint16_t isize;
4722
4723 (void) cls;
4724 msize = ntohs (cb->header.size) - sizeof(*cb);
4725 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4726 isize = ntohs (inbox->size);
4727 if (isize >= msize)
4728 {
4729 GNUNET_break (0);
4730 return GNUNET_SYSERR;
4731 }
4732 is = (const char *) inbox;
4733 is += isize;
4734 msize -= isize;
4735 GNUNET_assert (0 < msize);
4736 if ('\0' != is[msize - 1])
4737 {
4738 GNUNET_break (0);
4739 return GNUNET_SYSERR;
4740 }
4741 return GNUNET_OK;
4742}
4743
4744
4746{
4749};
4750
4751
4752static void
4753sign_dv_cb (void *cls,
4754 const struct GNUNET_PeerIdentity *pid,
4755 const struct GNUNET_CRYPTO_EddsaSignature *sig)
4756{
4757 struct SignDvCls *sign_dv_cls = cls;
4758 struct DistanceVector *dv = sign_dv_cls->dv;
4759 struct PilsRequest *pr = sign_dv_cls->req;
4760
4761 pr->op = NULL;
4764 pr);
4765 GNUNET_free (pr);
4766
4767 dv->sender_sig = *sig;
4768}
4769
4770
4776static void
4778{
4779 struct EphemeralConfirmationPS ec;
4780 struct SignDvCls *sign_dv_cls;
4781
4786 ec.target = dv->target;
4789 ec.purpose.size = htonl (sizeof(ec));
4790 sign_dv_cls = GNUNET_new (struct SignDvCls);
4791 sign_dv_cls->req = GNUNET_new (struct PilsRequest);
4792 sign_dv_cls->dv = dv;
4795 sign_dv_cls->req);
4797 &ec.purpose,
4798 sign_dv_cb,
4799 sign_dv_cls);
4800}
4801
4802
4803static void
4805 struct TransportClient *tc);
4806
4807
4808static void
4810{
4811 struct TransportClient *tc = cls;
4813
4815 "freeing timedout queue entries\n");
4816
4817 tc->details.communicator.free_queue_entry_task = NULL;
4818 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4819 queue = queue->next_client)
4820 {
4821 struct QueueEntry *qep = queue->queue_head;
4822
4824 "checking QID %u for timedout queue entries\n",
4825 queue->qid);
4826 while (NULL != qep)
4827 {
4828 struct QueueEntry *pos = qep;
4830 pos->creation_timestamp, now);
4831 qep = qep->next;
4832
4834 "diff to now %s \n",
4837 {
4839 "Freeing timed out QueueEntry with MID %" PRIu64
4840 " and QID %u\n",
4841 pos->mid,
4842 queue->qid);
4843 free_queue_entry (pos, tc);
4844 }
4845 }
4846 }
4847}
4848
4849
4859static void
4861 struct PendingMessage *pm,
4862 const void *payload,
4863 size_t payload_size)
4864{
4865 struct Neighbour *n = queue->neighbour;
4867 struct GNUNET_MQ_Envelope *env;
4868 struct PendingAcknowledgement *pa;
4869
4870 GNUNET_log (
4872 "Queueing %u bytes of payload for transmission <%" PRIu64
4873 "> on queue %llu to %s\n",
4874 (unsigned int) payload_size,
4875 (NULL == pm) ? 0 : pm->logging_uuid,
4876 (unsigned long long) queue->qid,
4877 GNUNET_i2s (&queue->neighbour->pid));
4878 env = GNUNET_MQ_msg_extra (smt,
4879 payload_size,
4881 smt->qid = htonl (queue->qid);
4882 smt->mid = GNUNET_htonll (queue->mid_gen);
4883 smt->receiver = n->pid;
4884 memcpy (&smt[1], payload, payload_size);
4885 {
4886 /* Pass the env to the communicator of queue for transmission. */
4887 struct QueueEntry *qe;
4888
4889 qe = GNUNET_new (struct QueueEntry);
4890 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4891 qe->mid = queue->mid_gen;
4893 "Create QueueEntry with MID %" PRIu64
4894 " and QID %u and prefix %s\n",
4895 qe->mid,
4896 queue->qid,
4897 queue->tc->details.communicator.address_prefix);
4898 queue->mid_gen++;
4899 qe->queue = queue;
4900 if (NULL != pm)
4901 {
4902 qe->pm = pm;
4903 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4904 // GNUNET_assert (NULL == pm->qe);
4905 if (NULL != pm->qe)
4906 {
4908 "Retransmitting message <%" PRIu64
4909 "> remove pm from qe with MID: %llu \n",
4910 pm->logging_uuid,
4911 (unsigned long long) pm->qe->mid);
4912 pm->qe->pm = NULL;
4913 }
4914 pm->qe = qe;
4915 }
4916 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4917 if (0 == queue->q_capacity)
4918 {
4919 // Messages without FC or fragments can get here.
4920 if (NULL != pm)
4921 {
4923 "Message %" PRIu64
4924 " (pm type %u) was not send because queue has no capacity.\n",
4925 pm->logging_uuid,
4926 pm->pmt);
4927 pm->qe = NULL;
4928 }
4929 GNUNET_free (env);
4930 GNUNET_free (qe);
4931 return;
4932 }
4933 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4934 queue->queue_length++;
4935 queue->tc->details.communicator.total_queue_length++;
4936 if (GNUNET_NO == queue->unlimited_length)
4937 queue->q_capacity--;
4939 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4940 queue->address,
4941 queue->qid,
4942 queue->q_capacity);
4944 queue->tc->details.communicator.total_queue_length)
4945 queue->idle = GNUNET_NO;
4946 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4947 queue->idle = GNUNET_NO;
4948 if (0 == queue->q_capacity)
4949 queue->idle = GNUNET_NO;
4950
4951 if (GNUNET_NO == queue->idle)
4952 {
4953 struct TransportClient *tc = queue->tc;
4954
4955 if (NULL == tc->details.communicator.free_queue_entry_task)
4956 tc->details.communicator.free_queue_entry_task =
4958 &
4960 tc);
4961 }
4962 if (NULL != pm && NULL != (pa = pm->pa_head))
4963 {
4964 while (pm != pa->pm)
4965 pa = pa->next_pa;
4966 pa->num_send++;
4967 }
4968 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4970 "Sending message MID %" PRIu64
4971 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4972 PRIu64 "\n",
4973 GNUNET_ntohll (smt->mid),
4974 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4975 ntohs (smt->header.size),
4976 (unsigned long) payload_size,
4977 queue->tc->mq,
4978 queue->address,
4979 queue->qid,
4980 (NULL == pm) ? 0 : pm->logging_uuid);
4981 GNUNET_MQ_send (queue->tc->mq, env);
4982 }
4983}
4984
4985
4996static struct GNUNET_TIME_Relative
4998 const struct GNUNET_MessageHeader *hdr,
5000{
5001 struct GNUNET_TIME_Absolute now;
5002 unsigned int candidates;
5003 unsigned int sel1;
5004 unsigned int sel2;
5005 struct GNUNET_TIME_Relative rtt;
5006
5007 /* Pick one or two 'random' queues from n (under constraints of options) */
5008 now = GNUNET_TIME_absolute_get ();
5009 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
5010 weight in the future; weight could be assigned by observed
5011 bandwidth (note: not sure if we should do this for this type
5012 of control traffic though). */
5013 candidates = 0;
5014 for (struct Queue *pos = n->queue_head; NULL != pos;
5015 pos = pos->next_neighbour)
5016 {
5017 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5018 (pos->validated_until.abs_value_us > now.abs_value_us))
5019 candidates++;
5020 }
5021 if (0 == candidates)
5022 {
5023 /* This can happen rarely if the last confirmed queue timed
5024 out just as we were beginning to process this message. */
5026 "Could not route message of type %u to %s: no valid queue\n",
5027 ntohs (hdr->type),
5028 GNUNET_i2s (&n->pid));
5030 "# route selection failed (all no valid queue)",
5031 1,
5032 GNUNET_NO);
5034 }
5035
5038 if (0 == (options & RMO_REDUNDANT))
5039 sel2 = candidates; /* picks none! */
5040 else
5042 candidates = 0;
5043 for (struct Queue *pos = n->queue_head; NULL != pos;
5044 pos = pos->next_neighbour)
5045 {
5046 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5047 (pos->validated_until.abs_value_us > now.abs_value_us))
5048 {
5049 if ((sel1 == candidates) || (sel2 == candidates))
5050 {
5052 "Routing message of type %u to %s using %s (#%u)\n",
5053 ntohs (hdr->type),
5054 GNUNET_i2s (&n->pid),
5055 pos->address,
5056 (sel1 == candidates) ? 1 : 2);
5057 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5058 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5059 }
5060 candidates++;
5061 }
5062 }
5063 return rtt;
5064}
5065
5066
5071{
5075 gcry_cipher_hd_t cipher;
5076
5080 struct
5081 {
5086
5090 char aes_key[256 / 8];
5091
5095 char aes_ctr[128 / 8];
5097};
5098
5099
5108static void
5110 const struct GNUNET_ShortHashCode *iv,
5111 struct DVKeyState *key)
5112{
5113 /* must match what we defive from decapsulated key */
5116 &key->material,
5117 sizeof(key->material),
5118 km,
5119 GNUNET_CRYPTO_kdf_arg_string ("gnunet-transport-dv-key"),
5123 "Deriving backchannel key based on KM %s and IV %s\n",
5124 GNUNET_sh2s (km),
5125 GNUNET_sh2s (iv));
5126 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5127 GCRY_CIPHER_AES256 /* low level: go for speed */
5128 ,
5129 GCRY_CIPHER_MODE_CTR,
5130 0 /* flags */));
5131 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5132 &key->material.aes_key,
5133 sizeof(key->material.aes_key)));
5134 gcry_cipher_setctr (key->cipher,
5135 &key->material.aes_ctr,
5136 sizeof(key->material.aes_ctr));
5137}
5138
5139
5149static void
5150dv_hmac (const struct DVKeyState *key,
5151 struct GNUNET_HashCode *hmac,
5152 const void *data,
5153 size_t data_size)
5154{
5155 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5156}
5157
5158
5168static void
5169dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5170{
5171 GNUNET_assert (0 ==
5172 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5173}
5174
5175
5186static enum GNUNET_GenericReturnValue
5188 void *out,
5189 const void *ciph,
5190 size_t out_size)
5191{
5192 return (0 ==
5193 gcry_cipher_decrypt (key->cipher,
5194 out, out_size,
5195 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5196}
5197
5198
5204static void
5206{
5207 gcry_cipher_close (key->cipher);
5208 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5209}
5210
5211
5222typedef void (*DVMessageHandler) (void *cls,
5223 struct Neighbour *next_hop,
5224 const struct GNUNET_MessageHeader *hdr,
5226
5241static struct GNUNET_TIME_Relative
5243 unsigned int num_dvhs,
5244 struct DistanceVectorHop **dvhs,
5245 const struct GNUNET_MessageHeader *hdr,
5246 DVMessageHandler use,
5247 void *use_cls,
5249 enum GNUNET_GenericReturnValue without_fc)
5250{
5251 const struct GNUNET_PeerIdentity *my_identity;
5252 struct TransportDVBoxMessage box_hdr;
5253 struct TransportDVBoxPayloadP payload_hdr;
5254 uint16_t enc_body_size = ntohs (hdr->size);
5255 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5256 struct DVKeyState *key;
5257 struct GNUNET_TIME_Relative rtt;
5258 struct GNUNET_ShortHashCode km;
5259
5262
5263 key = GNUNET_new (struct DVKeyState);
5264 /* Encrypt payload */
5266 box_hdr.total_hops = htons (0);
5267 box_hdr.without_fc = htons (without_fc);
5268 // update_ephemeral (dv);
5269 if (0 ==
5270 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5271 {
5272 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5273 &dv->ephemeral_key,
5274 &km);
5275 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5276 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5277 sign_ephemeral (dv);
5278 }
5279 box_hdr.ephemeral_key = dv->ephemeral_key;
5280 payload_hdr.sender_sig = dv->sender_sig;
5281
5283 &box_hdr.iv,
5284 sizeof(box_hdr.iv));
5285 // We are creating this key, so this must work.
5286 // FIXME: Possibly also add return values here. We are processing
5287 // Input from other peers...
5288 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5289 payload_hdr.sender = *my_identity;
5290 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5291 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5292 dv_encrypt (key,
5293 hdr,
5294 &enc[sizeof(struct TransportDVBoxPayloadP)],
5295 enc_body_size);
5296 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5297 dv_key_clean (key);
5299 /* For each selected path, take the pre-computed header and body
5300 and add the path in the middle of the message; then send it. */
5301 for (unsigned int i = 0; i < num_dvhs; i++)
5302 {
5303 struct DistanceVectorHop *dvh = dvhs[i];
5304 unsigned int num_hops = dvh->distance + 1;
5305 char buf[sizeof(struct TransportDVBoxMessage)
5306 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5307 + sizeof(struct TransportDVBoxPayloadP)
5308 + enc_body_size] GNUNET_ALIGN;
5309 struct GNUNET_PeerIdentity *dhops;
5310
5311 box_hdr.header.size = htons (sizeof(buf));
5312 box_hdr.orig_size = htons (sizeof(buf));
5313 box_hdr.num_hops = htons (num_hops);
5314 memcpy (buf, &box_hdr, sizeof(box_hdr));
5315 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5316 memcpy (dhops,
5317 dvh->path,
5318 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5319 dhops[dvh->distance] = dv->target;
5320 if (GNUNET_EXTRA_LOGGING > 0)
5321 {
5322 char *path;
5323
5325 for (unsigned int j = 0; j < num_hops; j++)
5326 {
5327 char *tmp;
5328
5329 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5330 GNUNET_free (path);
5331 path = tmp;
5332 }
5334 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5335 ntohs (hdr->type),
5336 GNUNET_i2s (&dv->target),
5337 i + 1,
5338 num_dvhs,
5339 path);
5340 GNUNET_free (path);
5341 }
5342 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5343 memcpy (&dhops[num_hops], enc, sizeof(enc));
5344 use (use_cls,
5345 dvh->next_hop,
5346 (const struct GNUNET_MessageHeader *) buf,
5347 options);
5348 GNUNET_free (key);
5349 }
5350 return rtt;
5351}
5352
5353
5363static void
5365 struct Neighbour *next_hop,
5366 const struct GNUNET_MessageHeader *hdr,
5368{
5369 (void) cls;
5370 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5371}
5372
5373
5385static struct GNUNET_TIME_Relative
5387// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5388 const struct GNUNET_MessageHeader *hdr,
5390{
5391 // struct VirtualLink *vl;
5392 struct Neighbour *n;
5393 struct DistanceVector *dv;
5394 struct GNUNET_TIME_Relative rtt1;
5395 struct GNUNET_TIME_Relative rtt2;
5396 const struct GNUNET_PeerIdentity *target = &vl->target;
5397
5399 "Trying to route message of type %u to %s without fc\n",
5400 ntohs (hdr->type),
5401 GNUNET_i2s (target));
5402
5403 // TODO Do this elsewhere. vl should be given as parameter to method.
5404 // vl = lookup_virtual_link (target);
5405 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5406 if (NULL == vl)
5408 n = vl->n;
5409 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5410 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5411 {
5412 /* if confirmed is required, and we do not have anything
5413 confirmed, drop respective options */
5414 if (NULL == n)
5415 n = lookup_neighbour (target);
5416 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5418 }
5419 if ((NULL == n) && (NULL == dv))
5420 {
5422 "Cannot route message of type %u to %s: no route\n",
5423 ntohs (hdr->type),
5424 GNUNET_i2s (target));
5426 "# Messages dropped in routing: no acceptable method",
5427 1,
5428 GNUNET_NO);
5430 }
5432 "Routing message of type %u to %s with options %X\n",
5433 ntohs (hdr->type),
5434 GNUNET_i2s (target),
5435 (unsigned int) options);
5436 /* If both dv and n are possible and we must choose:
5437 flip a coin for the choice between the two; for now 50/50 */
5438 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5439 {
5441 n = NULL;
5442 else
5443 dv = NULL;
5444 }
5445 if ((NULL != n) && (NULL != dv))
5446 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5447 enough for redundancy, so clear the flag. */
5450 if (NULL != n)
5451 {
5453 "Try to route message of type %u to %s without fc via neighbour\n",
5454 ntohs (hdr->type),
5455 GNUNET_i2s (target));
5456 rtt1 = route_via_neighbour (n, hdr, options);
5457 }
5458 if (NULL != dv)
5459 {
5460 struct DistanceVectorHop *hops[2];
5461 unsigned int res;
5462
5464 options,
5465 hops,
5466 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5467 if (0 == res)
5468 {
5470 "Failed to route message, could not determine DV path\n");
5471 return rtt1;
5472 }
5474 "encapsulate_for_dv 1\n");
5475 rtt2 = encapsulate_for_dv (dv,
5476 res,
5477 hops,
5478 hdr,
5480 NULL,
5482 GNUNET_YES);
5483 }
5484 return GNUNET_TIME_relative_min (rtt1, rtt2);
5485}
5486
5487
5488static void
5489consider_sending_fc (void *cls);
5490
5497static void
5499{
5500 struct VirtualLink *vl = cls;
5501 vl->fc_retransmit_task = NULL;
5502 consider_sending_fc (cls);
5503}
5504
5505
5506static char *
5507get_address_without_port (const char *address);
5508
5509
5511{
5512 size_t off;
5513 char *tgnas;
5514};
5515
5516
5517static enum GNUNET_GenericReturnValue
5519 const struct GNUNET_PeerIdentity *pid,
5520 void *value)
5521{
5522 struct AddGlobalAddressesContext *ctx = cls;
5523 struct TransportGlobalNattedAddress *tgna = value;
5524 char *addr = (char *) &tgna[1];
5525
5527 "sending address %s length %u\n",
5528 addr,
5529 ntohl (tgna->address_length));
5530 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5532 + ntohl (tgna->address_length));
5533 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5535
5536 return GNUNET_OK;
5537}
5538
5539
5540static struct GNUNET_TIME_Relative
5541calculate_rtt (struct DistanceVector *dv);
5542
5543
5550static void
5552{
5553 struct VirtualLink *vl = cls;
5554 struct GNUNET_TIME_Absolute monotime;
5555 struct TransportFlowControlMessage *fc;
5557 struct GNUNET_TIME_Relative rtt;
5558 struct GNUNET_TIME_Relative rtt_average;
5559 struct Neighbour *n = vl->n;
5560
5561 if (NULL != n && 0 < n->number_of_addresses)
5562 {
5563 size_t addresses_size =
5564 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5565 ->size_of_global_addresses;
5566 char *tgnas = GNUNET_malloc (addresses_size);
5568 ctx.off = 0;
5569 ctx.tgnas = tgnas;
5570
5572 + addresses_size);
5573 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5574 + addresses_size);
5575 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5576 fc->number_of_addresses = htonl (n->number_of_addresses);
5577 GNUNET_CONTAINER_multipeermap_iterate (n->natted_addresses,
5579 &ctx);
5582 }
5583 else
5584 {
5585 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5586 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5587 }
5588
5590 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5591 it always! */
5592 /* For example, we should probably ONLY do this if a bit more than
5593 an RTT has passed, or if the window changed "significantly" since
5594 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5595 need an estimate for the bandwidth-delay-product for the entire
5596 VL, as that determines "significantly". We have the delay, but
5597 the bandwidth statistics need to be added for the VL!*/(void) duration;
5598
5599 if (NULL != vl->dv)
5600 rtt_average = calculate_rtt (vl->dv);
5601 else
5602 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5603 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5605 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5606 (unsigned int) vl->fc_seq_gen,
5607 GNUNET_i2s (&vl->target),
5608 (unsigned long long) vl->incoming_fc_window_size,
5609 (unsigned long) rtt_average.rel_value_us,
5610 vl->sync_ready);
5612 vl->last_fc_transmission = monotime;
5613 fc->sync_ready = vl->sync_ready;
5615 fc->seq = htonl (vl->fc_seq_gen++);
5616 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5619 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5620 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5621 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5623 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5624 {
5627 "FC retransmission to %s failed, will retry in %s\n",
5628 GNUNET_i2s (&vl->target),
5631 }
5632 else
5633 {
5634 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5635 vl->last_fc_rtt = rtt;
5636 }
5637 if (NULL != vl->fc_retransmit_task)
5640 {
5642 vl->fc_retransmit_count = 0;
5643 }
5644 vl->fc_retransmit_task =
5646 vl->fc_retransmit_count++;
5647 GNUNET_free (fc);
5648}
5649
5650
5667static void
5669{
5670 struct Neighbour *n = vl->n;
5671 struct DistanceVector *dv = vl->dv;
5672 struct GNUNET_TIME_Absolute now;
5673 struct VirtualLink *vl_next_hop;
5674 int elig;
5675
5677 "check_vl_transmission to target %s\n",
5678 GNUNET_i2s (&vl->target));
5679 /* Check that we have an eligible pending message!
5680 (cheaper than having #transmit_on_queue() find out!) */
5681 elig = GNUNET_NO;
5682 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5683 pm = pm->next_vl)
5684 {
5686 "check_vl_transmission loop\n");
5687 if (NULL != pm->qe)
5688 continue; /* not eligible, is in a queue! */
5689 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5691 {
5693 "Stalled message %" PRIu64
5694 " transmission on VL %s due to flow control: %llu < %llu\n",
5695 pm->logging_uuid,
5696 GNUNET_i2s (&vl->target),
5697 (unsigned long long) vl->outbound_fc_window_size,
5698 (unsigned long long) (pm->bytes_msg
5701 return; /* We have a message, but flow control says "nope" */
5702 }
5704 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5705 GNUNET_i2s (&vl->target));
5706 /* Notify queues at direct neighbours that we are interested */
5707 now = GNUNET_TIME_absolute_get ();
5708 if (NULL != n)
5709 {
5710 for (struct Queue *queue = n->queue_head; NULL != queue;
5711 queue = queue->next_neighbour)
5712 {
5713 if ((GNUNET_YES == queue->idle) &&
5714 (queue->validated_until.abs_value_us > now.abs_value_us))
5715 {
5717 "Direct neighbour %s not stalled\n",
5718 GNUNET_i2s (&n->pid));
5720 queue,
5722 elig = GNUNET_YES;
5723 }
5724 else
5726 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5727 queue->qid,
5728 queue->idle);
5729 }
5730 }
5731 /* Notify queues via DV that we are interested */
5732 if (NULL != dv)
5733 {
5734 /* Do DV with lower scheduler priority, which effectively means that
5735 IF a neighbour exists and is available, we prefer it. */
5736 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5737 pos = pos->next_dv)
5738 {
5739 struct Neighbour *nh_iter = pos->next_hop;
5740
5741
5742 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5743 continue; /* skip this one: path not validated */
5744 else
5745 {
5746 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5747 GNUNET_assert (NULL != vl_next_hop);
5748 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5749 vl_next_hop->outbound_fc_window_size)
5750 {
5752 "Stalled message %" PRIu64
5753 " transmission on next hop %s due to flow control: %llu < %llu\n",
5754 pm->logging_uuid,
5755 GNUNET_i2s (&vl_next_hop->target),
5756 (unsigned long
5757 long) vl_next_hop->outbound_fc_window_size,
5758 (unsigned long long) (pm->bytes_msg
5759 + vl_next_hop->
5760 outbound_fc_window_size_used));
5761 consider_sending_fc (vl_next_hop);
5762 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5763 }
5764 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5765 queue = queue->next_neighbour)
5766 if ((GNUNET_YES == queue->idle) &&
5767 (queue->validated_until.abs_value_us > now.abs_value_us))
5768 {
5770 "Next hop neighbour %s not stalled\n",
5771 GNUNET_i2s (&nh_iter->pid));
5773 queue,
5775 elig = GNUNET_YES;
5776 }
5777 else
5779 "DV Queue QID: %u (%u) busy or invalid\n",
5780 queue->qid,
5781 queue->idle);
5782 }
5783 }
5784 }
5785 if (GNUNET_YES == elig)
5787 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5788 pm->logging_uuid,
5789 pm->bytes_msg,
5790 GNUNET_i2s (&vl->target),
5791 (unsigned long long) vl->outbound_fc_window_size,
5792 (unsigned long long) (pm->bytes_msg
5794 break;
5795 }
5796}
5797
5798
5805static void
5806handle_client_send (void *cls, const struct OutboundMessage *obm)
5807{
5808 struct TransportClient *tc = cls;
5809 struct PendingMessage *pm;
5810 const struct GNUNET_MessageHeader *obmm;
5811 uint32_t bytes_msg;
5812 struct VirtualLink *vl;
5814
5815 GNUNET_assert (CT_CORE == tc->type);
5816 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5817 bytes_msg = ntohs (obmm->size);
5818 pp = ntohl (obm->priority);
5819 vl = lookup_virtual_link (&obm->peer);
5820 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5821 {
5823 "Don't have %s as a neighbour (anymore).\n",
5824 GNUNET_i2s (&obm->peer));
5825 /* Failure: don't have this peer as a neighbour (anymore).
5826 Might have gone down asynchronously, so this is NOT
5827 a protocol violation by CORE. Still count the event,
5828 as this should be rare. */
5831 "# messages dropped (neighbour unknown)",
5832 1,
5833 GNUNET_NO);
5834 return;
5835 }
5836
5837 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5839 "1 created pm %p storing vl %p\n",
5840 pm,
5841 vl);
5842 pm->logging_uuid = logging_uuid_gen++;
5843 pm->prefs = pp;
5844 pm->client = tc;
5845 pm->vl = vl;
5846 pm->bytes_msg = bytes_msg;
5847 memcpy (&pm[1], obmm, bytes_msg);
5849 "Sending message of type %u with %u bytes as <%" PRIu64
5850 "> to %s\n",
5851 ntohs (obmm->type),
5852 bytes_msg,
5853 pm->logging_uuid,
5854 GNUNET_i2s (&obm->peer));
5856 tc->details.core.pending_msg_head,
5857 tc->details.core.pending_msg_tail,
5858 pm);
5860 vl->pending_msg_head,
5861 vl->pending_msg_tail,
5862 pm);
5865}
5866
5867
5877static void
5879 void *cls,
5881{
5882 struct Neighbour *n;
5883 struct VirtualLink *vl;
5884 struct TransportClient *tc = cls;
5885 const struct GNUNET_MessageHeader *inbox =
5886 (const struct GNUNET_MessageHeader *) &cb[1];
5887 uint16_t isize = ntohs (inbox->size);
5888 const char *is = ((const char *) &cb[1]) + isize;
5889 size_t slen = strlen (is) + 1;
5890 char
5891 mbuf[slen + isize
5892 + sizeof(struct
5896
5897 /* 0-termination of 'is' was checked already in
5898 #check_communicator_backchannel() */
5900 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5901 GNUNET_i2s (&cb->pid),
5902 is,
5903 ntohs (inbox->type),
5904 ntohs (inbox->size));
5905 /* encapsulate and encrypt message */
5906 be->header.type =
5908 be->header.size = htons (sizeof(mbuf));
5909 memcpy (&be[1], inbox, isize);
5910 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5911 + isize],
5912 is,
5913 strlen (is) + 1);
5914 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5915 vl = lookup_virtual_link (&cb->pid);
5916 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5917 {
5919 }
5920 else
5921 {
5922 /* Use route via neighbour */
5923 n = lookup_neighbour (&cb->pid);
5924 if (NULL != n)
5926 n,
5927 &be->header,
5928 RMO_NONE);
5929 }
5931}
5932
5933
5941static int
5943 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5944{
5945 struct TransportClient *tc = cls;
5946
5947 if (CT_COMMUNICATOR != tc->type)
5948 {
5949 GNUNET_break (0);
5950 return GNUNET_SYSERR;
5951 }
5953 return GNUNET_OK;
5954}
5955
5956
5962static void
5963store_pi (void *cls);
5964
5965
5970{
5971
5976
5981
5982
5987};
5988
5989
5990static void
5991shc_cont (void *cls, int success)
5992{
5993 struct PilsAddressSignContext *pc = cls;
5994
5995 GNUNET_assert (NULL == pc->req);
5996 if (GNUNET_OK != success)
5997 {
5999 "Failed to store our address `%s' with peerstore\n",
6000 pc->ale->address);
6001 if (NULL == pc->ale->st)
6002 {
6004 &store_pi,
6005 pc->ale);
6006 }
6007 }
6008 GNUNET_free (pc);
6009}
6010
6011
6015static void
6017 const struct GNUNET_PeerIdentity *pid,
6018 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6019{
6020 struct PilsAddressSignContext *pc = cls;
6021 struct GNUNET_MQ_Envelope *env;
6022 const struct GNUNET_MessageHeader *msg;
6023
6024 pc->req->op = NULL;
6027 pc->req);
6028 GNUNET_free (pc->req);
6029 pc->req = NULL;
6032 pid,
6033 sig,
6034 pc->et);
6037 "store_pi 1\n");
6039 msg,
6040 shc_cont,
6041 pc);
6042 GNUNET_free (env);
6043}
6044
6045
6052static void
6053peerstore_store_own_cb (void *cls, int success)
6054{
6055 struct PilsAddressSignContext *pc = cls;
6056
6057 pc->ale->sc = NULL;
6058 if (GNUNET_YES != success)
6060 "Failed to store our own address `%s' in peerstore!\n",
6061 pc->ale->address);
6062 else
6064 "Successfully stored our own address `%s' in peerstore!\n",
6065 pc->ale->address);
6066 /* refresh period is 1/4 of expiration time, that should be plenty
6067 without being excessive. */
6068 if (NULL == pc->ale->st)
6069 {
6070 pc->ale->st =
6072 GNUNET_TIME_relative_divide (pc->ale->expiration,
6073 4ULL),
6074 &store_pi,
6075 pc->ale);
6076 }
6077
6078 /* Now we have to update our HELLO! */
6080 pc->req = GNUNET_new (struct PilsRequest);
6083 pc->req);
6084 pc->req->op = GNUNET_PILS_sign_hello (pils,
6086 pc->et,
6088 pc);
6089}
6090
6091
6092// This function
6093static void
6095 const struct GNUNET_PeerIdentity *pid,
6096 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6097{
6098 struct PilsAddressSignContext *pc = cls;
6099 char *sig_str;
6100 void *result;
6101 size_t result_size;
6102
6103 pc->req->op = NULL;
6106 pc->req);
6107 GNUNET_free (pc->req);
6108 sig_str = NULL;
6109 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6110 result_size =
6111 1 + GNUNET_asprintf (
6112 (char **) &result,
6113 "%s;%llu;%u;%s",
6114 sig_str,
6115 (unsigned long long) pc->et.abs_value_us,
6116 (unsigned int) pc->ale->nt,
6117 pc->ale->address);
6118 GNUNET_free (sig_str);
6119
6121 "Build our HELLO URI `%s'\n",
6122 (char*) result);
6123
6124 pc->ale->signed_address = result;
6125 pc->ale->signed_address_len = result_size;
6127
6128 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6130 "transport",
6131 pid,
6133 result,
6134 result_size,
6135 expiration,
6138 pc);
6139}
6140
6141
6162
6163
6177void
6179 struct AddressListEntry *ale,
6180 struct GNUNET_TIME_Absolute mono_time)
6181{
6182 struct SignedAddress sa;
6183 struct PilsAddressSignContext *pc;
6184
6186 sa.purpose.size = htonl (sizeof(sa));
6187 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6188 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6190 pc->ale = ale;
6191 pc->et = mono_time;
6192 pc->req = GNUNET_new (struct PilsRequest);
6194 &sa.purpose,
6196 pc);
6199 pc->req);
6200}
6201
6202
6208static void
6209store_pi (void *cls)
6210{
6211 struct AddressListEntry *ale = cls;
6212 const char *dash;
6213 char *address_uri;
6214 char *prefix;
6215 unsigned int add_success;
6216
6217 if (NULL == GNUNET_PILS_get_identity (pils))
6218 {
6220 &store_pi,
6221 ale);
6222 return;
6223 }
6225 dash = strchr (ale->address, '-');
6226 GNUNET_assert (NULL != dash);
6227 dash++;
6228 GNUNET_asprintf (&address_uri,
6229 "%s://%s",
6230 prefix,
6231 dash);
6233 ale->st = NULL;
6235 "Storing our address `%s' in peerstore until %s!\n",
6236 ale->address,
6239 address_uri);
6240 if (GNUNET_OK != add_success)
6241 {
6243 "Storing our address `%s' %s\n",
6244 address_uri,
6245 GNUNET_NO == add_success ? "not done" : "failed");
6246 GNUNET_free (address_uri);
6247 return;
6248 }
6249 else
6250 {
6251
6253 "Storing our address `%s'\n",
6254 address_uri);
6255 }
6256 // FIXME hello_mono_time used here?? What about expiration in ale?
6257 pils_sign_address (ale,
6259 // TODO keep track of op and potentially cancel/clean
6260 GNUNET_free (address_uri);
6261}
6262
6263
6264static struct AddressListEntry *
6268 const char *address,
6269 uint32_t aid,
6270 size_t slen)
6271{
6272 struct AddressListEntry *ale;
6273 char *address_without_port;
6274
6275 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6276 ale->tc = tc;
6277 ale->address = (const char *) &ale[1];
6278 ale->expiration = expiration;
6279 ale->aid = aid;
6280 ale->nt = nt;
6281 memcpy (&ale[1], address, slen);
6282 address_without_port = get_address_without_port (ale->address);
6284 "Is this %s a local address (%s)\n",
6285 address_without_port,
6286 ale->address);
6287 if (0 != strcmp ("127.0.0.1", address_without_port))
6288 {
6289 if (NULL != ale->st)
6290 {
6292 }
6293 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6294 }
6295 GNUNET_free (address_without_port);
6296
6297 return ale;
6298}
6299
6300
6301static void
6303{
6304
6306 "Feeding addresses to PILS\n");
6307 pils_feed_task = NULL;
6308
6310 GST_my_hello);
6311}
6312
6313
6320static void
6322 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6323{
6324 struct TransportClient *tc = cls;
6325 struct AddressListEntry *ale;
6326 size_t slen;
6327 char *address;
6328
6329 /* 0-termination of &aam[1] was checked in #check_add_address */
6331 "Communicator added address `%s'!\n",
6332 (const char *) &aam[1]);
6333 slen = ntohs (aam->header.size) - sizeof(*aam);
6334 address = GNUNET_malloc (slen);
6335 memcpy (address, &aam[1], slen);
6336 ale = create_address_entry (tc,
6338 ntohl (aam->nt),
6339 address,
6340 aam->aid,
6341 slen);
6342 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6343 tc->details.communicator.addr_tail,
6344 ale);
6345 {
6346 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6347 (NULL != iter && NULL != iter->next);
6348 iter = iter->next)
6349 {
6350 char *address_uri;
6351 const char *dash = strchr (ale->address, '-');
6353 GNUNET_assert (NULL != dash);
6354 dash++;
6355 GNUNET_asprintf (&address_uri,
6356 "%s://%s",
6357 prefix,
6358 dash);
6361 GNUNET_free (address_uri);
6362 }
6363 if (NULL != pils_feed_task)
6367 NULL);
6368 }
6371}
6372
6373
6380static void
6382 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6383{
6384 struct TransportClient *tc = cls;
6385 struct AddressListEntry *alen;
6386
6387 if (CT_COMMUNICATOR != tc->type)
6388 {
6389 GNUNET_break (0);
6391 return;
6392 }
6393 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6394 NULL != ale;
6395 ale = alen)
6396 {
6397 alen = ale->next;
6398 if (dam->aid != ale->aid)
6399 continue;
6400 GNUNET_assert (ale->tc == tc);
6402 "Communicator deleted address `%s'!\n",
6403 ale->address);
6405 ale->address);
6406 if (NULL != pils_feed_task)
6410 NULL);
6413 return;
6414 }
6416 "Communicator removed address we did not even have.\n");
6418 // GNUNET_SERVICE_client_drop (tc->client);
6419}
6420
6421
6429static void
6431
6432
6440static void
6442{
6443 struct CoreSentContext *ctx = cls;
6444 struct VirtualLink *vl = ctx->vl;
6445
6446 if (NULL == vl)
6447 {
6448 /* lost the link in the meantime, ignore */
6449 GNUNET_free (ctx);
6450 return;
6451 }
6454 vl->incoming_fc_window_size_ram -= ctx->size;
6455 vl->incoming_fc_window_size_used += ctx->isize;
6457 GNUNET_free (ctx);
6458}
6459
6460
6461static void
6463 const struct GNUNET_MessageHeader *mh,
6464 struct CommunicatorMessageContext *cmc,
6465 unsigned int free_cmc)
6466{
6467 uint16_t size = ntohs (mh->size);
6468 int have_core;
6469
6470 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6471 {
6473 "# CORE messages dropped (FC arithmetic overflow)",
6474 1,
6475 GNUNET_NO);
6477 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6478 (unsigned int) ntohs (mh->type),
6479 (unsigned int) ntohs (mh->size));
6480 if (GNUNET_YES == free_cmc)
6482 return;
6483 }
6485 {
6487 "# CORE messages dropped (FC window overflow)",
6488 1,
6489 GNUNET_NO);
6491 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6492 (unsigned int) ntohs (mh->type),
6493 (unsigned int) ntohs (mh->size));
6494 if (GNUNET_YES == free_cmc)
6496 return;
6497 }
6498
6499 /* Forward to all CORE clients */
6500 have_core = GNUNET_NO;
6501 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6502 {
6503 struct GNUNET_MQ_Envelope *env;
6504 struct InboundMessage *im;
6505 struct CoreSentContext *ctx;
6506
6507 if (CT_CORE != tc->type)
6508 continue;
6511 ctx = GNUNET_new (struct CoreSentContext);
6512 ctx->vl = vl;
6513 ctx->size = size;
6514 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6515 have_core = GNUNET_YES;
6518 im->peer = cmc->im.sender;
6519 memcpy (&im[1], mh, size);
6520 GNUNET_MQ_send (tc->mq, env);
6522 }
6523 if (GNUNET_NO == have_core)
6524 {
6526 "Dropped message to CORE: no CORE client connected!\n");
6527 /* Nevertheless, count window as used, as it is from the
6528 perspective of the other peer! */
6530 /* TODO-M1 */
6532 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6533 (unsigned int) ntohs (mh->type),
6534 (unsigned int) ntohs (mh->size));
6535 if (GNUNET_YES == free_cmc)
6537 return;
6538 }
6540 "Delivered message from %s of type %u to CORE recv window %d\n",
6541 GNUNET_i2s (&cmc->im.sender),
6542 ntohs (mh->type),
6544 if (vl->core_recv_window > 0)
6545 {
6546 if (GNUNET_YES == free_cmc)
6548 return;
6549 }
6550 /* Wait with calling #finish_cmc_handling(cmc) until the message
6551 was processed by CORE MQs (for CORE flow control)! */
6552 if (GNUNET_YES == free_cmc)
6554}
6555
6556
6565static void
6567{
6568 struct CommunicatorMessageContext *cmc = cls;
6569 // struct CommunicatorMessageContext *cmc_copy =
6570 // GNUNET_new (struct CommunicatorMessageContext);
6571 struct GNUNET_MessageHeader *mh_copy;
6572 struct RingBufferEntry *rbe;
6573 struct VirtualLink *vl;
6574 uint16_t size = ntohs (mh->size);
6575
6577 "Handling raw message of type %u with %u bytes\n",
6578 (unsigned int) ntohs (mh->type),
6579 (unsigned int) ntohs (mh->size));
6580
6581 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6582 (size < sizeof(struct GNUNET_MessageHeader)))
6583 {
6584 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6585
6586 GNUNET_break (0);
6587 finish_cmc_handling (cmc);
6589 return;
6590 }
6591 vl = lookup_virtual_link (&cmc->im.sender);
6592 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6593 {
6594 /* FIXME: sender is giving us messages for CORE but we don't have
6595 the link up yet! I *suspect* this can happen right now (i.e.
6596 sender has verified us, but we didn't verify sender), but if
6597 we pass this on, CORE would be confused (link down, messages
6598 arrive). We should investigate more if this happens often,
6599 or in a persistent manner, and possibly do "something" about
6600 it. Thus logging as error for now. */
6601
6602 mh_copy = GNUNET_malloc (size);
6603 rbe = GNUNET_new (struct RingBufferEntry);
6604 rbe->cmc = cmc;
6605 /*cmc_copy->tc = cmc->tc;
6606 cmc_copy->im = cmc->im;*/
6607 GNUNET_memcpy (mh_copy, mh, size);
6608
6609 rbe->mh = mh_copy;
6610
6612 {
6613 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6614 GNUNET_free (rbe_old->cmc);
6615 GNUNET_free (rbe_old->mh);
6616 GNUNET_free (rbe_old);
6617 }
6618 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6619 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6620 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6622 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6623 GNUNET_i2s (&cmc->im.sender),
6624 (unsigned int) ntohs (mh->type),
6625 (unsigned int) ntohs (mh_copy->type),
6629 {
6630 ring_buffer_head = 0;
6632 }
6633 else
6635
6637 "%u items stored in ring buffer\n",
6640
6641 /*GNUNET_break_op (0);
6642 GNUNET_STATISTICS_update (GST_stats,
6643 "# CORE messages dropped (virtual link still down)",
6644 1,
6645 GNUNET_NO);
6646
6647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6648 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6649 (unsigned int) ntohs (mh->type),
6650 (unsigned int) ntohs (mh->size));
6651 finish_cmc_handling (cmc);*/
6654 // GNUNET_free (cmc);
6655 return;
6656 }
6658}
6659
6660
6668static int
6670{
6671 uint16_t size = ntohs (fb->header.size);
6672 uint16_t bsize = size - sizeof(*fb);
6673
6674 (void) cls;
6675 if (0 == bsize)
6676 {
6677 GNUNET_break_op (0);
6678 return GNUNET_SYSERR;
6679 }
6680 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6681 {
6682 GNUNET_break_op (0);
6683 return GNUNET_SYSERR;
6684 }
6685 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6686 {
6687 GNUNET_break_op (0);
6688 return GNUNET_SYSERR;
6689 }
6690 return GNUNET_YES;
6691}
6692
6693
6699static void
6701{
6702 struct AcknowledgementCummulator *ac = cls;
6703
6704 ac->task = NULL;
6705 GNUNET_assert (0 == ac->num_acks);
6707 GNUNET_YES ==
6709 GNUNET_free (ac);
6710}
6711
6712
6718static void
6720{
6721 struct Neighbour *n;
6722 struct VirtualLink *vl;
6723 struct AcknowledgementCummulator *ac = cls;
6724 char buf[sizeof(struct TransportReliabilityAckMessage)
6725 + ac->num_acks
6727 struct TransportReliabilityAckMessage *ack =
6728 (struct TransportReliabilityAckMessage *) buf;
6730
6731 ac->task = NULL;
6733 "Sending ACK with %u components to %s\n",
6734 ac->num_acks,
6735 GNUNET_i2s (&ac->target));
6736 GNUNET_assert (0 < ac->num_acks);
6738 ack->header.size =
6739 htons (sizeof(*ack)
6740 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6741 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6742 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6743 for (unsigned int i = 0; i < ac->num_acks; i++)
6744 {
6745 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6748 }
6749 /*route_control_message_without_fc (
6750 &ac->target,
6751 &ack->header,
6752 RMO_DV_ALLOWED);*/
6753 vl = lookup_virtual_link (&ac->target);
6754 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6755 {
6757 vl,
6758 &ack->header,
6760 }
6761 else
6762 {
6763 /* Use route via neighbour */
6764 n = lookup_neighbour (&ac->target);
6765 if (NULL != n)
6767 n,
6768 &ack->header,
6769 RMO_NONE);
6770 }
6771 ac->num_acks = 0;
6774 ac);
6775}
6776
6777
6786static void
6788 const struct AcknowledgementUUIDP *ack_uuid,
6789 struct GNUNET_TIME_Absolute max_delay)
6790{
6791 struct AcknowledgementCummulator *ac;
6792
6794 "Scheduling ACK %s for transmission to %s\n",
6795 GNUNET_uuid2s (&ack_uuid->value),
6796 GNUNET_i2s (pid));
6798 if (NULL == ac)
6799 {
6801 ac->target = *pid;
6802 ac->min_transmission_time = max_delay;
6806 &ac->target,
6807 ac,
6809 }
6810 else
6811 {
6812 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6813 {
6814 /* must run immediately, ack buffer full! */
6816 }
6820 }
6823 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6824 ac->num_acks++;
6827 ac);
6828}
6829
6830
6846
6847
6857static int
6858find_by_message_uuid (void *cls, uint32_t key, void *value)
6859{
6860 struct FindByMessageUuidContext *fc = cls;
6861 struct ReassemblyContext *rc = value;
6862
6863 (void) key;
6864 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6865 {
6866 fc->rc = rc;
6867 return GNUNET_NO;
6868 }
6869 return GNUNET_YES;
6870}
6871
6872
6880static void
6882{
6883 struct CommunicatorMessageContext *cmc = cls;
6884 struct VirtualLink *vl;
6885 struct ReassemblyContext *rc;
6886 const struct GNUNET_MessageHeader *msg;
6887 uint16_t msize;
6888 uint16_t fsize;
6889 uint16_t frag_off;
6890 char *target;
6891 struct GNUNET_TIME_Relative cdelay;
6892 struct FindByMessageUuidContext fc;
6893
6894 vl = lookup_virtual_link (&cmc->im.sender);
6895 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6896 {
6897 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6898
6900 "No virtual link for %s to handle fragment\n",
6901 GNUNET_i2s (&cmc->im.sender));
6902 GNUNET_break (0);
6903 finish_cmc_handling (cmc);
6905 return;
6906 }
6907 if (NULL == vl->reassembly_map)
6908 {
6910 vl->reassembly_heap =
6915 vl);
6916 }
6917 msize = ntohs (fb->msg_size);
6918 fc.message_uuid = fb->msg_uuid;
6919 fc.rc = NULL;
6921 fb->msg_uuid.uuid,
6923 &fc);
6924 fsize = ntohs (fb->header.size) - sizeof(*fb);
6925 if (NULL == (rc = fc.rc))
6926 {
6927 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6928 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6929 rc->msg_uuid = fb->msg_uuid;
6930 rc->virtual_link = vl;
6931 rc->msg_size = msize;
6932 rc->reassembly_timeout =
6936 rc,
6940 vl->reassembly_map,
6941 rc->msg_uuid.uuid,
6942 rc,
6944 target = (char *) &rc[1];
6945 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6946 if (fsize != rc->msg_size)
6947 rc->msg_missing = rc->msg_size;
6948 else
6949 rc->msg_missing = 0;
6951 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6952 PRIu64 "\n",
6953 fsize,
6954 ntohs (fb->frag_off),
6955 msize,
6956 rc->msg_missing,
6957 GNUNET_i2s (&cmc->im.sender),
6958 fb->msg_uuid.uuid);
6959 }
6960 else
6961 {
6962 target = (char *) &rc[1];
6964 "Received fragment at offset %u/%u from %s for message %u\n",
6965 ntohs (fb->frag_off),
6966 msize,
6967 GNUNET_i2s (&cmc->im.sender),
6968 (unsigned int) fb->msg_uuid.uuid);
6969 }
6970 if (msize != rc->msg_size)
6971 {
6972 GNUNET_break (0);
6973 finish_cmc_handling (cmc);
6974 return;
6975 }
6976
6977 /* reassemble */
6978 if (0 == fsize)
6979 {
6980 GNUNET_break (0);
6981 finish_cmc_handling (cmc);
6982 return;
6983 }
6984 frag_off = ntohs (fb->frag_off);
6985 if (frag_off + fsize > msize)
6986 {
6987 /* Fragment (plus fragment size) exceeds message size! */
6988 GNUNET_break_op (0);
6989 finish_cmc_handling (cmc);
6990 return;
6991 }
6992 memcpy (&target[frag_off], &fb[1], fsize);
6993 /* update bitfield and msg_missing */
6994 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6995 {
6996 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6997 {
6998 rc->bitfield[i / 8] |= (1 << (i % 8));
6999 rc->msg_missing--;
7000 }
7001 }
7002
7003 /* Compute cumulative ACK */
7005 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
7006 if (0 == rc->msg_missing)
7007 cdelay = GNUNET_TIME_UNIT_ZERO;
7008 cummulative_ack (&cmc->im.sender,
7009 &fb->ack_uuid,
7012 /* is reassembly complete? */
7013 if (0 != rc->msg_missing)
7014 {
7015 finish_cmc_handling (cmc);
7016 return;
7017 }
7018 /* reassembly is complete, verify result */
7019 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7020 if (ntohs (msg->size) != rc->msg_size)
7021 {
7022 GNUNET_break (0);
7024 finish_cmc_handling (cmc);
7025 return;
7026 }
7027 /* successful reassembly */
7029 "Fragment reassembly complete for message %u\n",
7030 (unsigned int) fb->msg_uuid.uuid);
7031 /* FIXME: check that the resulting msg is NOT a
7032 DV Box or Reliability Box, as that is NOT allowed! */
7033 cmc->mh = msg;
7035 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
7036 en-route and we forget that we finished this reassembly immediately!
7037 -> keep around until timeout?
7038 -> shorten timeout based on ACK? */
7040}
7041
7042
7050static int
7052 const struct TransportReliabilityBoxMessage *rb)
7053{
7054 const struct GNUNET_MessageHeader *box = (const struct
7055 GNUNET_MessageHeader *) &rb[1];
7056 (void) cls;
7057
7059 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7060 ntohs (rb->header.size),
7061 ntohs (box->type),
7062 ntohs (box->size),
7063 sizeof (struct TransportReliabilityBoxMessage),
7064 sizeof (struct GNUNET_MessageHeader));
7066 return GNUNET_YES;
7067}
7068
7069
7077static void
7079 const struct TransportReliabilityBoxMessage *rb)
7080{
7081 struct CommunicatorMessageContext *cmc = cls;
7082 const struct GNUNET_MessageHeader *inbox =
7083 (const struct GNUNET_MessageHeader *) &rb[1];
7084 struct GNUNET_TIME_Relative rtt;
7085
7087 "Received reliability box from %s with UUID %s of type %u\n",
7088 GNUNET_i2s (&cmc->im.sender),
7090 (unsigned int) ntohs (inbox->type));
7091 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
7092 do not really have an RTT for the
7093 * incoming* queue (should we have
7094 the sender add it to the rb message?) */
7096 &cmc->im.sender,
7097 &rb->ack_uuid,
7098 (0 == ntohl (rb->ack_countdown))
7101 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
7102 /* continue with inner message */
7103 /* FIXME: check that inbox is NOT a DV Box, fragment or another
7104 reliability box (not allowed!) */
7105 cmc->mh = inbox;
7107}
7108
7109
7118static void
7119update_pd_age (struct PerformanceData *pd, unsigned int age)
7120{
7121 unsigned int sage;
7122
7123 if (age == pd->last_age)
7124 return; /* nothing to do */
7125 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7126 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7127 {
7128 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7129
7130 the->bytes_sent = 0;
7131 the->bytes_received = 0;
7132 }
7133 pd->last_age = age;
7134}
7135
7136
7145static void
7147 struct GNUNET_TIME_Relative rtt,
7148 uint16_t bytes_transmitted_ok)
7149{
7150 uint64_t nval = rtt.rel_value_us;
7151 uint64_t oval = pd->aged_rtt.rel_value_us;
7152 unsigned int age = get_age ();
7153 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7154
7155 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7156 pd->aged_rtt = rtt;
7157 else
7158 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7159 update_pd_age (pd, age);
7160 the->bytes_received += bytes_transmitted_ok;
7161}
7162
7163
7171static void
7173 struct GNUNET_TIME_Relative rtt,
7174 uint16_t bytes_transmitted_ok)
7175{
7176 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7177}
7178
7179
7187static void
7189 struct GNUNET_TIME_Relative rtt,
7190 uint16_t bytes_transmitted_ok)
7191{
7192 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7193}
7194
7195
7203static void
7205{
7206 struct PendingMessage *pos;
7207
7209 "Complete transmission of message %" PRIu64 " %u\n",
7210 pm->logging_uuid,
7211 pm->pmt);
7212 switch (pm->pmt)
7213 {
7214 case PMT_CORE:
7216 /* Full message sent, we are done */
7218 return;
7219
7220 case PMT_FRAGMENT_BOX:
7221 /* Fragment sent over reliable channel */
7222 pos = pm->frag_parent;
7226 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7227 (unsigned long) pos->frag_off,
7228 (unsigned long) pos->bytes_msg,
7229 pos->pmt,
7230 NULL == pos->frag_parent ? 1 : 0);
7231 /* check if subtree is done */
7232 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7233 - sizeof(struct
7235 &&
7236 (NULL != pos->frag_parent))
7237 {
7238 pm = pos;
7239 pos = pm->frag_parent;
7240 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7241 {
7243 return;
7244 }
7245 else if (PMT_DV_BOX == pm->pmt)
7246 {
7248 return;
7249 }
7252 }
7253
7254 /* Was this the last applicable fragment? */
7255 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7256 pos->pmt) &&
7257 (pos->frag_off == pos->bytes_msg))
7259 return;
7260
7261 case PMT_DV_BOX:
7263 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7264 pm->logging_uuid);
7265 if (NULL != pm->frag_parent)
7266 {
7267 pos = pm->frag_parent;
7269 pos->bpm = NULL;
7271 }
7272 else
7274 return;
7275 }
7276}
7277
7278
7286static void
7288 struct GNUNET_TIME_Relative ack_delay)
7289{
7290 struct GNUNET_TIME_Relative delay;
7291
7293 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7294 if (NULL != pa->queue && 1 == pa->num_send)
7296 if (NULL != pa->dvh && 1 == pa->num_send)
7297 update_dvh_performance (pa->dvh, delay, pa->message_size);
7298 if (NULL != pa->pm)
7301}
7302
7303
7311static int
7313 const struct TransportReliabilityAckMessage *ra)
7314{
7315 unsigned int n_acks;
7316
7317 (void) cls;
7318 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7319 / sizeof(struct TransportCummulativeAckPayloadP);
7320 if (0 == n_acks)
7321 {
7322 GNUNET_break_op (0);
7323 return GNUNET_SYSERR;
7324 }
7325 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7326 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7327 {
7328 GNUNET_break_op (0);
7329 return GNUNET_SYSERR;
7330 }
7331 return GNUNET_OK;
7332}
7333
7334
7342static void
7344 const struct TransportReliabilityAckMessage *ra)
7345{
7346 struct CommunicatorMessageContext *cmc = cls;
7347 const struct TransportCummulativeAckPayloadP *ack;
7348 unsigned int n_acks;
7349 uint32_t ack_counter;
7350
7351 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7352 / sizeof(struct TransportCummulativeAckPayloadP);
7353 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7354 for (unsigned int i = 0; i < n_acks; i++)
7355 {
7356 struct PendingAcknowledgement *pa =
7358 if (NULL == pa)
7359 {
7361 "Received ACK from %s with UUID %s which is unknown to us!\n",
7362 GNUNET_i2s (&cmc->im.sender),
7363 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7365 GST_stats,
7366 "# FRAGMENT_ACKS dropped, no matching pending message",
7367 1,
7368 GNUNET_NO);
7369 continue;
7370 }
7372 "Received ACK from %s with UUID %s\n",
7373 GNUNET_i2s (&cmc->im.sender),
7374 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7375 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7376 }
7377
7378 ack_counter = htonl (ra->ack_counter);
7379 (void) ack_counter; /* silence compiler warning for now */
7380 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7381 // (DV and/or Neighbour?)
7382 finish_cmc_handling (cmc);
7383}
7384
7385
7393static int
7395 void *cls,
7397{
7398 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7399 const struct GNUNET_MessageHeader *inbox =
7400 (const struct GNUNET_MessageHeader *) &be[1];
7401 const char *is;
7402 uint16_t isize;
7403
7404 (void) cls;
7405 if (ntohs (inbox->size) >= size)
7406 {
7407 GNUNET_break_op (0);
7408 return GNUNET_SYSERR;
7409 }
7410 isize = ntohs (inbox->size);
7411 is = ((const char *) inbox) + isize;
7412 size -= isize;
7413 if ('\0' != is[size - 1])
7414 {
7415 GNUNET_break_op (0);
7416 return GNUNET_SYSERR;
7417 }
7418 return GNUNET_YES;
7419}
7420
7421
7430static void
7432 void *cls,
7434{
7435 const struct GNUNET_PeerIdentity *my_identity;
7436 struct CommunicatorMessageContext *cmc = cls;
7438 struct GNUNET_MQ_Envelope *env;
7439 struct TransportClient *tc;
7440 const struct GNUNET_MessageHeader *inbox =
7441 (const struct GNUNET_MessageHeader *) &be[1];
7442 uint16_t isize = ntohs (inbox->size);
7443 const char *target_communicator = ((const char *) inbox) + isize;
7444 char *sender;
7445 char *self;
7446
7449
7450 GNUNET_asprintf (&sender,
7451 "%s",
7452 GNUNET_i2s (&cmc->im.sender));
7453 GNUNET_asprintf (&self,
7454 "%s",
7456
7457 /* Find client providing this communicator */
7458 for (tc = clients_head; NULL != tc; tc = tc->next)
7459 if ((CT_COMMUNICATOR == tc->type) &&
7460 (0 ==
7461 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7462 break;
7463 if (NULL == tc)
7464 {
7465 char *stastr;
7466
7468 &stastr,
7469 "# Backchannel message dropped: target communicator `%s' unknown",
7470 target_communicator);
7472 GNUNET_free (stastr);
7473 finish_cmc_handling (cmc);
7474 return;
7475 }
7476 /* Finally, deliver backchannel message to communicator */
7478 "Delivering backchannel message from %s to %s of type %u to %s\n",
7479 sender,
7480 self,
7481 ntohs (inbox->type),
7482 target_communicator);
7484 cbi,
7485 isize,
7487 cbi->pid = cmc->im.sender;
7488 memcpy (&cbi[1], inbox, isize);
7489 GNUNET_MQ_send (tc->mq, env);
7490 finish_cmc_handling (cmc);
7491}
7492
7493
7503static void
7505{
7506 struct DistanceVector *dv = cls;
7507 struct DistanceVectorHop *pos;
7508
7509 dv->timeout_task = NULL;
7510 while (NULL != (pos = dv->dv_head))
7511 {
7512 GNUNET_assert (dv == pos->dv);
7514 break;
7516 }
7517 if (NULL == pos)
7518 {
7519 free_dv_route (dv);
7520 return;
7521 }
7522 dv->timeout_task =
7524}
7525
7526
7527static void
7529{
7530
7531 const struct GNUNET_PeerIdentity target = vl->target;
7532
7533
7535 {
7536 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7537 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7538 0;
7539 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7542 struct CommunicatorMessageContext *cmc;
7543 struct RingBufferEntry *rbe;
7544 struct GNUNET_MessageHeader *mh;
7545
7547 "Sending from ring buffer, which has %u items\n",
7548 head);
7549
7550 ring_buffer_head = 0;
7551 for (unsigned int i = 0; i < head; i++)
7552 {
7553 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7554 cmc = rbe->cmc;
7555 mh = rbe->mh;
7556
7557 im = cmc->im;
7558 // mh = cmc->mh;
7560 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7561 mh->type,
7562 GNUNET_i2s (&im.sender),
7563 GNUNET_i2s2 (&target),
7564 (i + tail) % RING_BUFFER_SIZE);
7565 if (0 == GNUNET_memcmp (&target, &im.sender))
7566 {
7568 "Finish handling message of type %u and size %u\n",
7569 (unsigned int) ntohs (mh->type),
7570 (unsigned int) ntohs (mh->size));
7572 GNUNET_free (mh);
7573 GNUNET_free (rbe->cmc);
7574 GNUNET_free (rbe);
7575 }
7576 else
7577 {
7578 ring_buffer_copy[ring_buffer_head] = rbe;
7580 }
7581 }
7582
7585 {
7587 }
7588
7589 for (unsigned int i = 0; i < ring_buffer_head; i++)
7590 {
7591 ring_buffer[i] = ring_buffer_copy[i];
7593 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7594 i,
7595 ring_buffer_copy[i]->mh->type);
7597 "ring_buffer[i]->mh->type for i %u %u\n",
7598 i,
7599 ring_buffer[i]->mh->type);
7600 }
7601
7603 "%u items still in ring buffer\n",
7605 }
7606
7608 {
7609 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7610 struct PendingMessage *pm;
7611 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7613 0;
7614 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7617
7619 "Sending from ring buffer dv, which has %u items\n",
7620 head);
7621
7623 for (unsigned int i = 0; i < head; i++)
7624 {
7625 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7626
7628 "Sending to ring buffer target %s using vl target %s\n",
7629 GNUNET_i2s (&pm->target),
7630 GNUNET_i2s2 (&target));
7631 if (0 == GNUNET_memcmp (&target, &pm->target))
7632 {
7634 "Adding PendingMessage to vl, checking transmission.\n");
7635 pm->vl = vl;
7639 pm);
7640
7642 }
7643 else
7644 {
7645 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7647 }
7648 }
7649
7651 {
7653 }
7654
7655 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7656 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7657
7659 "%u items still in ring buffer dv.\n",
7661
7662 }
7663}
7664
7665
7673static void
7675{
7676 struct DistanceVector *dv = hop->dv;
7677 struct VirtualLink *vl;
7678
7679 vl = lookup_virtual_link (&dv->target);
7680 if (NULL == vl)
7681 {
7682
7683 vl = GNUNET_new (struct VirtualLink);
7685 "Creating new virtual link %p to %s using DV!\n",
7686 vl,
7687 GNUNET_i2s (&dv->target));
7688 vl->burst_addr = NULL;
7689 vl->confirmed = GNUNET_YES;
7690 vl->message_uuid_ctr =
7692 vl->target = dv->target;
7698 links,
7699 &vl->target,
7700 vl,
7702 vl->dv = dv;
7703 dv->vl = vl;
7704 vl->visibility_task =
7707 /* We lacked a confirmed connection to the target
7708 before, so tell CORE about it (finally!) */
7711 }
7712 else
7713 {
7714 /* Link was already up, remember dv is also now available and we are done */
7715 vl->dv = dv;
7716 dv->vl = vl;
7717 if (GNUNET_NO == vl->confirmed)
7718 {
7719 vl->confirmed = GNUNET_YES;
7720 vl->visibility_task =
7723 /* We lacked a confirmed connection to the target
7724 before, so tell CORE about it (finally!) */
7727 }
7728 else
7730 "Virtual link to %s could now also use DV!\n",
7731 GNUNET_i2s (&dv->target));
7732 }
7733}
7734
7735
7761static int
7763 unsigned int path_len,
7764 struct GNUNET_TIME_Relative network_latency,
7765 struct GNUNET_TIME_Absolute path_valid_until)
7766{
7767 const struct GNUNET_PeerIdentity *my_identity;
7768 struct DistanceVectorHop *hop;
7769 struct DistanceVector *dv;
7770 struct Neighbour *next_hop;
7771 unsigned int shorter_distance;
7772
7773 if (path_len < 3)
7774 {
7775 /* what a boring path! not allowed! */
7776 GNUNET_break (0);
7777 return GNUNET_SYSERR;
7778 }
7779
7782
7783 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
7784 next_hop = lookup_neighbour (&path[1]);
7785 if (NULL == next_hop)
7786 {
7787 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7788 GNUNET_break (0);
7789 return GNUNET_SYSERR;
7790 }
7791 for (unsigned int i = 2; i < path_len; i++)
7792 {
7793 struct Neighbour *n = lookup_neighbour (&path[i]);
7794 struct GNUNET_TIME_Absolute q_timeout;
7795
7796 if (NULL != n)
7797 {
7798 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7799 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7800 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7802 "remaining %lu to %s\n",
7803 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7804 .rel_value_us,
7805 GNUNET_i2s (&n->pid));
7806 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7807 {
7808 /* Useless path: we have a direct active connection to some hop
7809 in the middle of the path, so this one is not even
7810 terribly useful for redundancy */
7812 "Path of %u hops useless: directly link to hop %u (%s)\n",
7813 path_len,
7814 i,
7815 GNUNET_i2s (&path[i]));
7817 "# Useless DV path ignored: hop is neighbour",
7818 1,
7819 GNUNET_NO);
7820 return GNUNET_SYSERR;
7821 }
7822 }
7823 }
7824 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7825 if (NULL == dv)
7826 {
7827 dv = GNUNET_new (struct DistanceVector);
7828 dv->target = path[path_len - 1];
7831 dv);
7834 dv_routes,
7835 &dv->target,
7836 dv,
7838 }
7839 /* Check if we have this path already! */
7840 shorter_distance = 0;
7841 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7842 pos = pos->next_dv)
7843 {
7844 if (pos->distance < path_len - 3)
7845 shorter_distance++;
7846 /* Note that the distances in 'pos' excludes us (path[0]),
7847 the next_hop (path[1]) and the target so we need to subtract three
7848 and check next_hop explicitly */
7849 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7850 {
7851 int match = GNUNET_YES;
7852
7853 for (unsigned int i = 0; i < pos->distance; i++)
7854 {
7855 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7856 {
7857 match = GNUNET_NO;
7858 break;
7859 }
7860 }
7861 if (GNUNET_YES == match)
7862 {
7863 struct GNUNET_TIME_Relative last_timeout;
7864
7865 /* Re-discovered known path, update timeout */
7867 "# Known DV path refreshed",
7868 1,
7869 GNUNET_NO);
7870 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7871 pos->timeout =
7873 pos->path_valid_until =
7874 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7875 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7876 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7877 if (0 <
7880 if (last_timeout.rel_value_us <
7883 .rel_value_us)
7884 {
7885 /* Some peer send DV learn messages too often, we are learning
7886 the same path faster than it would be useful; do not forward! */
7888 "Rediscovered path too quickly, not forwarding further\n")
7889 ;
7890 return GNUNET_NO;
7891 }
7893 "Refreshed known path to %s valid until %s, forwarding further\n",
7894 GNUNET_i2s (&dv->target),
7896 pos->path_valid_until));
7897 return GNUNET_YES;
7898 }
7899 }
7900 }
7901 /* Count how many shorter paths we have (incl. direct
7902 neighbours) before simply giving up on this one! */
7903 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7904 {
7905 /* We have a shorter path already! */
7907 "Have many shorter DV paths %s, not forwarding further\n",
7908 GNUNET_i2s (&dv->target));
7909 return GNUNET_NO;
7910 }
7911 /* create new DV path entry */
7913 "Discovered new DV path to %s valid until %s\n",
7914 GNUNET_i2s (&dv->target),
7915 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7916 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7917 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7918 hop->next_hop = next_hop;
7919 hop->dv = dv;
7920 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7921 memcpy (&hop[1],
7922 &path[2],
7923 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7925 hop->path_valid_until = path_valid_until;
7926 hop->distance = path_len - 3;
7927 hop->pd.aged_rtt = network_latency;
7928 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7930 next_hop->dv_head,
7931 next_hop->dv_tail,
7932 hop);
7933 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7935 return GNUNET_YES;
7936}
7937
7938
7946static int
7947check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7948{
7949 const struct GNUNET_PeerIdentity *my_identity;
7950 uint16_t size = ntohs (dvl->header.size);
7951 uint16_t num_hops = ntohs (dvl->num_hops);
7952 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7953
7954 (void) cls;
7955 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7956 {
7957 GNUNET_break_op (0);
7958 return GNUNET_SYSERR;
7959 }
7960 if (num_hops > MAX_DV_HOPS_ALLOWED)
7961 {
7962 GNUNET_break_op (0);
7963 return GNUNET_SYSERR;
7964 }
7965
7968
7969 for (unsigned int i = 0; i < num_hops; i++)
7970 {
7971 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7972 {
7973 GNUNET_break_op (0);
7974 return GNUNET_SYSERR;
7975 }
7976 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
7977 {
7978 GNUNET_break_op (0);
7979 return GNUNET_SYSERR;
7980 }
7981 }
7982 return GNUNET_YES;
7983}
7984
7985
7994
7995
7996static void
7997sign_dhp_cp (void *cls,
7998 const struct GNUNET_PeerIdentity *pid,
7999 const struct GNUNET_CRYPTO_EddsaSignature *sig)
8000{
8001 struct SignDhpCls *sign_dhp_cls = cls;
8002 struct VirtualLink *vl;
8003 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
8004 uint16_t nhops = sign_dhp_cls->nhops;
8005 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
8006 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
8007 struct Neighbour *n;
8008
8009 sign_dhp_cls->pr->op = NULL;
8012 sign_dhp_cls->pr);
8013 GNUNET_free (sign_dhp_cls->pr);
8014 dhops[nhops].hop_sig = *sig;
8015
8016 /*route_control_message_without_fc (next_hop,
8017 &fwd->header,
8018 RMO_UNCONFIRMED_ALLOWED);*/
8019 vl = lookup_virtual_link (next_hop);
8020 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8021 {
8023 &fwd->header,
8025 }
8026 else
8027 {
8028 /* Use route via neighbour */
8029 n = lookup_neighbour (next_hop);
8030 if (NULL != n)
8032 n,
8033 &fwd->header,
8035 }
8036 GNUNET_free (sign_dhp_cls);
8037}
8038
8039
8051static void
8053 const struct TransportDVLearnMessage *msg,
8054 uint16_t bi_history,
8055 uint16_t nhops,
8056 const struct DVPathEntryP *hops,
8057 struct GNUNET_TIME_Absolute in_time)
8058{
8059 struct DVPathEntryP *dhops;
8060 char buf[sizeof(struct TransportDVLearnMessage)
8061 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8062 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
8063 struct GNUNET_TIME_Relative nnd;
8064 const struct GNUNET_PeerIdentity *my_identity;
8065
8066 /* compute message for forwarding */
8068 "Forwarding DV learn message originating from %s to %s\n",
8069 GNUNET_i2s (&msg->initiator),
8070 GNUNET_i2s2 (next_hop));
8073 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8074 + (nhops + 1) * sizeof(struct DVPathEntryP));
8075 fwd->num_hops = htons (nhops + 1);
8076 fwd->bidirectional = htons (bi_history);
8079 msg->non_network_delay));
8081 fwd->init_sig = msg->init_sig;
8082 fwd->initiator = msg->initiator;
8083 fwd->challenge = msg->challenge;
8084 fwd->monotonic_time = msg->monotonic_time;
8085
8088
8089 dhops = (struct DVPathEntryP *) &fwd[1];
8090 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8091 dhops[nhops].hop = *my_identity;
8092 {
8093 struct DvHopPS dhp = {
8095 .purpose.size = htonl (sizeof(dhp)),
8096 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8097 .succ = *next_hop,
8098 .challenge = msg->challenge
8099 };
8100 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
8101 sign_dhp_cls->dhops = dhops;
8102 sign_dhp_cls->nhops = nhops;
8103 sign_dhp_cls->next_hop = next_hop;
8104 sign_dhp_cls->fwd = fwd;
8105 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
8108 sign_dhp_cls->pr);
8109 sign_dhp_cls->pr->op =
8111 &dhp.purpose,
8113 sign_dhp_cls);
8114 }
8115}
8116
8117
8127static int
8129 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
8130 const struct GNUNET_PeerIdentity *init,
8131 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
8132 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
8133{
8134 struct DvInitPS ip = { .purpose.purpose = htonl (
8136 .purpose.size = htonl (sizeof(ip)),
8137 .monotonic_time = sender_monotonic_time,
8138 .challenge = *challenge };
8139
8140 if (
8141 GNUNET_OK !=
8143 &ip,
8144 init_sig,
8145 &init->public_key))
8146 {
8147 GNUNET_break_op (0);
8148 return GNUNET_SYSERR;
8149 }
8150 return GNUNET_OK;
8151}
8152
8153
8158{
8163
8167 const struct DVPathEntryP *hops;
8168
8173
8178
8182 unsigned int num_eligible;
8183
8187 unsigned int num_selections;
8188
8192 uint16_t nhops;
8193
8197 uint16_t bi_history;
8198};
8199
8200
8209static int
8211 const struct GNUNET_PeerIdentity *pid,
8212 void *value)
8213{
8214 struct NeighbourSelectionContext *nsc = cls;
8215
8216 (void) value;
8217 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8218 return GNUNET_YES; /* skip initiator */
8219 for (unsigned int i = 0; i < nsc->nhops; i++)
8220 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8221 return GNUNET_YES;
8222 /* skip peers on path */
8223 nsc->num_eligible++;
8224 return GNUNET_YES;
8225}
8226
8227
8238static int
8240 const struct GNUNET_PeerIdentity *pid,
8241 void *value)
8242{
8243 struct NeighbourSelectionContext *nsc = cls;
8244
8246 "transmission %s\n",
8247 GNUNET_i2s (pid));
8248 (void) value;
8249 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8250 return GNUNET_YES; /* skip initiator */
8251 for (unsigned int i = 0; i < nsc->nhops; i++)
8252 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8253 return GNUNET_YES;
8254 /* skip peers on path */
8255 for (unsigned int i = 0; i < nsc->num_selections; i++)
8256 {
8257 if (nsc->selections[i] == nsc->num_eligible)
8258 {
8260 nsc->dvl,
8261 nsc->bi_history,
8262 nsc->nhops,
8263 nsc->hops,
8264 nsc->in_time);
8265 break;
8266 }
8267 }
8268 nsc->num_eligible++;
8269 return GNUNET_YES;
8270}
8271
8272
8316static unsigned int
8317calculate_fork_degree (unsigned int hops_taken,
8318 unsigned int neighbour_count,
8319 unsigned int eligible_count)
8320{
8321 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8322 double eligible_ratio =
8323 ((double) eligible_count) / ((double) neighbour_count);
8324 double boost_factor = eligible_ratio * eligible_ratio;
8325 unsigned int rnd;
8326 double left;
8327
8328 if (hops_taken >= 64)
8329 {
8330 GNUNET_break (0);
8331 return 0; /* precaution given bitshift below */
8332 }
8333 for (unsigned int i = 1; i < hops_taken; i++)
8334 {
8335 /* For each hop, subtract the expected number of targets
8336 reached at distance d (so what remains divided by 2^d) */
8337 target_total -= (target_total * boost_factor / (1LLU << i));
8338 }
8339 rnd =
8340 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8341 /* round up or down probabilistically depending on how close we were
8342 when floor()ing to rnd */
8343 left = target_total - (double) rnd;
8344 if (UINT32_MAX * left >
8346 rnd++; /* round up */
8348 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8349 hops_taken,
8350 rnd,
8351 eligible_count,
8352 neighbour_count);
8353 return rnd;
8354}
8355
8356
8363static void
8364neighbour_store_dvmono_cb (void *cls, int success)
8365{
8366 struct Neighbour *n = cls;
8367
8368 n->sc = NULL;
8369 if (GNUNET_YES != success)
8371 "Failed to store other peer's monotonic time in peerstore!\n");
8372}
8373
8374
8375static struct GNUNET_TIME_Relative
8377{
8378 struct GNUNET_TIME_Relative host_latency_sum;
8379 struct GNUNET_TIME_Relative latency;
8380 struct GNUNET_TIME_Relative network_latency;
8381 uint16_t nhops = ntohs (dvl->num_hops);;
8382
8383 /* We initiated this, learn the forward path! */
8384 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8385
8386 // Need also something to lookup initiation time
8387 // to compute RTT! -> add RTT argument here?
8389 dvl->monotonic_time));
8390 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8391 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8392 // (based on dvl->challenge, we can identify time of origin!)
8393
8394 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8395 /* assumption: latency on all links is the same */
8396 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8397
8398 return network_latency;
8399}
8400
8401
8409static void
8410handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8411{
8412 struct CommunicatorMessageContext *cmc = cls;
8414 int bi_hop;
8415 uint16_t nhops;
8416 uint16_t bi_history;
8417 const struct DVPathEntryP *hops;
8418 int do_fwd;
8419 int did_initiator;
8420 struct GNUNET_TIME_Absolute in_time;
8421 struct Neighbour *n;
8422 const struct GNUNET_PeerIdentity *my_identity;
8423
8424 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8425 bi_history = ntohs (dvl->bidirectional);
8426 hops = (const struct DVPathEntryP *) &dvl[1];
8427 if (0 == nhops)
8428 {
8429 /* sanity check */
8430 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8431 {
8432 GNUNET_break (0);
8433 finish_cmc_handling (cmc);
8434 return;
8435 }
8436 }
8437 else
8438 {
8440 "handle dv learn message last hop %s\n",
8441 GNUNET_i2s (&hops[nhops - 1].hop));
8442 /* sanity check */
8443 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8444 {
8445 GNUNET_break (0);
8446 finish_cmc_handling (cmc);
8447 return;
8448 }
8449 }
8450
8452 cc = cmc->tc->details.communicator.cc;
8453 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8454 cc); // FIXME: add bi-directional flag to cc?
8455 in_time = GNUNET_TIME_absolute_get ();
8456
8457 /* continue communicator here, everything else can happen asynchronous! */
8458 finish_cmc_handling (cmc);
8459
8460 n = lookup_neighbour (&dvl->initiator);
8461 if (NULL != n)
8462 {
8463 if ((n->dv_monotime_available == GNUNET_YES) &&
8466 {
8468 "DV learn from %s discarded due to time travel",
8469 GNUNET_i2s (&dvl->initiator));
8471 "# DV learn discarded due to time travel",
8472 1,
8473 GNUNET_NO);
8474 return;
8475 }
8477 &dvl->initiator,
8478 &dvl->challenge,
8479 &dvl->init_sig))
8480 {
8482 "DV learn signature from %s invalid\n",
8483 GNUNET_i2s (&dvl->initiator));
8484 GNUNET_break_op (0);
8485 return;
8486 }
8489 {
8490 if (NULL != n->sc)
8491 {
8493 "store cancel\n");
8495 }
8496 n->sc =
8498 "transport",
8499 &dvl->initiator,
8501 &dvl->monotonic_time,
8502 sizeof(dvl->monotonic_time),
8506 n);
8507 }
8508 }
8509
8512
8513 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8514 If signature verification load too high, implement random drop strategy */
8515 for (unsigned int i = 0; i < nhops; i++)
8516 {
8517 struct DvHopPS dhp = { .purpose.purpose =
8519 .purpose.size = htonl (sizeof(dhp)),
8520 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8521 .succ = (nhops == i + 1) ? *my_identity
8522 : hops[i + 1].hop,
8523 .challenge = dvl->challenge };
8524
8525 if (GNUNET_OK !=
8527 &dhp,
8528 &hops[i].hop_sig,
8529 &hops[i].hop.public_key))
8530 {
8532 "DV learn from %s signature of hop %u invalid\n",
8533 GNUNET_i2s (&dvl->initiator),
8534 i);
8536 "signature of hop %s invalid\n",
8537 GNUNET_i2s (&hops[i].hop));
8539 "pred %s\n",
8540 GNUNET_i2s (&dhp.pred));
8542 "succ %s\n",
8543 GNUNET_i2s (&dhp.succ));
8545 "hash %s\n",
8546 GNUNET_sh2s (&dhp.challenge.value));
8547 GNUNET_break_op (0);
8548 return;
8549 }
8550 }
8551 if (GNUNET_EXTRA_LOGGING > 0)
8552 {
8553 char *path;
8554
8555 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8556 for (unsigned int i = 0; i < nhops; i++)
8557 {
8558 char *tmp;
8559
8560 GNUNET_asprintf (&tmp,
8561 "%s%s%s",
8562 path,
8563 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8564 GNUNET_i2s (&hops[i].hop));
8565 GNUNET_free (path);
8566 path = tmp;
8567 }
8569 "Received DVInit via %s%s%s\n",
8570 path,
8571 bi_hop ? "<->" : "-->",
8573 GNUNET_free (path);
8574 }
8575 do_fwd = GNUNET_YES;
8576 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
8577 {
8578 struct GNUNET_PeerIdentity path[nhops + 1];
8579 struct GNUNET_TIME_Relative network_latency;
8580
8581 /* We initiated this, learn the forward path! */
8582 path[0] = *my_identity;
8583 path[1] = hops[0].hop;
8584
8585 network_latency = get_network_latency (dvl);
8586
8587 for (unsigned int i = 2; i <= nhops; i++)
8588 {
8589 struct GNUNET_TIME_Relative ilat;
8590
8591 /* assumption: linear latency increase per hop */
8592 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8593 path[i] = hops[i - 1].hop;
8595 "Learned path with %u hops to %s with latency %s\n",
8596 i,
8597 GNUNET_i2s (&path[i]),
8599 learn_dv_path (path,
8600 i + 1,
8601 ilat,
8604 }
8605 /* as we initiated, do not forward again (would be circular!) */
8606 do_fwd = GNUNET_NO;
8607 return;
8608 }
8609 if (bi_hop)
8610 {
8611 /* last hop was bi-directional, we could learn something here! */
8612 struct GNUNET_PeerIdentity path[nhops + 2];
8613 struct GNUNET_TIME_Relative ilat;
8614 struct GNUNET_TIME_Relative network_latency;
8615
8616 path[0] = *my_identity;
8617 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8618 for (unsigned int i = 0; i < nhops; i++)
8619 {
8620 int iret;
8621
8622 if (0 == (bi_history & (1 << i)))
8623 break; /* i-th hop not bi-directional, stop learning! */
8624 if (i == nhops - 1)
8625 {
8626 path[i + 2] = dvl->initiator;
8627 }
8628 else
8629 {
8630 path[i + 2] = hops[nhops - i - 2].hop;
8631 }
8632
8634 "Learned inverse path with %u hops to %s\n",
8635 i + 2,
8636 GNUNET_i2s (&path[i + 2]));
8637 network_latency = get_network_latency (dvl);
8638 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8639 iret = learn_dv_path (path,
8640 i + 3,
8641 ilat,
8644 if (GNUNET_SYSERR == iret)
8645 {
8646 /* path invalid or too long to be interesting for US, thus should also
8647 not be interesting to our neighbours, cut path when forwarding to
8648 'i' hops, except of course for the one that goes back to the
8649 initiator */
8651 "# DV learn not forwarded due invalidity of path",
8652 1,
8653 GNUNET_NO);
8654 do_fwd = GNUNET_NO;
8655 break;
8656 }
8657 if ((GNUNET_NO == iret) && (nhops == i + 1))
8658 {
8659 /* we have better paths, and this is the longest target,
8660 so there cannot be anything interesting later */
8662 "# DV learn not forwarded, got better paths",
8663 1,
8664 GNUNET_NO);
8665 do_fwd = GNUNET_NO;
8666 break;
8667 }
8668 }
8669 }
8670 if (MAX_DV_HOPS_ALLOWED == nhops)
8671 {
8672 /* At limit, we're out of here! */
8673 return;
8674 }
8675
8676 /* Forward to initiator, if path non-trivial and possible */
8677 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8678 did_initiator = GNUNET_NO;
8679 if ((1 <= nhops) &&
8680 (GNUNET_YES ==
8682 {
8683 /* send back to origin! */
8685 "Sending DVL back to initiator %s\n",
8686 GNUNET_i2s (&dvl->initiator));
8687 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8688 did_initiator = GNUNET_YES;
8689 }
8690 /* We forward under two conditions: either we still learned something
8691 ourselves (do_fwd), or the path was darn short and thus the initiator is
8692 likely to still be very interested in this (and we did NOT already
8693 send it back to the initiator) */
8694 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8695 (GNUNET_NO == did_initiator)))
8696 {
8697 /* Pick random neighbours that are not yet on the path */
8698 struct NeighbourSelectionContext nsc;
8699 unsigned int n_cnt;
8700
8702 nsc.nhops = nhops;
8703 nsc.dvl = dvl;
8704 nsc.bi_history = bi_history;
8705 nsc.hops = hops;
8706 nsc.in_time = in_time;
8707 nsc.num_eligible = 0;
8710 &nsc);
8711 if (0 == nsc.num_eligible)
8712 return; /* done here, cannot forward to anyone else */
8714 nsc.num_selections =
8717 "Forwarding DVL to %u other peers\n",
8718 nsc.num_selections);
8719 for (unsigned int i = 0; i < nsc.num_selections; i++)
8720 nsc.selections[i] =
8721 (nsc.num_selections == n_cnt)
8722 ? i /* all were selected, avoid collisions by chance */
8724 nsc.num_eligible = 0;
8727 &nsc);
8728 }
8729}
8730
8731
8739static int
8740check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8741{
8742 uint16_t size = ntohs (dvb->header.size);
8743 uint16_t num_hops = ntohs (dvb->num_hops);
8744 const struct GNUNET_PeerIdentity *hops =
8745 (const struct GNUNET_PeerIdentity *) &dvb[1];
8746 const struct GNUNET_PeerIdentity *my_identity;
8747
8748 (void) cls;
8749 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8750 + sizeof(struct GNUNET_MessageHeader))
8751 {
8752 GNUNET_break_op (0);
8753 return GNUNET_SYSERR;
8754 }
8755
8758
8759 /* This peer must not be on the path */
8760 for (unsigned int i = 0; i < num_hops; i++)
8761 if (0 == GNUNET_memcmp (&hops[i], my_identity))
8762 {
8763 GNUNET_break_op (0);
8764 return GNUNET_SYSERR;
8765 }
8766 return GNUNET_YES;
8767}
8768
8769
8782static void
8783forward_dv_box (struct Neighbour *next_hop,
8784 struct TransportDVBoxMessage *hdr,
8785 uint16_t total_hops,
8786 uint16_t num_hops,
8787 const struct GNUNET_PeerIdentity *hops,
8788 const void *enc_payload,
8789 uint16_t enc_payload_size)
8790{
8791 struct VirtualLink *vl = next_hop->vl;
8792 struct PendingMessage *pm;
8793 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8794 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8795 + enc_payload_size;
8796 char *buf;
8797 char msg_buf[msg_size] GNUNET_ALIGN;
8798 struct GNUNET_PeerIdentity *dhops;
8799
8800 hdr->num_hops = htons (num_hops);
8801 hdr->total_hops = htons (total_hops);
8802 hdr->header.size = htons (msg_size);
8803 memcpy (msg_buf, hdr, sizeof(*hdr));
8804 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8806 ;
8807 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8808 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8809
8810 if (GNUNET_YES == ntohs (hdr->without_fc))
8811 {
8813 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8814 enc_payload_size,
8815 GNUNET_i2s (&next_hop->pid),
8816 (unsigned int) num_hops,
8817 (unsigned int) total_hops);
8818 route_via_neighbour (next_hop, (const struct
8819 GNUNET_MessageHeader *) msg_buf,
8821 }
8822 else
8823 {
8824 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8826 "2 created pm %p storing vl %p \n",
8827 pm,
8828 vl);
8829 pm->pmt = PMT_DV_BOX;
8830 pm->vl = vl;
8831 pm->target = next_hop->pid;
8833 pm->logging_uuid = logging_uuid_gen++;
8835 pm->bytes_msg = msg_size;
8836 buf = (char *) &pm[1];
8837 memcpy (buf, msg_buf, msg_size);
8838
8840 "Created pending message %" PRIu64
8841 " for DV Box with next hop %s (%u/%u)\n",
8842 pm->logging_uuid,
8843 GNUNET_i2s (&next_hop->pid),
8844 (unsigned int) num_hops,
8845 (unsigned int) total_hops);
8846
8847 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8848 {
8850 vl->pending_msg_head,
8851 vl->pending_msg_tail,
8852 pm);
8853
8855 }
8856 else
8857 {
8859 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8860
8862 {
8864
8865 GNUNET_free (pm_old);
8866 }
8869 {
8872 }
8873 else
8875
8877 "%u items stored in DV ring buffer\n",
8880 }
8881 }
8882}
8883
8884
8890static void
8892{
8893 if (NULL != b->get)
8894 {
8896 b->get = NULL;
8897 GNUNET_assert (NULL != b->cmc);
8899 b->cmc = NULL;
8900 }
8901 if (NULL != b->task)
8902 {
8904 b->task = NULL;
8905 }
8906 if (NULL != b->sc)
8907 {
8909 "store cancel\n");
8911 b->sc = NULL;
8912 }
8914 "Removing backtalker for %s\n",
8915 GNUNET_i2s (&b->pid));
8917 GNUNET_YES ==
8919 GNUNET_free (b);
8920}
8921
8922
8931static int
8933 const struct GNUNET_PeerIdentity *pid,
8934 void *value)
8935{
8936 struct Backtalker *b = value;
8937
8938 (void) cls;
8939 (void) pid;
8940 free_backtalker (b);
8941 return GNUNET_OK;
8942}
8943
8944
8950static void
8952{
8953 struct Backtalker *b = cls;
8954
8956 "backtalker timeout.\n");
8957 b->task = NULL;
8959 {
8961 return;
8962 }
8963 GNUNET_assert (NULL == b->sc);
8964 free_backtalker (b);
8965}
8966
8967
8976static void
8978 const struct GNUNET_PEERSTORE_Record *record,
8979 const char *emsg)
8980{
8981 struct Backtalker *b = cls;
8982 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8983 struct GNUNET_TIME_Absolute mt;
8984
8985 (void) emsg;
8986 if (NULL == record)
8987 {
8988 /* we're done with #backtalker_monotime_cb() invocations,
8989 continue normal processing */
8990 b->get = NULL;
8991 GNUNET_assert (NULL != b->cmc);
8992 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8993 if (0 != b->body_size)
8995 else
8997 b->cmc = NULL;
8998 return;
8999 }
9000 if (sizeof(*mtbe) != record->value_size)
9001 {
9003 GNUNET_break (0);
9004 return;
9005 }
9006 mtbe = record->value;
9007 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
9009 {
9011 "Backtalker message from %s dropped, monotime in the past\n",
9012 GNUNET_i2s (&b->pid));
9014 GST_stats,
9015 "# Backchannel messages dropped: monotonic time not increasing",
9016 1,
9017 GNUNET_NO);
9018 b->monotonic_time = mt;
9019 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
9020 */
9021 b->body_size = 0;
9022 }
9024}
9025
9026
9034static void
9035backtalker_monotime_store_cb (void *cls, int success)
9036{
9037 struct Backtalker *b = cls;
9038
9039 if (GNUNET_OK != success)
9040 {
9042 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
9043 }
9044 b->sc = NULL;
9045 if (NULL != b->task)
9046 {
9048 b->task = NULL;
9049 }
9051}
9052
9053
9059static void
9061{
9062 struct GNUNET_TIME_AbsoluteNBO mtbe;
9063
9064 if (NULL != b->sc)
9065 {
9067 "store cancel before store with sc %p\n",
9068 b->sc);
9069 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9070 b->sc = NULL;*/
9072 "store cancel before store with sc %p is null\n",
9073 b->sc);
9074 }
9075 else
9076 {
9078 b->task = NULL;
9079 }
9081 b->sc =
9083 "transport",
9084 &b->pid,
9086 &mtbe,
9087 sizeof(mtbe),
9091 b);
9092}
9093
9094
9101
9102
9103static void
9104decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
9105{
9106 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
9107 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
9108 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
9109 struct DVKeyState key;
9110 const char *hdr;
9111 size_t hdr_len;
9112 struct GNUNET_HashCode hmac;
9113
9114 decaps_dv_box_cls->pr->op = NULL;
9117 decaps_dv_box_cls->pr);
9118 GNUNET_free (decaps_dv_box_cls->pr);
9119 if (NULL == km)
9120 {
9121 GNUNET_break_op (0);
9122 finish_cmc_handling (cmc);
9123 return;
9124 }
9125 dv_setup_key_state_from_km (km, &dvb->iv, &key);
9126 hdr = (const char *) &dvb[1];
9127 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
9129 * ntohs (dvb->total_hops);
9130
9131 dv_hmac (&key, &hmac, hdr, hdr_len);
9132 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
9133 {
9134 /* HMAC mismatch, discard! */
9135 GNUNET_break_op (0);
9136 finish_cmc_handling (cmc);
9137 return;
9138 }
9139 /* begin actual decryption */
9140 {
9141 struct Backtalker *b;
9142 struct GNUNET_TIME_Absolute monotime;
9143 struct TransportDVBoxPayloadP ppay = { 0 };
9144 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
9145 const struct GNUNET_MessageHeader *mh;
9146
9147 GNUNET_assert (hdr_len >=
9148 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
9149 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
9150 {
9152 "Error decrypting DV payload header\n");
9153 GNUNET_break_op (0);
9154 finish_cmc_handling (cmc);
9155 return;
9156 }
9157 if (GNUNET_OK != dv_decrypt (&key, body,
9158 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
9159 {
9161 "Error decrypting DV payload\n");
9162 GNUNET_break_op (0);
9163 finish_cmc_handling (cmc);
9164 return;
9165 }
9166 mh = (const struct GNUNET_MessageHeader *) body;
9167 dv_key_clean (&key);
9168 if (ntohs (mh->size) != sizeof(body))
9169 {
9170 GNUNET_break_op (0);
9171 finish_cmc_handling (cmc);
9172 return;
9173 }
9174 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9175 switch (ntohs (mh->type))
9176 {
9178 GNUNET_break_op (0);
9179 finish_cmc_handling (cmc);
9180 return;
9181
9183 GNUNET_break_op (0);
9184 finish_cmc_handling (cmc);
9185 return;
9186
9187 default:
9188 /* permitted, continue */
9189 break;
9190 }
9191 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
9193 "Decrypted backtalk from %s\n",
9194 GNUNET_i2s (&ppay.sender));
9196 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9197 {
9199 GST_stats,
9200 "# Backchannel messages dropped: monotonic time not increasing",
9201 1,
9202 GNUNET_NO);
9203 finish_cmc_handling (cmc);
9204 return;
9205 }
9206 if ((NULL == b) ||
9207 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9208 {
9209 /* Check signature */
9210 const struct GNUNET_PeerIdentity *my_identity;
9211 struct EphemeralConfirmationPS ec;
9212
9215
9217 ec.target = *my_identity;
9218 ec.ephemeral_key = dvb->ephemeral_key;
9219 ec.purpose.size = htonl (sizeof(ec));
9221 if (
9222 GNUNET_OK !=
9225 &ec,
9226 &ppay.sender_sig,
9227 &ppay.sender.public_key))
9228 {
9229 /* Signature invalid, discard! */
9230 GNUNET_break_op (0);
9231 finish_cmc_handling (cmc);
9232 return;
9233 }
9234 }
9235 /* Update sender, we now know the real origin! */
9237 "DVBox received for me from %s via %s\n",
9238 GNUNET_i2s2 (&ppay.sender),
9239 GNUNET_i2s (&cmc->im.sender));
9240 cmc->im.sender = ppay.sender;
9241
9242 if (NULL != b)
9243 {
9244 /* update key cache and mono time */
9245 b->last_ephemeral = dvb->ephemeral_key;
9246 b->monotonic_time = monotime;
9248 b->timeout =
9250 cmc->mh = mh;
9252 return;
9253 }
9254 /* setup data structure to cache signature AND check
9255 monotonic time with PEERSTORE before forwarding backchannel payload */
9256 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
9257 b->pid = ppay.sender;
9258 b->body_size = sizeof(body);
9259 memcpy (&b[1], body, sizeof(body));
9263 &b->pid,
9264 b,
9266 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9267 b->cmc = cmc;
9268 b->timeout =
9271 b->get =
9273 "transport",
9274 &b->pid,
9277 b);
9278 } /* end actual decryption */
9279}
9280
9281
9289static void
9290handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9291{
9292 struct CommunicatorMessageContext *cmc = cls;
9293 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9294 uint16_t num_hops = ntohs (dvb->num_hops);
9295 const struct GNUNET_PeerIdentity *hops =
9296 (const struct GNUNET_PeerIdentity *) &dvb[1];
9297 const char *enc_payload = (const char *) &hops[num_hops];
9298 uint16_t enc_payload_size =
9299 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9300 struct DecapsDvBoxCls *decaps_dv_box_cls;
9301 const struct GNUNET_PeerIdentity *my_identity;
9302
9305
9306 if (GNUNET_EXTRA_LOGGING > 0)
9307 {
9308 char *path;
9309
9311 for (unsigned int i = 0; i < num_hops; i++)
9312 {
9313 char *tmp;
9314
9315 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9316 GNUNET_free (path);
9317 path = tmp;
9318 }
9320 "Received DVBox with remaining path %s\n",
9321 path);
9322 GNUNET_free (path);
9323 }
9324
9325 if (num_hops > 0)
9326 {
9327 /* We're trying from the end of the hops array, as we may be
9328 able to find a shortcut unknown to the origin that way */
9329 for (int i = num_hops - 1; i >= 0; i--)
9330 {
9331 struct Neighbour *n;
9332
9333 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9334 {
9335 GNUNET_break_op (0);
9336 finish_cmc_handling (cmc);
9337 return;
9338 }
9339 n = lookup_neighbour (&hops[i]);
9340 if (NULL == n)
9341 continue;
9343 "Skipping %u/%u hops ahead while routing DV Box\n",
9344 i,
9345 num_hops);
9346
9347 forward_dv_box (n,
9348 (struct TransportDVBoxMessage *) dvb,
9349 ntohs (dvb->total_hops) + 1,
9350 num_hops - i - 1, /* number of hops left */
9351 &hops[i + 1], /* remaining hops */
9352 enc_payload,
9353 enc_payload_size);
9355 "# DV hops skipped routing boxes",
9356 i,
9357 GNUNET_NO);
9359 "# DV boxes routed (total)",
9360 1,
9361 GNUNET_NO);
9362 finish_cmc_handling (cmc);
9363 return;
9364 }
9365 /* Woopsie, next hop not in neighbours, drop! */
9367 "# DV Boxes dropped: next hop unknown",
9368 1,
9369 GNUNET_NO);
9370 finish_cmc_handling (cmc);
9371 return;
9372 }
9373 /* We are the target. Unbox and handle message. */
9375 "# DV boxes opened (ultimate target)",
9376 1,
9377 GNUNET_NO);
9378 cmc->total_hops = ntohs (dvb->total_hops);
9379
9380 {
9381 // DH key derivation with received DV, could be garbage.
9382 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9383 decaps_dv_box_cls->cmc = cmc;
9384 decaps_dv_box_cls->dvb = dvb;
9385 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9386
9389 decaps_dv_box_cls->pr);
9390 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9391 &dvb->ephemeral_key,
9393 decaps_dv_box_cls);
9394 }
9395 // TODO keep track of cls and potentially clean
9396}
9397
9398
9406static int
9408 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9409{
9410 struct TransportClient *tc = cls;
9411
9412 if (CT_COMMUNICATOR != tc->type)
9413 {
9414 GNUNET_break (0);
9415 return GNUNET_SYSERR;
9416 }
9418 return GNUNET_OK;
9419}
9420
9421
9426{
9430 const char *address;
9431
9436};
9437
9438
9448static int
9450 const struct GNUNET_PeerIdentity *pid,
9451 void *value)
9452{
9453 struct CheckKnownAddressContext *ckac = cls;
9454 struct ValidationState *vs = value;
9455
9456 (void) pid;
9457 if (0 != strcmp (vs->address, ckac->address))
9458 return GNUNET_OK;
9459 ckac->vs = vs;
9460 return GNUNET_NO;
9461}
9462
9463
9469static void
9470validation_start_cb (void *cls);
9471
9472
9480static void
9482 struct GNUNET_TIME_Absolute new_time)
9483{
9485
9486 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9487 return; /* be lazy */
9488 vs->next_challenge = new_time;
9489 if (NULL == vs->hn)
9490 vs->hn =
9492 else
9495 (NULL != validation_task))
9496 return;
9497 if (NULL != validation_task)
9499 /* randomize a bit */
9502 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9503 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9506}
9507
9508
9515static void
9517 const char *address)
9518{
9519 struct GNUNET_TIME_Absolute now;
9520 struct ValidationState *vs;
9521 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9522
9524 pid,
9526 &ckac);
9527 if (NULL != (vs = ckac.vs))
9528 {
9529 /* if 'vs' is not currently valid, we need to speed up retrying the
9530 * validation */
9531 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9532 {
9533 /* reduce backoff as we got a fresh advertisement */
9534 vs->challenge_backoff =
9537 vs->challenge_backoff,
9538 2));
9541 vs->challenge_backoff));
9542 }
9543 return;
9544 }
9546 vs = GNUNET_new (struct ValidationState);
9547 vs->pid = *pid;
9548 vs->valid_until =
9550 vs->first_challenge_use = now;
9551 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9553 &vs->challenge,
9554 sizeof(vs->challenge));
9555 vs->address = GNUNET_strdup (address);
9556 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9558 "Starting address validation `%s' of peer %s using challenge %s\n",
9559 address,
9560 GNUNET_i2s (pid),
9561 GNUNET_sh2s (&vs->challenge.value));
9565 &vs->pid,
9566 vs,
9569}
9570
9571
9572static struct Queue *
9573find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9574
9575
9576static void
9577suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9578
9579
9580static void
9582 const struct GNUNET_PeerIdentity *pid,
9583 const char *uri)
9584{
9585 struct Queue *q;
9586 int pfx_len;
9587 const char *eou;
9588 char *address;
9589 (void) cls;
9590
9591 eou = strstr (uri,
9592 "://");
9593 pfx_len = eou - uri;
9594 eou += 3;
9596 "%.*s-%s",
9597 pfx_len,
9598 uri,
9599 eou);
9600
9602 "helo for client %s\n",
9603 address);
9604 q = find_queue (pid, address);
9605 if (NULL == q)
9606 {
9608 }
9609 else
9612}
9613
9614
9622static void
9624 const struct GNUNET_PEERSTORE_Record *record,
9625 const char *emsg)
9626{
9627 struct IncomingRequest *ir = cls;
9628 struct GNUNET_HELLO_Parser *parser;
9629 struct GNUNET_MessageHeader *hello;
9630 const struct GNUNET_PeerIdentity *my_identity;
9631
9632 if (NULL != emsg)
9633 {
9635 "Got failure from PEERSTORE: %s\n",
9636 emsg);
9637 return;
9638 }
9639 hello = record->value;
9642 if (0 == GNUNET_memcmp (&record->peer, my_identity))
9643 {
9645 return;
9646 }
9647 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
9650 NULL);
9651 GNUNET_HELLO_parser_free (parser);
9652}
9653
9654
9655static void
9657{
9659 "Error in PEERSTORE monitoring\n");
9660}
9661
9662
9663static void
9665{
9667 "Done with initial PEERSTORE iteration during monitoring\n");
9668}
9669
9670
9677
9678
9679static void
9681 const struct GNUNET_PeerIdentity *pid,
9682 const struct GNUNET_CRYPTO_EddsaSignature *sig)
9683{
9684 struct SignTValidationCls *sign_t_validation_cls = cls;
9685 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9686 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9687 struct VirtualLink *vl;
9688 struct Neighbour *n;
9689 struct IncomingRequest *ir;
9690 struct GNUNET_PeerIdentity sender;
9691
9692 sign_t_validation_cls->pr->op = NULL;
9695 sign_t_validation_cls->pr);
9696 GNUNET_free (sign_t_validation_cls->pr);
9697 tvr.signature = *sig;
9698 sender = cmc->im.sender;
9699 vl = lookup_virtual_link (&sender);
9700 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9701 {
9702 // route_control_message_without_fc (&cmc->im.sender,
9704 &tvr.header,
9706 }
9707 else
9708 {
9709 /* Use route via neighbour */
9710 n = lookup_neighbour (&sender);
9711 if (NULL != n)
9712 route_via_neighbour (n, &tvr.header,
9715 }
9716
9717 finish_cmc_handling (cmc);
9718 if (NULL != vl)
9719 return;
9720
9721 /* For us, the link is still down, but we need bi-directional
9722 connections (for flow-control and for this to be useful for
9723 CORE), so we must try to bring the link up! */
9724
9725 /* (1) Check existing queues, if any, we may be lucky! */
9726 n = lookup_neighbour (&sender);
9727 if (NULL != n)
9728 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9729 start_address_validation (&sender, q->address);
9730 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9731 we could use */
9732 for (ir = ir_head; NULL != ir; ir = ir->next)
9733 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9734 return;
9735 /* we are already trying */
9736 ir = GNUNET_new (struct IncomingRequest);
9737 ir->pid = sender;
9739
9741 GNUNET_YES,
9742 "peerstore",
9743 NULL,
9746 NULL,
9748 NULL,
9750 ir);
9751 ir_total++;
9752 /* Bound attempts we do in parallel here, might otherwise get excessive */
9755};
9756
9757
9766static void
9768 void *cls,
9769 const struct TransportValidationChallengeMessage *tvc)
9770{
9771 struct CommunicatorMessageContext *cmc = cls;
9772 struct TransportValidationResponseMessage tvr = { 0 };
9773 struct GNUNET_TIME_RelativeNBO validity_duration;
9774
9775 /* DV-routed messages are not allowed for validation challenges */
9776 if (cmc->total_hops > 0)
9777 {
9778 GNUNET_break_op (0);
9779 finish_cmc_handling (cmc);
9780 return;
9781 }
9782 validity_duration = cmc->im.expected_address_validity;
9784 "Received address validation challenge %s\n",
9785 GNUNET_sh2s (&tvc->challenge.value));
9786 /* If we have a virtual link, we use this mechanism to signal the
9787 size of the flow control window, and to allow the sender
9788 to ask for increases. If for us the virtual link is still down,
9789 we will always give a window size of zero. */
9790 tvr.header.type =
9792 tvr.header.size = htons (sizeof(tvr));
9793 tvr.reserved = htonl (0);
9794 tvr.challenge = tvc->challenge;
9795 tvr.origin_time = tvc->sender_time;
9796 tvr.validity_duration = validity_duration;
9797 {
9798 /* create signature */
9799 struct TransportValidationPS tvp = {
9801 .purpose.size = htonl (sizeof(tvp)),
9802 .validity_duration = validity_duration,
9803 .challenge = tvc->challenge
9804 };
9805 struct SignTValidationCls *sign_t_validation_cls;
9806
9807 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9808 sign_t_validation_cls->cmc = cmc;
9809 sign_t_validation_cls->tvr = tvr;
9810 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9813 sign_t_validation_cls->pr);
9814 sign_t_validation_cls->pr->op =
9816 &tvp.purpose,
9818 sign_t_validation_cls);
9819 }
9820}
9821
9822
9838
9839
9849static int
9851 const struct GNUNET_PeerIdentity *pid,
9852 void *value)
9853{
9854 struct CheckKnownChallengeContext *ckac = cls;
9855 struct ValidationState *vs = value;
9856
9857 (void) pid;
9858 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9859 return GNUNET_OK;
9860 ckac->vs = vs;
9861 return GNUNET_NO;
9862}
9863
9864
9872static void
9873peerstore_store_validation_cb (void *cls, int success)
9874{
9875 struct ValidationState *vs = cls;
9876
9877 vs->sc = NULL;
9878 if (GNUNET_YES == success)
9879 return;
9881 "# Peerstore failed to store foreign address",
9882 1,
9883 GNUNET_NO);
9884}
9885
9886
9894static struct Queue *
9895find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9896{
9897 struct Neighbour *n;
9898
9899 n = lookup_neighbour (pid);
9900 if (NULL == n)
9901 return NULL;
9902 for (struct Queue *pos = n->queue_head; NULL != pos;
9903 pos = pos->next_neighbour)
9904 {
9905 if (0 == strcmp (pos->address, address))
9906 return pos;
9907 }
9908 return NULL;
9909}
9910
9911
9912static void
9914
9915static void
9917{
9918 struct ValidationState *vs = cls;
9919 struct Queue *q;
9920 struct GNUNET_TIME_Absolute now;
9921
9922 vs->revalidation_task = NULL;
9923 q = find_queue (&vs->pid, vs->address);
9924 if (NULL == q)
9925 {
9926 now = GNUNET_TIME_absolute_get ();
9927 vs->awaiting_queue = GNUNET_YES;
9928 suggest_to_connect (&vs->pid, vs->address);
9930 }
9931 else
9933}
9934
9935
9936static enum GNUNET_GenericReturnValue
9938 void *cls,
9939 const struct GNUNET_HashCode *key,
9940 void *value)
9941{
9942 (void) cls;
9944 "Key in revalidate map %s \n",
9945 GNUNET_h2s (key));
9946 return GNUNET_YES;
9947}
9948
9949
9958static void
9960 void *cls,
9961 const struct TransportValidationResponseMessage *tvr)
9962{
9963 struct CommunicatorMessageContext *cmc = cls;
9964 struct ValidationState *vs;
9965 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9966 .vs = NULL};
9967 struct GNUNET_TIME_Absolute origin_time;
9968 struct Queue *q;
9969 struct Neighbour *n;
9970 struct VirtualLink *vl;
9972 GST_cfg);
9973
9974 /* check this is one of our challenges */
9976 &cmc->im.sender,
9978 &ckac);
9979 if (NULL == (vs = ckac.vs))
9980 {
9981 /* This can happen simply if we 'forgot' the challenge by now,
9982 i.e. because we received the validation response twice */
9984 "# Validations dropped, challenge unknown",
9985 1,
9986 GNUNET_NO);
9988 "Validation response %s dropped, challenge unknown\n",
9989 GNUNET_sh2s (&tvr->challenge.value));
9990 finish_cmc_handling (cmc);
9991 return;
9992 }
9993
9994 /* sanity check on origin time */
9995 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9996 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9997 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9998 {
10000 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
10001 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
10002 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
10003 GNUNET_break_op (0);
10004 finish_cmc_handling (cmc);
10005 return;
10006 }
10007
10008 {
10009 /* check signature */
10010 struct TransportValidationPS tvp = {
10012 .purpose.size = htonl (sizeof(tvp)),
10013 .validity_duration = tvr->validity_duration,
10014 .challenge = tvr->challenge
10015 };
10016
10017 if (
10018 GNUNET_OK !=
10020 &tvp,
10021 &tvr->signature,
10022 &cmc->im.sender.public_key))
10023 {
10024 GNUNET_break_op (0);
10025 finish_cmc_handling (cmc);
10026 return;
10027 }
10028 }
10029
10030 /* validity is capped by our willingness to keep track of the
10031 validation entry and the maximum the other peer allows */
10034 tvr->validity_duration),
10036 vs->validated_until =
10040 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
10041 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
10043 &vs->challenge,
10044 sizeof(vs->challenge));
10045 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
10046 vs->validated_until,
10047 GNUNET_TIME_relative_multiply (vs->validation_rtt,
10049 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
10050 {
10052 "First challenge use is now %" PRIu64 " %s \n",
10053 vs->first_challenge_use.abs_value_us,
10054 GNUNET_sh2s (&vs->challenge.value));
10055 vs->first_challenge_use = now;
10056 }
10057 else
10059 "First challenge use is later %" PRIu64 " %s \n",
10060 vs->first_challenge_use.abs_value_us,
10061 GNUNET_sh2s (&vs->challenge.value));
10062 vs->last_challenge_use =
10063 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10064 update_next_challenge_time (vs, vs->first_challenge_use);
10066 "Validation response %s from %s accepted, address valid until %s\n",
10067 GNUNET_sh2s (&tvr->challenge.value),
10068 GNUNET_i2s (&cmc->im.sender),
10070 /*memcpy (&hkey,
10071 &hc,
10072 sizeof (hkey));*/
10074 "Key %s for address %s map size %u contains %u\n",
10075 GNUNET_h2s (&vs->hc),
10076 vs->address,
10079 &vs->hc));
10083 &vs->hc,
10084 vs,
10088 NULL);
10089 vs->revalidation_task =
10094 "transport",
10095 &cmc->im.sender,
10097 vs->address,
10098 strlen (vs->address) + 1,
10099 vs->valid_until,
10102 vs);
10103 finish_cmc_handling (cmc);
10104
10105 /* Finally, we now possibly have a confirmed (!) working queue,
10106 update queue status (if queue still is around) */
10107 q = find_queue (&vs->pid, vs->address);
10108 if (NULL == q)
10109 {
10111 "# Queues lost at time of successful validation",
10112 1,
10113 GNUNET_NO);
10114 return;
10115 }
10116 q->validated_until = vs->validated_until;
10117 q->pd.aged_rtt = vs->validation_rtt;
10118 n = q->neighbour;
10119 vl = lookup_virtual_link (&vs->pid);
10120 if (NULL == vl)
10121 {
10122 vl = GNUNET_new (struct VirtualLink);
10124 "Creating new virtual link %p to %s using direct neighbour!\n",
10125 vl,
10126 GNUNET_i2s (&vs->pid));
10127 vl->burst_addr = NULL;
10128 vl->confirmed = GNUNET_YES;
10129 vl->message_uuid_ctr =
10131 vl->target = n->pid;
10137 links,
10138 &vl->target,
10139 vl,
10141 vl->n = n;
10142 n->vl = vl;
10143 q->idle = GNUNET_YES;
10144 vl->visibility_task =
10145 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10147 /* We lacked a confirmed connection to the target
10148 before, so tell CORE about it (finally!) */
10151 }
10152 else
10153 {
10154 /* Link was already up, remember n is also now available and we are done */
10155 if (NULL == vl->n)
10156 {
10157 vl->n = n;
10158 n->vl = vl;
10159 if (GNUNET_YES == vl->confirmed)
10161 "Virtual link to %s could now also use direct neighbour!\n",
10162 GNUNET_i2s (&vs->pid));
10163 }
10164 else
10165 {
10166 GNUNET_assert (n == vl->n);
10167 }
10168 if (GNUNET_NO == vl->confirmed)
10169 {
10170 vl->confirmed = GNUNET_YES;
10171 q->idle = GNUNET_YES;
10172 vl->visibility_task =
10173 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10175 /* We lacked a confirmed connection to the target
10176 before, so tell CORE about it (finally!) */
10179 }
10180 }
10181}
10182
10183
10189static void
10191 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10192{
10193 struct TransportClient *tc = cls;
10194 struct CommunicatorMessageContext *cmc =
10196
10197 cmc->tc = tc;
10198 cmc->im = *im;
10200 "Received message with size %u and flow control id %" PRIu64
10201 " via communicator from peer %s\n",
10202 ntohs (im->header.size),
10203 im->fc_id,
10204 GNUNET_i2s (&im->sender));
10205 cmc->im.neighbour_sender = cmc->im.sender;
10206 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10208}
10209
10210
10219static int
10221{
10222 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10223 (void) cls;
10224
10226 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10227 ntohs (fc->header.size),
10228 ntohl (fc->size_of_addresses),
10229 ntohl (fc->number_of_addresses),
10230 sizeof(struct TransportFlowControlMessage),
10231 sizeof (struct TransportGlobalNattedAddress));
10232
10233 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10235 + ntohl (fc->number_of_addresses) * sizeof (struct
10237 + ntohl (fc->size_of_addresses))
10238 return GNUNET_OK;
10239 else
10240 {
10241 GNUNET_break_op (0);
10242 return GNUNET_SYSERR;
10243 }
10244}
10245
10246
10247static struct GNUNET_TIME_Relative
10249{
10251 unsigned int n_hops = 0;
10252
10254 "calculate_rtt\n");
10255 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10256 pos = pos->next_dv)
10257 {
10259 "calculate_rtt %lu\n",
10260 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10261 n_hops++;
10263 aged_rtt, pos
10264 ->distance
10265 + 2), ret);
10266 }
10267
10268 GNUNET_assert (0 != n_hops);
10269
10270 return ret;
10271}
10272
10273
10274static void
10276 const struct GNUNET_PeerIdentity *pid,
10277 const char *uri)
10278{
10279 struct VirtualLink *vl = cls;
10280 const char *slash;
10281 char *address_uri;
10282 char *prefix;
10283 char *uri_without_port;
10284
10285 slash = strrchr (uri, '/');
10286 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10287 GNUNET_assert (NULL != slash);
10288 slash++;
10289 GNUNET_asprintf (&address_uri,
10290 "%s-%s",
10291 prefix,
10292 slash);
10293
10294 uri_without_port = get_address_without_port (address_uri);
10296 "iterate_address_start_burst %s %s %s %s\n",
10297 uri_without_port,
10298 uri,
10299 address_uri,
10300 slash);
10301 if (0 == strcmp (uri_without_port, slash))
10302 {
10303 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10304 );
10305 }
10306 else
10307 vl->burst_addr = NULL;
10308
10310 GNUNET_free (uri_without_port);
10311}
10312
10313
10314static void
10316 const struct GNUNET_PEERSTORE_Record *record,
10317 const char *emsg)
10318{
10319 struct GNUNET_StartBurstCls *sb_cls = cls;
10320 struct VirtualLink *vl = sb_cls->vl;
10321 struct GNUNET_MessageHeader *hello;
10322 struct GNUNET_HELLO_Parser *parser;
10323
10324 if (NULL != emsg)
10325 {
10327 "Got failure from PEERSTORE: %s\n",
10328 emsg);
10329 return;
10330 }
10331 if (NULL == record)
10332 {
10334 "Hello iteration end for %s\n",
10335 GNUNET_i2s (&vl->target));
10336 vl->ic = NULL;
10337 GNUNET_free (sb_cls);
10338 return;
10339 }
10340
10342 "check_for_burst_address\n");
10343 hello = record->value;
10344 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10347 vl);
10348 GNUNET_HELLO_parser_free (parser);
10349
10351 GNUNET_free (sb_cls);
10352}
10353
10354
10355static void
10356burst_timeout (void *cls)
10357{
10359}
10360
10361
10362static void
10363start_burst (void *cls)
10364{
10365 struct GNUNET_StartBurstCls *sb_cls = cls;
10366 struct VirtualLink *vl = sb_cls->vl;
10367 struct GNUNET_TRANSPORT_StartBurst *sb;
10368 struct GNUNET_MQ_Envelope *env;
10369 char *uri_without_port = vl->burst_addr;
10370
10371 burst_task = NULL;
10372 /*char buf[strlen (uri_without_port) + 1];
10373
10374 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10375 buf[strlen (uri_without_port)] = '\0';*/
10376 env =
10378 strlen (uri_without_port) + 1,
10380 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10381 sb->pid = vl->target;
10382 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10383 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10384 {
10386 "iterate_address_start_burst client tc prefix %s\n",
10387 tc->details.communicator.address_prefix);
10388 if (CT_COMMUNICATOR != tc->type)
10389 continue;
10390 if (GNUNET_YES == tc->details.communicator.can_burst)
10391 {
10393 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10394 uri_without_port,
10395 strlen (uri_without_port),
10396 ntohs (sb->header.size),
10397 (unsigned long) sb_cls->rtt.rel_value_us);
10398 GNUNET_MQ_send (tc->mq, env);
10402 60),
10404 NULL);
10405 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10406 break;
10407 }
10408 }
10409 GNUNET_free (env);
10410 GNUNET_free (sb_cls);
10411}
10412
10413
10414static void
10415queue_burst (void *cls)
10416{
10417 struct GNUNET_StartBurstCls *sb_cls = cls;
10418 struct VirtualLink *vl = sb_cls->vl;
10419
10420 if (GNUNET_YES != use_burst)
10421 return;
10423 "burst_task %p ready %s burst addr %s (%p)\n",
10424 burst_task,
10425 sb_cls->sync_ready ? "yes" : "no",
10426 vl->burst_addr,
10427 vl->burst_addr);
10428 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10429 {
10431 burst_task = NULL;
10433 return;
10434 }
10435 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10436 )
10437 {
10439 &start_burst,
10440 sb_cls);
10441 }
10442 else if (NULL == vl->burst_addr)
10443 {
10445 "peerstore",
10446 &vl->target,
10449 sb_cls);
10450 }
10451}
10452
10453
10462static void
10464{
10465 struct CommunicatorMessageContext *cmc = cls;
10466 struct VirtualLink *vl;
10468 uint32_t seq;
10469 struct GNUNET_TIME_Absolute st;
10470 uint64_t os;
10471 uint64_t wnd;
10472 uint32_t random;
10473
10475 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10476 vl = lookup_virtual_link (&cmc->im.sender);
10477 if (NULL == vl)
10478 {
10479 vl = GNUNET_new (struct VirtualLink);
10481 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10482 vl,
10483 GNUNET_i2s (&cmc->im.sender));
10484 vl->burst_addr = NULL;
10485 vl->confirmed = GNUNET_NO;
10486 vl->message_uuid_ctr =
10488 vl->target = cmc->im.sender;
10494 links,
10495 &vl->target,
10496 vl,
10498 }
10499 if (NULL != vl->n)
10500 {
10501 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10502 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10503 }
10504
10506 "remaining %lu timeout for neighbour %p\n",
10507 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10508 rel_value_us,
10509 vl->n);
10510 if (NULL == vl->n ||
10511 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10512 {
10513 struct GNUNET_TIME_Relative rtt;
10514 struct GNUNET_BurstSync burst_sync;
10515 struct GNUNET_StartBurstCls *bcls;
10516
10517 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10518 bcls->vl = vl;
10519 vl->sb_cls = bcls;
10520 if (NULL != vl->dv)
10521 rtt = calculate_rtt (vl->dv);
10522 else
10524 burst_sync.rtt_average = fc->rtt;
10525 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10526 burst_sync.sync_ready = fc->sync_ready;
10527
10529 &burst_sync,
10530 &queue_burst,
10531 bcls);
10532 }
10533 if (0 != ntohl (fc->number_of_addresses))
10534 {
10535 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10536 const char *tgnas;
10537 unsigned int off = 0;
10538
10539 tgnas = (const char *) &fc[1];
10540
10541 for (int i = 1; i <= number_of_addresses; i++)
10542 {
10543 struct TransportGlobalNattedAddress *tgna;
10544 char *addr;
10545 unsigned int address_length;
10546
10547 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10548 addr = (char *) &tgna[1];
10549 address_length = ntohl (tgna->address_length);
10550 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10551
10553 "received address %s length %u\n",
10554 addr,
10555 ntohl (tgna->address_length));
10556
10557 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10558 }
10559 }
10561 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10562 {
10564 "FC dropped: Message out of order\n");
10565 /* out of order, drop */
10567 "# FC dropped: message out of order",
10568 1,
10569 GNUNET_NO);
10570 finish_cmc_handling (cmc);
10571 return;
10572 }
10573 seq = ntohl (fc->seq);
10574 if (seq < vl->last_fc_seq)
10575 {
10576 /* Wrap-around/reset of other peer; start all counters from zero */
10578 }
10579 vl->last_fc_seq = seq;
10580 vl->last_fc_timestamp = st;
10582 os = GNUNET_ntohll (fc->outbound_sent);
10584 (int64_t) (os - vl->incoming_fc_window_size_used);
10586 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10587 GNUNET_i2s (&vl->target),
10588 (unsigned int) seq,
10589 (unsigned long long) vl->outbound_fc_window_size,
10590 (long long) vl->incoming_fc_window_size_loss);
10593 UINT32_MAX);
10594 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10598 != wnd) ||
10599 (0 == random
10601 {
10603 "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",
10604 (unsigned long long) wnd,
10605 (unsigned long long) vl->incoming_fc_window_size,
10606 (unsigned long long) vl->last_outbound_window_size_received,
10609 }
10610 if ((wnd == vl->incoming_fc_window_size
10614 (NULL != vl->fc_retransmit_task))
10615 {
10617 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10618 GNUNET_i2s (&vl->target),
10619 (unsigned long long) wnd);
10621 vl->fc_retransmit_task = NULL;
10622 vl->fc_retransmit_count = 0;
10623 }
10625 /* FC window likely increased, check transmission possibilities! */
10627 finish_cmc_handling (cmc);
10628}
10629
10630
10638static void
10640{
10642 { GNUNET_MQ_hd_var_size (fragment_box,
10645 cmc),
10646 GNUNET_MQ_hd_var_size (reliability_box,
10649 cmc),
10650 GNUNET_MQ_hd_var_size (reliability_ack,
10653 cmc),
10654 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10657 cmc),
10658 GNUNET_MQ_hd_var_size (dv_learn,
10661 cmc),
10662 GNUNET_MQ_hd_var_size (dv_box,
10664 struct TransportDVBoxMessage,
10665 cmc),
10666 GNUNET_MQ_hd_var_size (flow_control,
10669 cmc),
10671 validation_challenge,
10674 cmc),
10676 validation_response,
10679 cmc),
10681 int ret;
10682 const struct GNUNET_MessageHeader *msg = cmc->mh;
10683
10685 "Handling message of type %u with %u bytes\n",
10686 (unsigned int) ntohs (msg->type),
10687 (unsigned int) ntohs (msg->size));
10689 if (GNUNET_SYSERR == ret)
10690 {
10691 GNUNET_break (0);
10693 GNUNET_free (cmc);
10694 return;
10695 }
10696 if (GNUNET_NO == ret)
10697 {
10698 /* unencapsulated 'raw' message */
10699 handle_raw_message (cmc, msg);
10700 }
10701}
10702
10703
10710static int
10712 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10713{
10714 struct TransportClient *tc = cls;
10715
10716 if (CT_COMMUNICATOR != tc->type)
10717 {
10718 GNUNET_break (0);
10719 return GNUNET_SYSERR;
10720 }
10722 return GNUNET_OK;
10723}
10724
10725
10731static void
10733{
10734 if (pm->msg_uuid_set)
10735 return;
10736 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10737 pm->msg_uuid_set = GNUNET_YES;
10738}
10739
10740
10749static struct PendingAcknowledgement *
10751 struct DistanceVectorHop *dvh,
10752 struct PendingMessage *pm)
10753{
10754 struct PendingAcknowledgement *pa;
10755
10756 pa = GNUNET_new (struct PendingAcknowledgement);
10757 pa->queue = queue;
10758 pa->dvh = dvh;
10759 pa->pm = pm;
10760 do
10761 {
10763 &pa->ack_uuid,
10764 sizeof(pa->ack_uuid));
10765 }
10768 &pa->ack_uuid.value,
10769 pa,
10771 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10772 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10773 if (NULL != dvh)
10776 pa->message_size = pm->bytes_msg;
10778 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10780 pm->logging_uuid);
10781 return pa;
10782}
10783
10784
10796static struct PendingMessage *
10798 struct DistanceVectorHop *dvh,
10799 struct PendingMessage *pm)
10800{
10801 struct PendingAcknowledgement *pa;
10802 struct PendingMessage *ff;
10803 uint16_t mtu;
10804 uint16_t msize;
10805
10806 mtu = (UINT16_MAX == queue->mtu)
10807 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10808 : queue->mtu;
10810 "Fragmenting message <%" PRIu64
10811 "> with size %u to %s for MTU %u\n",
10812 pm->logging_uuid,
10813 pm->bytes_msg,
10814 GNUNET_i2s (&pm->vl->target),
10815 (unsigned int) mtu);
10818 "Fragmenting message %" PRIu64 " <%" PRIu64
10819 "> with size %u to %s for MTU %u\n",
10820 pm->msg_uuid.uuid,
10821 pm->logging_uuid,
10822 pm->bytes_msg,
10823 GNUNET_i2s (&pm->vl->target),
10824 (unsigned int) mtu);
10825
10826 /* This invariant is established in #handle_add_queue_message() */
10827 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10828
10829 /* select fragment for transmission, descending the tree if it has
10830 been expanded until we are at a leaf or at a fragment that is small
10831 enough
10832 */
10833 ff = pm;
10834 msize = ff->bytes_msg;
10835
10836 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10837 (ff->frag_off == msize) && (NULL != ff->head_frag))
10838 {
10839 ff = ff->head_frag; /* descent into fragmented fragments */
10840 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10841 }
10842
10843 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10844 {
10845 /* Did not yet calculate all fragments, calculate next fragment */
10846 struct PendingMessage *frag;
10847 struct TransportFragmentBoxMessage tfb;
10848 const char *orig;
10849 char *msg;
10850 uint16_t fragmax;
10851 uint16_t fragsize;
10852 uint16_t msize_ff;
10853 uint16_t xoff = 0;
10854 pm->frag_count++;
10855
10856 orig = (const char *) &ff[1];
10857 msize_ff = ff->bytes_msg;
10858 if (pm != ff)
10859 {
10860 const struct TransportFragmentBoxMessage *tfbo;
10861
10862 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10863 orig += sizeof(struct TransportFragmentBoxMessage);
10864 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10865 xoff = ntohs (tfbo->frag_off);
10866 }
10867 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10868 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10869 frag =
10870 GNUNET_malloc (sizeof(struct PendingMessage)
10871 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10873 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10874 frag,
10875 ff,
10876 pm->vl,
10877 pm);
10879 frag->vl = pm->vl;
10880 frag->frag_parent = ff;
10881 frag->timeout = pm->timeout;
10882 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10883 frag->pmt = PMT_FRAGMENT_BOX;
10884 msg = (char *) &frag[1];
10886 tfb.header.size =
10887 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10888 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10889 tfb.ack_uuid = pa->ack_uuid;
10890 tfb.msg_uuid = pm->msg_uuid;
10891 tfb.frag_off = htons (ff->frag_off + xoff);
10892 tfb.msg_size = htons (pm->bytes_msg);
10893 memcpy (msg, &tfb, sizeof(tfb));
10894 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10896 ff->tail_frag, frag);
10897 ff->frag_off += fragsize;
10898 ff = frag;
10899 }
10900
10901 /* Move head to the tail and return it */
10905 ff);
10909 ff);
10910
10911 return ff;
10912}
10913
10914
10927static struct PendingMessage *
10929 struct DistanceVectorHop *dvh,
10930 struct PendingMessage *pm)
10931{
10933 struct PendingAcknowledgement *pa;
10934 struct PendingMessage *bpm;
10935 char *msg;
10936
10937 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10938 return pm; /* already fragmented or reliability boxed, or control message:
10939 do nothing */
10940 if (NULL != pm->bpm)
10941 return pm->bpm; /* already computed earlier: do nothing */
10942 // TODO I guess we do not need this assertion. We might have a DLL with
10943 // fragments, because the MTU changed, and we do not need to fragment anymore.
10944 // But we should keep the fragments until message was completed, because
10945 // the MTU might change again.
10946 // GNUNET_assert (NULL == pm->head_frag);
10947 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10948 {
10949 /* failed hard */
10950 GNUNET_break (0);
10952 return NULL;
10953 }
10954
10956
10957 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10958 + pm->bytes_msg);
10960 "4 created pm %p storing vl %p from pm %p\n",
10961 bpm,
10962 pm->vl,
10963 pm);
10965 bpm->vl = pm->vl;
10966 bpm->frag_parent = pm;
10967 // Why was this needed?
10968 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10969 bpm->timeout = pm->timeout;
10971 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10974 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10975 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10976
10977 rbox.ack_uuid = pa->ack_uuid;
10978 msg = (char *) &bpm[1];
10979 memcpy (msg, &rbox, sizeof(rbox));
10980 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10981 pm->bpm = bpm;
10983 "Preparing reliability box for message <%" PRIu64
10984 "> of size %d (%d) to %s on queue %s\n",
10985 pm->logging_uuid,
10986 pm->bytes_msg,
10987 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10988 GNUNET_i2s (&pm->vl->target),
10989 queue->address);
10990 return bpm;
10991}
10992
10993
10994static void
10997{
10998 struct VirtualLink *vl = pm->vl;
10999 struct PendingMessage *pos;
11000
11001 /* re-insert sort in neighbour list */
11005 pm);
11006 pos = vl->pending_msg_tail;
11007 while ((NULL != pos) &&
11009 pos = pos->prev_vl;
11013 pos,
11014 pm);
11015}
11016
11017
11018static unsigned int
11020{
11021 struct PendingMessage *pos;
11023
11024 pos = pm->head_frag;
11025 while (NULL != pos)
11026 {
11027 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
11028 GNUNET_NO == check_next_attempt_tree (pos, root))
11030 else
11031 {
11033 break;
11034 }
11035 pos = pos->next_frag;
11036 }
11037
11038 return frags_in_flight;
11039}
11040
11041
11042static void
11044{
11045 struct PendingMessage *pos;
11046
11047 pos = pm->head_frag;
11048 while (NULL != pos)
11049 {
11050 pos->frags_in_flight_round = pm->frags_in_flight_round;
11052 pos = pos->next_frag;
11053 }
11054}
11055
11056
11065static void
11068{
11069 if (NULL == pm->frag_parent)
11070 {
11073 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11074 pm->logging_uuid,
11077 }
11078 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11079 {
11080 struct PendingMessage *root = pm->frag_parent;
11081
11082 while (NULL != root->frag_parent)
11083 root = root->frag_parent;
11085 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11086 root->logging_uuid,
11088 root->next_attempt = next_attempt;
11090 }
11091 else
11092 {
11093 struct PendingMessage *root = pm->frag_parent;
11094
11095 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11096 root = root->frag_parent;
11097
11099 "frag_count next attempt %u\n",
11100 root->frag_count);
11101
11102 if (GNUNET_NO == root->frags_in_flight)
11103 {
11104 root->next_attempt = next_attempt;
11106 root->frags_in_flight_round++;
11108 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11109 ">)set to %" PRIu64 "\n",
11110 pm->logging_uuid,
11111 root->logging_uuid,
11113 }
11114
11115 pm->next_attempt = root->next_attempt;
11116 pm->frags_in_flight_round = root->frags_in_flight_round;
11118
11119 if (root->bytes_msg == root->frag_off)
11120 root->frags_in_flight = check_next_attempt_tree (root, root);
11121 else
11123
11124 if (GNUNET_NO == root->frags_in_flight)
11125 {
11127 "We have no fragments in flight for message %" PRIu64
11128 ", reorder root! Next attempt is %" PRIu64 "\n",
11129 root->logging_uuid,
11131 if (PMT_DV_BOX == root->pmt)
11132 root = root->frag_parent;
11133 reorder_root_pm (root, root->next_attempt);
11134 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11135 }
11136 else
11137 {
11138 double factor = ((double) root->frag_count - 1)
11139 / (double) root->frag_count;
11140 struct GNUNET_TIME_Relative s1;
11141 struct GNUNET_TIME_Relative s2;
11142 struct GNUNET_TIME_Relative plus_mean =
11145 next_attempt);
11146
11148 "frag_count %u after factor\n",
11149 root->frag_count);
11151 factor);
11152 s2 = GNUNET_TIME_relative_divide (plus,
11153 root->frag_count);
11154 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11157 "We have fragments in flight for message %" PRIu64
11158 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11159 root->logging_uuid,
11161 }
11162 }
11163}
11164
11165
11170{
11175
11180
11185
11190
11194 int frag;
11195
11199 int relb;
11200
11205
11209 unsigned int frags_in_flight;
11210
11215};
11216
11217
11229static void
11231 struct Queue *queue,
11232 struct VirtualLink *vl,
11233 struct DistanceVectorHop *dvh,
11234 size_t overhead)
11235{
11236 struct GNUNET_TIME_Absolute now;
11237
11238 now = GNUNET_TIME_absolute_get ();
11239 sc->to_early = GNUNET_NO;
11240 sc->frags_in_flight = GNUNET_NO;
11241 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11242 pos = pos->next_vl)
11243 {
11244 size_t real_overhead = overhead;
11245 int frag;
11246 int relb;
11247
11248 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11249 {
11251 "DV messages must not be DV-routed to next hop!\n");
11252 continue; /* DV messages must not be DV-routed to next hop! */
11253 }
11254 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11255 {
11256 if (GNUNET_YES == pos->frags_in_flight)
11257 {
11258 sc->frags_in_flight = GNUNET_YES;
11260 "Fragments in flight for message %" PRIu64 "\n",
11261 pos->logging_uuid);
11262 }
11263 else
11264 {
11266 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11267 PRIu64 "\n",
11268 pos->logging_uuid);
11269 sc->to_early = GNUNET_YES;
11270 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11271 pos->next_attempt);
11272 continue;
11273 }
11274 // break; /* too early for all messages, they are sorted by next_attempt */
11275 }
11276 if (NULL != pos->qe)
11277 {
11279 "not eligible\n");
11280 continue; /* not eligible */
11281 }
11282 sc->consideration_counter++;
11283 /* determine if we have to fragment, if so add fragmentation
11284 overhead! */
11286 "check %" PRIu64 " for sc->best\n",
11287 pos->logging_uuid);
11288 frag = GNUNET_NO;
11289 if (((0 != queue->mtu) &&
11290 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11291 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11293 ||
11294 (NULL != pos->head_frag /* fragments already exist, should
11295 respect that even if MTU is UINT16_MAX for
11296 this queue */))
11297 {
11299 "fragment msg with size %u, realoverhead is %lu\n",
11300 pos->bytes_msg,
11301 real_overhead);
11302 frag = GNUNET_YES;
11303 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11304 {
11305 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11306 header without the ACK UUID when using a *reliable* channel! */
11307 }
11308 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11309 }
11310 /* determine if we have to reliability-box, if so add reliability box
11311 overhead */
11312 relb = GNUNET_NO;
11313 if ((GNUNET_NO == frag) &&
11314 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11315 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11316 {
11317 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11318
11319 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11320 {
11321 frag = GNUNET_YES;
11322 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11323 }
11324 else
11325 {
11326 relb = GNUNET_YES;
11327 }
11329 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11330 pos->bytes_msg,
11331 real_overhead,
11332 queue->mtu,
11333 frag,
11334 relb);
11335 }
11336
11337 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11338 message would beat it! */
11339 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11340 {
11341 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11342 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11343 experimentally validated. There may be some huge potential for
11344 improvement here. Also, we right now only compare how well the
11345 given message fits _this_ queue, and do not consider how well other
11346 queues might suit the message. Taking other queues into consideration
11347 may further improve the result, but could also be expensive
11348 in terms of CPU time. */
11349 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11350 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11351 long long time_delta =
11352 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11353 / 1000LL;
11354
11355 /* "time_delta" considers which message has been 'ready' for transmission
11356 for longer, if a message has a preference for low latency, increase
11357 the weight of the time_delta by 10x if it is favorable for that message */
11358 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11359 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11360 time_delta *= 10; /* increase weight (always, both are low latency) */
11361 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11362 (time_delta > 0))
11363 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11364 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11365 (time_delta < 0))
11366 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11367 if (0 != queue->mtu)
11368 {
11369 /* Grant bonus if we are below MTU, larger bonus the closer we will
11370 be to the MTU */
11371 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11372 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11373 if (queue->mtu > real_overhead + pos->bytes_msg)
11374 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11375 }
11376 if (sc_score + time_delta > pm_score)
11377 {
11379 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11380 "\n",
11381 pos->logging_uuid,
11382 sc->best->logging_uuid);
11383 continue; /* sc_score larger, keep sc->best */
11384 }
11385 }
11386 sc->best = pos;
11387 sc->dvh = dvh;
11388 sc->frag = frag;
11389 sc->relb = relb;
11390 sc->real_overhead = real_overhead;
11391 }
11392}
11393
11394
11405static void
11407 struct Neighbour *next_hop,
11408 const struct GNUNET_MessageHeader *hdr,
11410{
11411 struct PendingMessageScoreContext *sc = cls;
11412 struct PendingMessage *pm = sc->best;
11413 struct PendingMessage *bpm;
11414 uint16_t bsize = ntohs (hdr->size);
11415
11416 GNUNET_assert (NULL == pm->bpm);
11417 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11419 "5 created pm %p storing vl %p from pm %p\n",
11420 bpm,
11421 pm->vl,
11422 pm);
11424 bpm->pmt = PMT_DV_BOX;
11425 bpm->vl = pm->vl;
11426 bpm->timeout = pm->timeout;
11427 bpm->bytes_msg = bsize;
11428 bpm->frag_parent = pm;
11431 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11432 " (next hop is %s)\n",
11434 pm->logging_uuid,
11435 GNUNET_i2s (&next_hop->pid));
11436 memcpy (&bpm[1], hdr, bsize);
11437 pm->bpm = bpm;
11438}
11439
11440
11456static void
11458{
11459 struct Queue *queue = cls;
11460 struct Neighbour *n = queue->neighbour;
11462 struct PendingMessage *pm;
11463
11464 queue->transmit_task = NULL;
11465 if (NULL == n->vl)
11466 {
11468 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11469 GNUNET_i2s (&n->pid),
11470 queue->address);
11471 queue->idle = GNUNET_YES;
11472 return;
11473 }
11474 memset (&sc, 0, sizeof(sc));
11475 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11476 if (NULL == sc.best)
11477 {
11478 /* Also look at DVH that have the n as first hop! */
11479 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11480 dvh = dvh->next_neighbour)
11481 {
11483 queue,
11484 dvh->dv->vl,
11485 dvh,
11486 sizeof(struct GNUNET_PeerIdentity)
11487 * (1 + dvh->distance)
11488 + sizeof(struct TransportDVBoxMessage)
11489 + sizeof(struct TransportDVBoxPayloadP));
11490 }
11491 }
11492 if (NULL == sc.best)
11493 {
11494 /* no message pending, nothing to do here! */
11496 "No pending messages, queue `%s' to %s now idle\n",
11497 queue->address,
11498 GNUNET_i2s (&n->pid));
11499 if (GNUNET_YES == sc.to_early)
11500 schedule_transmit_on_queue (sc.to_early_retry_delay,
11501 queue,
11503 queue->idle = GNUNET_YES;
11504 return;
11505 }
11506 /* There is a message pending, we are certainly not idle */
11507 queue->idle = GNUNET_NO;
11508
11509 /* Given selection in `sc`, do transmission */
11510 pm = sc.best;
11512 "Selected message <%" PRIu64 ">\n",
11513 pm->logging_uuid);
11514 if (NULL != sc.dvh)
11515 {
11517 "Is this %u a DV box?\n",
11518 pm->pmt);
11519 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11520 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11521 {
11523 "Discard old box, because we have a new DV path.\n");
11524 free_pending_message (sc.best->bpm);
11525 sc.best->bpm = NULL;
11526 }
11527
11528 if (NULL == sc.best->bpm)
11529 {
11531 "encapsulate_for_dv 2\n");
11532 encapsulate_for_dv (sc.dvh->dv,
11533 1,
11534 &sc.dvh,
11535 (const struct GNUNET_MessageHeader *) &sc.best[1],
11537 &sc,
11538 RMO_NONE,
11539 GNUNET_NO);
11540 GNUNET_assert (NULL != sc.best->bpm);
11542 "%lu %lu %lu %lu %u\n",
11543 sizeof(struct GNUNET_PeerIdentity),
11544 sizeof(struct TransportDVBoxMessage),
11545 sizeof(struct TransportDVBoxPayloadP),
11546 sizeof(struct TransportFragmentBoxMessage),
11547 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11548 sc.best->bpm->used_dvh = sc.dvh;
11549 }
11550 pm = sc.best->bpm;
11551 }
11552 if (GNUNET_YES == sc.frag)
11553 {
11554 pm = fragment_message (queue, sc.dvh, pm);
11555 if (NULL == pm)
11556 {
11558 "Fragmentation failed queue %s to %s for <%" PRIu64
11559 ">, trying again\n",
11560 queue->address,
11561 GNUNET_i2s (&n->pid),
11562 sc.best->logging_uuid);
11564 queue,
11566 return;
11567 }
11568 }
11569 else if (GNUNET_YES == sc.relb)
11570 {
11572 if (NULL == pm)
11573 {
11574 /* Reliability boxing failed, try next message... */
11575 GNUNET_log (
11577 "Reliability boxing failed queue %s to %s for <%" PRIu64
11578 ">, trying again\n",
11579 queue->address,
11580 GNUNET_i2s (&n->pid),
11581 sc.best->logging_uuid);
11583 queue,
11585 return;
11586 }
11587 }
11588
11589 /* Pass 'pm' for transission to the communicator */
11590 GNUNET_log (
11592 "Passing message <%" PRIu64
11593 "> to queue %s for peer %s (considered %u others)\n",
11594 pm->logging_uuid,
11595 queue->address,
11596 GNUNET_i2s (&n->pid),
11597 sc.consideration_counter);
11598
11599 /* Flow control: increment amount of traffic sent; if we are routing
11600 via DV (and thus the ultimate target of the pending message is for
11601 a different virtual link than the one of the queue), then we need
11602 to use up not only the window of the direct link but also the
11603 flow control window for the DV link! */
11604 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11605
11606 if (pm->vl != queue->neighbour->vl)
11607 {
11608 /* If the virtual link of the queue differs, this better be distance
11609 vector routing! */
11610 GNUNET_assert (NULL != sc.dvh);
11611 /* If we do distance vector routing, we better not do this for a
11612 message that was itself DV-routed */
11613 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11614 /* We use the size of the unboxed message here, to avoid counting
11615 the DV-Box header which is eaten up on the way by intermediaries */
11616 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11617 }
11618 else
11619 {
11620 GNUNET_assert (NULL == sc.dvh);
11621 }
11622
11623 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11624
11625 /* Check if this transmission somehow conclusively finished handing 'pm'
11626 even without any explicit ACKs */
11627 if ((PMT_CORE == pm->pmt) ||
11628 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11629 {
11631 }
11632 else
11633 {
11634 struct GNUNET_TIME_Relative wait_duration;
11635 unsigned int wait_multiplier;
11636
11637 if (PMT_FRAGMENT_BOX == pm->pmt)
11638 {
11639 struct PendingMessage *root;
11640
11641 root = pm->frag_parent;
11642 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11643 root = root->frag_parent;
11644
11645 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11646 / ((double) root->frag_off
11647 / (double) root->frag_count))
11648 * 4;
11649 }
11650 else
11651 {
11652 // No fragments, we use 4 RTT before retransmitting.
11653 wait_multiplier = 4;
11654 }
11655
11656 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11657 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11658
11660 "Wait multiplier %u\n",
11661 wait_multiplier);
11662
11663 /* Message not finished, waiting for acknowledgement.
11664 Update time by which we might retransmit 's' based on queue
11665 characteristics (i.e. RTT); it takes one RTT for the message to
11666 arrive and the ACK to come back in the best case; but the other
11667 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11668 retransmitting.
11669
11670 OPTIMIZE: Note that in the future this heuristic should likely
11671 be improved further (measure RTT stability, consider message
11672 urgency and size when delaying ACKs, etc.) */
11673
11674 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11675 queue->pd.aged_rtt.rel_value_us)
11676 wait_duration = queue->pd.aged_rtt;
11677 else
11678 {
11679 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11680 wait_multiplier = 4;
11681 }
11682 {
11685 wait_duration, wait_multiplier));
11687 wait_duration, wait_multiplier);
11689 "Waiting %s for ACK until %s\n",
11694 GNUNET_TIME_relative_multiply (wait_duration,
11695 wait_multiplier))
11696 );
11697 }
11698 }
11699 /* finally, re-schedule queue transmission task itself */
11701 queue,
11703}
11704
11705
11712static void
11714 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11715{
11716 struct TransportClient *tc = cls;
11717
11718 if (CT_COMMUNICATOR != tc->type)
11719 {
11720 GNUNET_break (0);
11722 return;
11723 }
11724 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11725 queue = queue->next_client)
11726 {
11727 struct Neighbour *neighbour = queue->neighbour;
11728
11729 if ((ntohl (dqm->qid) != queue->qid) ||
11730 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11731 continue;
11733 "Dropped queue %s to peer %s\n",
11734 queue->address,
11735 GNUNET_i2s (&neighbour->pid));
11736 free_queue (queue);
11738 return;
11739 }
11740 GNUNET_break (0);
11742}
11743
11744
11745static void
11747 struct TransportClient *tc)
11748{
11749 struct PendingMessage *pm;
11750
11751 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11752 qe->queue->queue_tail,
11753 qe);
11754 qe->queue->queue_length--;
11755 tc->details.communicator.total_queue_length--;
11757 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11758 qe->queue->address,
11759 qe->queue->qid,
11760 GNUNET_i2s (&qe->queue->neighbour->pid),
11761 qe->queue->queue_length,
11762 tc->details.communicator.total_queue_length);
11763
11764 /* if applicable, resume transmissions that waited on ACK */
11766 tc->details.communicator.total_queue_length)
11767 {
11768 /* Communicator dropped below threshold, resume all queues
11769 incident with this client! */
11771 GST_stats,
11772 "# Transmission throttled due to communicator queue limit",
11773 -1,
11774 GNUNET_NO);
11775 for (struct Queue *queue = tc->details.communicator.queue_head;
11776 NULL != queue;
11777 queue = queue->next_client)
11778 {
11780 queue,
11782 }
11783 }
11784 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11785 {
11786 /* queue dropped below threshold; only resume this one queue */
11788 "# Transmission throttled due to queue queue limit",
11789 -1,
11790 GNUNET_NO);
11792 qe->queue,
11794 }
11795 else if (1 == qe->queue->q_capacity)
11796 {
11797 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11799 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11800 PRIu64 ".\n",
11801 qe->queue->qid,
11802 qe->queue->q_capacity);
11803 /* message queue has capacity; only resume this one queue */
11804 /* queue dropped below threshold; only resume this one queue */
11806 "# Transmission throttled due to message queue capacity",
11807 -1,
11808 GNUNET_NO);
11810 qe->queue,
11812 }
11813
11814 if (NULL != (pm = qe->pm))
11815 {
11816 struct VirtualLink *vl;
11817
11818 // GNUNET_assert (qe == pm->qe);
11819 pm->qe = NULL;
11820 /* If waiting for this communicator may have blocked transmission
11821 of pm on other queues for this neighbour, force schedule
11822 transmit on queue for queues of the neighbour */
11823 if (NULL == pm->frag_parent)
11824 {
11825 vl = pm->vl;
11826 if ((NULL != vl) &&
11827 (NULL != vl->pending_msg_head) &&
11828 (vl->pending_msg_head == pm))
11830 }
11831 }
11832 GNUNET_free (qe);
11833}
11834
11835
11842static void
11844 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11845{
11846 struct TransportClient *tc = cls;
11847 struct QueueEntry *qe;
11848
11849 if (CT_COMMUNICATOR != tc->type)
11850 {
11851 GNUNET_break (0);
11853 return;
11854 }
11855
11856 /* find our queue entry matching the ACK */
11857 qe = NULL;
11859 "Looking for queue for PID %s\n",
11860 GNUNET_i2s (&sma->receiver));
11861 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11862 queue = queue->next_client)
11863 {
11864 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11865 continue;
11867 "Found PID %s\n",
11868 GNUNET_i2s (&queue->neighbour->pid));
11869
11870
11871 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11872 qep = qep->next)
11873 {
11874 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11875 sma->qid))
11876 continue;
11878 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11879 PRIu64 " Ack QID %u\n",
11880 qep->mid,
11881 queue->qid,
11882 GNUNET_ntohll (sma->mid),
11883 ntohl (sma->qid));
11884 qe = qep;
11885 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11887 "For pending message %" PRIu64 " we had retransmissions.\n",
11888 qe->pm->logging_uuid);
11889 break;
11890 }
11891 }
11892 if (NULL == qe)
11893 {
11895 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11896 GNUNET_ntohll (sma->mid),
11897 ntohl (sma->qid));
11898 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11899 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11900 /* this should never happen */
11901 // GNUNET_break (0);
11902 // GNUNET_SERVICE_client_drop (tc->client);
11904 return;
11905 }
11908}
11909
11910
11916static void
11918 const struct GNUNET_TRANSPORT_BurstFinished *bf)
11919{
11921}
11922
11923
11933static int
11935 const struct GNUNET_PeerIdentity *pid,
11936 void *value)
11937{
11938 struct TransportClient *tc = cls;
11939 struct Neighbour *neighbour = value;
11940
11941 GNUNET_assert (CT_MONITOR == tc->type);
11942 for (struct Queue *q = neighbour->queue_head; NULL != q;
11943 q = q->next_neighbour)
11944 {
11945 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11946 .cs = q->cs,
11947 .num_msg_pending = q->num_msg_pending,
11948 .num_bytes_pending = q->num_bytes_pending };
11949
11950 notify_monitor (tc, pid, q->address, q->nt, &me);
11951 }
11952 return GNUNET_OK;
11953}
11954
11955
11962static void
11965{
11966 struct TransportClient *tc = cls;
11967
11968 if (CT_NONE != tc->type)
11969 {
11970 GNUNET_break (0);
11972 return;
11973 }
11974 tc->type = CT_MONITOR;
11975 tc->details.monitor.peer = start->peer;
11976 tc->details.monitor.one_shot = ntohl (start->one_shot);
11980}
11981
11982
11990static struct TransportClient *
11992{
11993 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11994 {
11995 if (CT_COMMUNICATOR != tc->type)
11996 continue;
11997 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11998 return tc;
11999 }
12000 GNUNET_log (
12002 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
12003 prefix);
12004 return NULL;
12005}
12006
12007
12015static void
12017{
12018 static uint32_t idgen = 0;
12019 struct TransportClient *tc;
12020 char *prefix;
12021 struct GNUNET_TRANSPORT_CreateQueue *cqm;
12022 struct GNUNET_MQ_Envelope *env;
12023 size_t alen;
12024
12026 if (NULL == prefix)
12027 {
12028 GNUNET_break (0); /* We got an invalid address!? */
12029 return;
12030 }
12032 if (NULL == tc)
12033 {
12035 "# Suggestions ignored due to missing communicator",
12036 1,
12037 GNUNET_NO);
12039 "Cannot connect to %s at `%s', no matching communicator present\n",
12040 GNUNET_i2s (pid),
12041 address);
12043 return;
12044 }
12045 /* forward suggestion for queue creation to communicator */
12047 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
12048 (unsigned int) idgen,
12049 prefix,
12050 GNUNET_i2s (pid),
12051 address);
12053 alen = strlen (address) + 1;
12054 env =
12056 cqm->request_id = htonl (idgen++);
12057 cqm->receiver = *pid;
12058 memcpy (&cqm[1], address, alen);
12059 GNUNET_MQ_send (tc->mq, env);
12060}
12061
12062
12070static void
12072{
12074 struct GNUNET_TIME_Absolute monotonic_time;
12075
12076 if (NULL != vs->revalidation_task)
12077 {
12078 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12079 vs->revalidation_task = NULL;
12080 }
12081 /*memcpy (&hkey,
12082 &hc,
12083 sizeof (hkey));*/
12085 "Remove key %s for address %s map size %u contains %u\n",
12086 GNUNET_h2s (&vs->hc),
12087 vs->address,
12090 &vs->hc));
12092
12094 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12095 vs->last_challenge_use.abs_value_us)
12096 {
12097 vs->first_challenge_use = monotonic_time;
12098 }
12099 vs->last_challenge_use = monotonic_time;
12100 tvc.header.type =
12102 tvc.header.size = htons (sizeof(tvc));
12103 tvc.reserved = htonl (0);
12104 tvc.challenge = vs->challenge;
12105 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12107 "Sending address validation challenge %s to %s\n",
12109 GNUNET_i2s (&q->neighbour->pid));
12110 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12111}
12112
12113
12119static void
12121{
12122 struct ValidationState *vs;
12123 struct Queue *q;
12125 GST_cfg);
12126
12127 (void) cls;
12128 validation_task = NULL;
12130 /* drop validations past their expiration */
12131 while (
12132 (NULL != vs) &&
12134 {
12136 "Validation response %s cleaned up\n",
12137 GNUNET_sh2s (&vs->challenge.value));
12140 }
12141 if (NULL == vs)
12142 {
12144 "Address validation task not scheduled anymore, nothing to do\n");
12145 return; /* woopsie, no more addresses known, should only
12146 happen if we're really a lonely peer */
12147 }
12148 q = find_queue (&vs->pid, vs->address);
12149 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
12150 {
12152 "To early to start next address validation for challenge %s\n",
12153 GNUNET_sh2s (&vs->challenge.value));
12154 return;
12155 }
12156 if (NULL == q)
12157 {
12158 vs->awaiting_queue = GNUNET_YES;
12159 suggest_to_connect (&vs->pid, vs->address);
12160 }
12161 else
12163 /* Finally, reschedule next attempt */
12164 vs->challenge_backoff =
12165 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12168 "Address validation task will run again in %s\n",
12169 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12170 GNUNET_YES));
12173 vs->challenge_backoff));
12174}
12175
12176
12181{
12185 struct Queue *q;
12186
12190 unsigned int quality_count;
12191
12195 unsigned int num_queues;
12196
12201 unsigned int k;
12202};
12203
12204
12216static int
12218 const struct GNUNET_PeerIdentity *pid,
12219 void *value)
12220{
12221 struct QueueQualityContext *ctx = cls;
12222 struct Neighbour *n = value;
12223 int do_inc;
12224
12225 (void) pid;
12226 do_inc = GNUNET_NO;
12227 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12228 {
12229 ctx->num_queues++;
12230 if (0 == ctx->k--)
12231 ctx->q = q;
12232 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12233 statistics and consider those as well here? */
12234 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12235 do_inc = GNUNET_YES;
12236 }
12237 if (GNUNET_YES == do_inc)
12238 ctx->quality_count++;
12239 return GNUNET_OK;
12240}
12241
12242
12254static void
12255start_dv_learn (void *cls);
12256
12257
12265
12266
12267static void
12269 const struct GNUNET_PeerIdentity *pid,
12270 const struct GNUNET_CRYPTO_EddsaSignature *sig)
12271{
12272 const struct GNUNET_PeerIdentity *my_identity;
12273 struct SignDvInitCls *sign_dv_init_cls = cls;
12274 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12275 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12276 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12277
12280
12281 sign_dv_init_cls->pr->op = NULL;
12284 sign_dv_init_cls->pr);
12285 GNUNET_free (sign_dv_init_cls->pr);
12286
12287 dvl.init_sig = *sig;
12288 dvl.initiator = *my_identity;
12289 dvl.challenge = lle->challenge;
12290
12291 qqc.quality_count = 0;
12293 qqc.num_queues = 0;
12294 qqc.q = NULL;
12297 &qqc);
12298 GNUNET_assert (NULL != qqc.q);
12299
12300 /* Do this as close to transmission time as possible! */
12302
12303 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12304 /* reschedule this job, randomizing the time it runs (but no
12305 actual backoff!) */
12306 if (NULL != dvlearn_task)
12311 NULL);
12312}
12313
12314
12326static void
12328{
12329 struct LearnLaunchEntry *lle;
12330 struct QueueQualityContext qqc;
12331 struct TransportDVLearnMessage dvl;
12332 const struct GNUNET_PeerIdentity *my_identity;
12333
12334 (void) cls;
12335 dvlearn_task = NULL;
12337 return; /* lost all connectivity, cannot do learning */
12338 qqc.quality_count = 0;
12339 qqc.num_queues = 0;
12343 &qqc);
12345 {
12346 struct GNUNET_TIME_Relative delay;
12347 unsigned int factor;
12348
12349 /* scale our retries by how far we are above the threshold */
12353 "At connection quality %u, will launch DV learn in %s\n",
12354 qqc.quality_count,
12357 return;
12358 }
12359 /* remove old entries in #dvlearn_map if it has grown too big */
12360 while (MAX_DV_LEARN_PENDING <=
12362 {
12363 lle = lle_tail;
12366 &lle->challenge.value,
12367 lle));
12369 GNUNET_free (lle);
12370 }
12371 /* setup data structure for learning */
12372 lle = GNUNET_new (struct LearnLaunchEntry);
12374 &lle->challenge,
12375 sizeof(lle->challenge));
12377 "Starting launch DV learn with challenge %s\n",
12378 GNUNET_sh2s (&lle->challenge.value));
12383 &lle->challenge.value,
12384 lle,
12389 dvl.header.size = htons (sizeof(dvl));
12390 dvl.num_hops = htons (0);
12391 dvl.bidirectional = htons (0);
12393 dvl.monotonic_time =
12395 // We will set the below again later
12396 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12397 dvl.challenge = lle->challenge;
12398 dvl.initiator = *my_identity;
12399 {
12400 struct DvInitPS dvip = {
12401 .purpose.purpose = htonl (
12403 .purpose.size = htonl (sizeof(dvip)),
12404 .monotonic_time = dvl.monotonic_time,
12405 .challenge = lle->challenge
12406 };
12407 struct SignDvInitCls *sign_dv_init_cls;
12408
12409 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12410 sign_dv_init_cls->dvl = dvl;
12411 sign_dv_init_cls->lle = lle;
12412 sign_dv_init_cls->qqc = qqc;
12413 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12416 sign_dv_init_cls->pr);
12417 sign_dv_init_cls->pr->op =
12419 &dvip.purpose,
12421 sign_dv_init_cls);
12422 }
12423}
12424
12425
12433static char *
12435{
12436 const char *colon;
12437 char *colon_rest;
12438 size_t colon_rest_length;
12439 char *address_without_port;
12440
12441 colon = strchr (address,':');
12442 colon_rest = GNUNET_strndup (address, colon - address);
12443 colon_rest_length = strlen (colon_rest);
12444 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12445 GNUNET_free (colon_rest);
12446
12447 return address_without_port;
12448}
12449
12450
12460static int
12462 const struct GNUNET_PeerIdentity *pid,
12463 void *value)
12464{
12465 struct Queue *q = cls;
12466 struct ValidationState *vs = value;
12467 char *address_without_port_vs;
12468 char *address_without_port_q;
12469 int success = GNUNET_YES;
12470
12471 // TODO Check if this is really necessary.
12472 address_without_port_vs = get_address_without_port (vs->address);
12473 address_without_port_q = get_address_without_port (q->address);
12474
12476 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12477 GNUNET_i2s (pid),
12478 address_without_port_vs,
12479 address_without_port_q);
12480 (void) pid;
12481 if ((GNUNET_YES == vs->awaiting_queue) &&
12482 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12483 {
12484
12485 vs->awaiting_queue = GNUNET_NO;
12487 success = GNUNET_NO;
12488 }
12489
12490 GNUNET_free (address_without_port_vs);
12491 GNUNET_free (address_without_port_q);
12492 return success;
12493}
12494
12495
12504static void
12506 const struct GNUNET_PEERSTORE_Record *record,
12507 const char *emsg)
12508{
12509 struct Neighbour *n = cls;
12510 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12511
12512 (void) emsg;
12513 if (NULL == record)
12514 {
12515 /* we're done with #neighbour_dv_monotime_cb() invocations,
12516 continue normal processing */
12517 n->get = NULL;
12519 return;
12520 }
12521 if (0 == record->value_size)
12522 {
12524 GNUNET_break (0);
12525 return;
12526 }
12527 mtbe = record->value;
12532}
12533
12534
12535static void
12537 const struct GNUNET_PeerIdentity *pid,
12538 const char *uri)
12539{
12540 struct Queue *queue = cls;
12541 struct sockaddr_in v4;
12542 const char *slash;
12543 char *address_uri;
12544 char *prefix;
12545 char *uri_without_port;
12546 char *address_uri_without_port;
12547
12548 slash = strrchr (uri, '/');
12549 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12550 GNUNET_assert (NULL != slash);
12551 slash++;
12552 GNUNET_asprintf (&address_uri,
12553 "%s-%s",
12554 prefix,
12555 slash);
12556
12558 "1 not global natted_address %u %s %s %s\n",
12559 queue->is_global_natted,
12560 uri,
12561 queue->address,
12562 slash);
12563
12564 uri_without_port = get_address_without_port (address_uri);
12565 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12566 {
12568 GNUNET_free (address_uri);
12569 GNUNET_free (uri_without_port);
12570 return;
12571 }
12572
12574 "2 not global natted_address %u %s %s\n",
12575 queue->is_global_natted,
12576 uri,
12577 queue->address);
12578
12579 if (GNUNET_NO == queue->is_global_natted)
12580 {
12582 GNUNET_free (address_uri);
12583 GNUNET_free (uri_without_port);
12584 return;
12585 }
12586
12588 "3 not global natted_address %u %s %s\n",
12589 queue->is_global_natted,
12590 uri,
12591 queue->address);
12592
12593 if (0 == strcmp (uri_without_port, address_uri))
12594 {
12596 GNUNET_free (address_uri);
12597 GNUNET_free (uri_without_port);
12598 return;
12599 }
12600
12602 "4 not global natted_address %u %s %s\n",
12603 queue->is_global_natted,
12604 uri,
12605 queue->address);
12606
12607 address_uri_without_port = get_address_without_port (queue->address);
12608 if (0 == strcmp (uri_without_port, address_uri_without_port))
12609 {
12610 queue->is_global_natted = GNUNET_NO;
12611 }
12612
12614 "not global natted_address %u %s %s %s %s %s %u\n",
12615 queue->is_global_natted,
12616 uri,
12617 queue->address,
12618 uri_without_port,
12619 address_uri_without_port,
12620 prefix,
12621 GNUNET_NO);
12623 GNUNET_free (address_uri);
12624 GNUNET_free (address_uri_without_port);
12625 GNUNET_free (uri_without_port);
12626}
12627
12628
12641
12642
12643static enum GNUNET_GenericReturnValue
12645 const struct GNUNET_PeerIdentity *pid,
12646 void *value)
12647{
12648 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12649 struct TransportGlobalNattedAddress *tgna = value;
12650 char *addr = (char *) &tgna[1];
12651
12653 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12654 tgna,
12655 addr,
12656 ntohl (tgna->address_length),
12657 strlen (tgna_cls->addr));
12658 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12659 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12660 {
12661 tgna_cls->tgna = tgna;
12662 return GNUNET_NO;
12663 }
12664 return GNUNET_YES;
12665}
12666
12667
12668static void
12670{
12672 "Error in PEERSTORE monitoring for checking global natted\n");
12673}
12674
12675
12676static void
12678{
12680 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12681}
12682
12683
12684static void
12686 const struct GNUNET_PEERSTORE_Record *record,
12687 const char *emsg)
12688{
12689 struct Queue *queue = cls;
12690 struct Neighbour *neighbour = queue->neighbour;
12691 struct GNUNET_HELLO_Parser *parser;
12692 struct GNUNET_MessageHeader *hello;
12694 size_t address_len_without_port;
12695
12696 if (NULL != emsg)
12697 {
12699 "Got failure from PEERSTORE: %s\n",
12700 emsg);
12701 return;
12702 }
12703 if (0 == record->value_size)
12704 {
12706 GNUNET_break (0);
12707 return;
12708 }
12709 queue->is_global_natted = GNUNET_YES;
12710 hello = record->value;
12711 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
12713 "before not global natted %u\n",
12714 queue->is_global_natted);
12717 queue);
12719 "after not global natted %u\n",
12720 queue->is_global_natted);
12721 GNUNET_HELLO_parser_free (parser);
12722
12723 tgna_cls.addr = get_address_without_port (queue->address);
12724 address_len_without_port = strlen (tgna_cls.addr);
12725 /*{
12726 char buf[address_len_without_port + 1];
12727
12728 GNUNET_memcpy (&buf, addr, address_len_without_port);
12729 buf[address_len_without_port] = '\0';
12730 GNUNET_free (addr);
12731 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12732 }*/
12733 tgna_cls.tgna = NULL;
12735 &neighbour->pid,
12737 &tgna_cls);
12738 if (NULL != tgna_cls.tgna)
12740 " tgna_cls.tgna tgna %p %lu %u %u\n",
12741 tgna_cls.tgna,
12742 neighbour->size_of_global_addresses,
12743 ntohl (tgna_cls.tgna->address_length),
12744 neighbour->number_of_addresses);
12745 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12746 {
12747 struct TransportGlobalNattedAddress *tgna;
12748
12749 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12750 + address_len_without_port);
12751 tgna->address_length = htonl (address_len_without_port);
12752 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12754 &neighbour->pid,
12755 tgna,
12757 neighbour->number_of_addresses++;
12758 neighbour->size_of_global_addresses += address_len_without_port + 1;
12760 "Created tgna %p with address %s and length %lu\n",
12761 tgna,
12762 tgna_cls.addr,
12763 address_len_without_port + 1);
12764 }
12765 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12766 {
12768 &neighbour->pid,
12769 tgna_cls.tgna);
12770 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12772 );
12773 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12774 ;
12775 GNUNET_assert (0 < neighbour->number_of_addresses);
12776 neighbour->number_of_addresses--;
12778 "removed tgna %p\n",
12779 tgna_cls.tgna);
12780 GNUNET_free (tgna_cls.tgna);
12781 }
12783 GNUNET_free (tgna_cls.addr);
12784}
12785
12786
12793static void
12795 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12796{
12797 struct TransportClient *tc = cls;
12798 struct Queue *queue;
12799 struct Neighbour *neighbour;
12800 const char *addr;
12801 uint16_t addr_len;
12802
12803 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12804 {
12805 /* MTU so small as to be useless for transmissions,
12806 required for #fragment_message()! */
12807 GNUNET_break_op (0);
12809 return;
12810 }
12811 /* This may simply be a queue update */
12812 for (queue = tc->details.communicator.queue_head;
12813 NULL != queue;
12814 queue = queue->next_client)
12815 {
12816 if (queue->qid != ntohl (aqm->qid))
12817 continue;
12818 break;
12819 }
12820
12821 if (NULL != queue)
12822 {
12823 neighbour = queue->neighbour;
12824 }
12825 else
12826 {
12827 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12828
12829 neighbour = lookup_neighbour (&aqm->receiver);
12830 if (NULL == neighbour)
12831 {
12832 neighbour = GNUNET_new (struct Neighbour);
12834 GNUNET_YES);
12835 neighbour->pid = aqm->receiver;
12838 neighbours,
12839 &neighbour->pid,
12840 neighbour,
12842 neighbour->get =
12844 "transport",
12845 &neighbour->pid,
12848 neighbour);
12849 }
12850 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12851 addr = (const char *) &aqm[1];
12853 "New queue %s to %s available with QID %u and q_len %" PRIu64
12854 " and mtu %u\n",
12855 addr,
12856 GNUNET_i2s (&aqm->receiver),
12857 ntohl (aqm->qid),
12858 GNUNET_ntohll (aqm->q_len),
12859 ntohl (aqm->mtu));
12860 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12861 queue->tc = tc;
12862 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12863 next_neighbour)
12864 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12865 validated_until);
12866 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12867 {
12869 "New queue with QID %u inherit validated until\n",
12870 ntohl (aqm->qid));
12871 queue->validated_until = validated_until;
12872 }
12873 queue->address = (const char *) &queue[1];
12874 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12875 queue->qid = ntohl (aqm->qid);
12876 queue->neighbour = neighbour;
12878 queue->unlimited_length = GNUNET_YES;
12879 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12880 memcpy (&queue[1], addr, addr_len);
12881 /* notify monitors about new queue */
12882 {
12883 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12884
12885 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12886 }
12888 neighbour->queue_head,
12889 neighbour->queue_tail,
12890 queue);
12892 tc->details.communicator.queue_head,
12893 tc->details.communicator.queue_tail,
12894 queue);
12895
12896 }
12897 queue->mtu = ntohl (aqm->mtu);
12898 queue->nt = ntohl (aqm->nt);
12899 queue->cs = ntohl (aqm->cs);
12900 queue->idle = GNUNET_YES;
12901
12902 {
12903 struct sockaddr_in v4;
12904 char *addr_without = get_address_without_port (queue->address);
12905 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12906 {
12908 "start not global natted\n");
12910 GNUNET_YES,
12911 "peerstore",
12912 &neighbour->pid,
12914 &
12916 NULL,
12917 &
12919 NULL,
12921 queue);
12922 }
12923 GNUNET_free (addr_without);
12924 }
12925 /* check if valdiations are waiting for the queue */
12927 &aqm->receiver))
12928 {
12931 &aqm->
12932 receiver,
12933 &
12935 queue))
12936 start_address_validation (&aqm->receiver, queue->address);
12937 }
12938 else
12939 start_address_validation (&aqm->receiver, queue->address);
12940 /* look for traffic for this queue */
12941 // TODO Check whether this makes any sense at all.
12942 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12943 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12944 /* might be our first queue, try launching DV learning */
12945 if (NULL == dvlearn_task)
12948}
12949
12950
12957static void
12959 const struct
12961{
12962 struct TransportClient *tc = cls;
12963 struct Queue *target_queue = NULL;
12964
12966 "Received queue update message for %u with q_len %llu and mtu %u\n",
12967 ntohl (msg->qid),
12968 (unsigned long long) GNUNET_ntohll (msg->q_len),
12969 ntohl (msg->mtu));
12970 for (target_queue = tc->details.communicator.queue_head;
12971 NULL != target_queue;
12972 target_queue = target_queue->next_client)
12973 {
12974 if (ntohl (msg->qid) == target_queue->qid)
12975 break;
12976 }
12977 if (NULL == target_queue)
12978 {
12980 "Queue to update no longer exists! Discarding update.\n");
12981 return;
12982 }
12983
12984 target_queue->nt = msg->nt;
12985 target_queue->mtu = ntohl (msg->mtu);
12986 target_queue->cs = msg->cs;
12987 target_queue->priority = ntohl (msg->priority);
12988 /* The update message indicates how many messages
12989 * the queue should be able to handle.
12990 */
12992 target_queue->unlimited_length = GNUNET_YES;
12993 else
12994 target_queue->unlimited_length = GNUNET_NO;
12995 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12996 if (0 < target_queue->q_capacity)
12998 target_queue,
13001}
13002
13003
13011static void
13013 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
13014{
13015 struct TransportClient *tc = cls;
13016
13017 if (CT_COMMUNICATOR != tc->type)
13018 {
13019 GNUNET_break (0);
13021 return;
13022 }
13024 "# Suggestions succeeded at communicator",
13025 1,
13026 GNUNET_NO);
13028 "Request #%u for communicator to create queue succeeded\n",
13029 (unsigned int) ntohs (cqr->request_id));
13031}
13032
13033
13042static void
13044 void *cls,
13045 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
13046{
13047 struct TransportClient *tc = cls;
13048
13049 if (CT_COMMUNICATOR != tc->type)
13050 {
13051 GNUNET_break (0);
13053 return;
13054 }
13056 "Request #%u for communicator to create queue failed\n",
13057 (unsigned int) ntohl (cqr->request_id));
13059 "# Suggestions failed in queue creation at communicator",
13060 1,
13061 GNUNET_NO);
13063}
13064
13065
13073static void
13075{
13076 struct TransportClient *tc = cls;
13077 struct PeerRequest *pr;
13078
13079 if (CT_APPLICATION != tc->type)
13080 {
13081 GNUNET_break (0);
13083 return;
13084 }
13085 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
13086 &msg->peer);
13087 if (NULL == pr)
13088 {
13089 GNUNET_break (0);
13091 return;
13092 }
13093 (void) stop_peer_request (tc, &pr->pid, pr);
13095}
13096
13097
13098static void
13100 const struct GNUNET_PeerIdentity *pid,
13101 const char *uri)
13102{
13103 struct Queue *q;
13104 int pfx_len;
13105 const char *eou;
13106 char *address;
13107 (void) cls;
13108
13109 eou = strstr (uri,
13110 "://");
13111 pfx_len = eou - uri;
13112 eou += 3;
13114 "%.*s-%s",
13115 pfx_len,
13116 uri,
13117 eou);
13118
13120 "hello for client %s\n",
13121 address);
13122
13123 q = find_queue (pid, address);
13124 if (NULL == q)
13125 {
13127 }
13128 else
13131}
13132
13133
13141static void
13143 const struct GNUNET_PEERSTORE_Record *record,
13144 const char *emsg)
13145{
13146 const struct GNUNET_PeerIdentity *my_identity;
13147 struct PeerRequest *pr = cls;
13148 struct GNUNET_HELLO_Parser *parser;
13149 struct GNUNET_MessageHeader *hello;
13150
13151 if (NULL != emsg)
13152 {
13154 "Got failure from PEERSTORE: %s\n",
13155 emsg);
13156 return;
13157 }
13159 if (NULL == my_identity)
13160 {
13162 "No identity given yet!\n");
13163 return;
13164 }
13165 hello = record->value;
13166 if (0 == GNUNET_memcmp (&record->peer, my_identity))
13167 {
13169 return;
13170 }
13171 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
13172 if (NULL == parser)
13173 {
13175 "HELLO cannot be parsed!\n");
13176 return;
13177 }
13179 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13183 NULL);
13184 GNUNET_HELLO_parser_free (parser);
13185}
13186
13187
13188static void
13190{
13192 "Error in PEERSTORE monitoring\n");
13193}
13194
13195
13196static void
13198{
13200 "Done with initial PEERSTORE iteration during monitoring\n");
13201}
13202
13203
13211static void
13213{
13214 struct TransportClient *tc = cls;
13215 const struct GNUNET_PeerIdentity *my_identity;
13216 struct PeerRequest *pr;
13217
13218 if (CT_NONE == tc->type)
13219 {
13220 tc->type = CT_APPLICATION;
13221 tc->details.application.requests =
13223 }
13224 if (CT_APPLICATION != tc->type)
13225 {
13226 GNUNET_break (0);
13228 return;
13229 }
13231 if (NULL == my_identity)
13232 {
13234 "Still waiting for own identity!\n");
13236 return;
13237 }
13239 "Client suggested we talk to %s with preference %d at rate %u\n",
13240 GNUNET_i2s (&msg->peer),
13241 (int) ntohl (msg->pk),
13242 (int) ntohl (msg->bw.value__));
13243 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
13244 {
13246 "Client suggested connection to ourselves, ignoring...\n");
13248 return;
13249 }
13250 pr = GNUNET_new (struct PeerRequest);
13251 pr->tc = tc;
13252 pr->pid = msg->peer;
13253 pr->bw = msg->bw;
13254 pr->pk = ntohl (msg->pk);
13256 tc->details.application.requests,
13257 &pr->pid,
13258 pr,
13260 {
13261 GNUNET_break (0);
13262 GNUNET_free (pr);
13264 return;
13265 }
13266 pr->nc =
13268 GNUNET_YES,
13269 "peerstore",
13270 NULL,
13273 NULL,
13275 NULL,
13277 pr);
13279}
13280
13281
13290static int
13292 const struct RequestHelloValidationMessage *m)
13293{
13294 (void) cls;
13296 return GNUNET_OK;
13297}
13298
13299
13307static void
13309 const struct RequestHelloValidationMessage *m)
13310{
13311 struct TransportClient *tc = cls;
13312 struct Queue *q;
13313
13314 q = find_queue (&m->peer, (const char *) &m[1]);
13315 if (NULL == q)
13316 {
13317 suggest_to_connect (&m->peer, (const char *) &m[1]);
13318 }
13319 else
13320 start_address_validation (&m->peer, (const char *) &m[1]);
13322}
13323
13324
13333static int
13335 const struct GNUNET_PeerIdentity *pid,
13336 void *value)
13337{
13338 struct Neighbour *neighbour = value;
13339
13340 (void) cls;
13341 (void) pid;
13342 GNUNET_break (0); // should this ever happen?
13343 free_neighbour (neighbour, GNUNET_YES);
13344
13345 return GNUNET_OK;
13346}
13347
13348
13357static int
13359 const struct GNUNET_PeerIdentity *pid,
13360 void *value)
13361{
13362 struct DistanceVector *dv = value;
13363
13364 (void) cls;
13365 (void) pid;
13366 free_dv_route (dv);
13367
13368 return GNUNET_OK;
13369}
13370
13371
13380static int
13382 const struct GNUNET_PeerIdentity *pid,
13383 void *value)
13384{
13385 struct ValidationState *vs = value;
13386
13387 (void) cls;
13388 (void) pid;
13390 return GNUNET_OK;
13391}
13392
13393
13402static int
13403free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
13404{
13405 struct PendingAcknowledgement *pa = value;
13406
13407 (void) cls;
13408 (void) key;
13410 return GNUNET_OK;
13411}
13412
13413
13422static int
13424 const struct GNUNET_PeerIdentity *pid,
13425 void *value)
13426{
13427 struct AcknowledgementCummulator *ac = value;
13428
13429 (void) cls;
13430 (void) pid;
13432 GNUNET_free (ac);
13433 return GNUNET_OK;
13434}
13435
13436
13443static void
13444do_shutdown (void *cls)
13445{
13446 struct LearnLaunchEntry *lle;
13447 struct PilsRequest *pr;
13448 (void) cls;
13449
13451 "shutdown logic\n");
13454 &free_neighbour_cb, NULL);
13455 if (NULL != validation_task)
13456 {
13458 validation_task = NULL;
13459 }
13460 if (NULL != dvlearn_task)
13461 {
13463 dvlearn_task = NULL;
13464 }
13465 if (NULL != burst_task)
13466 {
13468 burst_task = NULL;
13469 }
13470 if (NULL != burst_timeout_task)
13471 {
13473 burst_timeout_task = NULL;
13474 }
13477 dvlearn_map = NULL;
13480 dv_routes = NULL;
13481 if (NULL != GST_stats)
13482 {
13484 GST_stats = NULL;
13485 }
13486 if (NULL != GST_my_hello)
13487 {
13489 GST_my_hello = NULL;
13490 }
13493 NULL);
13495 ack_cummulators = NULL;
13498 NULL);
13500 pending_acks = NULL;
13503 neighbours = NULL;
13506 links = NULL;
13509 NULL);
13511 backtalkers = NULL;
13514 NULL);
13516 validation_map = NULL;
13518 validation_heap = NULL;
13520 revalidation_map = NULL;
13521 while (NULL != ir_head)
13523 GNUNET_assert (0 == ir_total);
13524 while (NULL != (lle = lle_head))
13525 {
13527 GNUNET_free (lle);
13528 }
13529 while (NULL != (pr = pils_requests_head))
13530 {
13533 pr);
13534 if (NULL != pr->op)
13535 GNUNET_PILS_cancel (pr->op);
13536 GNUNET_free (pr);
13537 }
13538 if (NULL != pils_feed_task)
13539 {
13541 pils_feed_task = NULL;
13542 }
13543 if (NULL != pils)
13544 {
13546 pils = NULL;
13547 }
13548 if (NULL != peerstore)
13549 {
13551 "Disconnecting from PEERSTORE service\n");
13553 peerstore = NULL;
13554 }
13556}
13557
13558
13559static const char*
13561{
13562 switch (type)
13563 {
13564 case CT_CORE:
13565 return "CORE";
13566 case CT_MONITOR:
13567 return "MONITOR";
13568 case CT_COMMUNICATOR:
13569 return "COMMUNICATOR";
13570 case CT_APPLICATION:
13571 return "APPLICATION";
13572 default:
13573 return "UNKNOWN";
13574 }
13575}
13576
13577
13578static void
13579shutdown_task (void *cls)
13580{
13582
13584 "Shutdown task executed\n");
13585 if (NULL != clients_head)
13586 {
13587 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13588 {
13590 "Client still connected: %s\n",
13591 get_client_type_name (tc->type));
13592 }
13593 }
13594 else
13595 do_shutdown (cls);
13596
13597}
13598
13599
13604
13605static void
13606update_hello_from_pid_change_cb (void *cls, int success)
13607{
13608 struct UpdateHelloFromPidCtx *pc = cls;
13609
13610 if (GNUNET_OK != success)
13611 {
13613 "Failed to store our new hello with peerstore\n");
13614 }
13615 GNUNET_free (pc);
13617 "Stored our new hello with peerstore\n");
13618}
13619
13620
13621void
13623 const struct GNUNET_PeerIdentity *pid,
13624 const char *uri)
13625{
13627 "%s\n", uri);
13628}
13629
13630
13640static void
13642 const struct GNUNET_HELLO_Parser *parser,
13643 const struct GNUNET_HashCode *hash)
13644{
13645 const struct GNUNET_PeerIdentity *my_identity;
13646 struct GNUNET_MQ_Envelope *env;
13647 const struct GNUNET_MessageHeader *msg;
13648 struct UpdateHelloFromPidCtx *sc;
13649 struct GNUNET_HELLO_Builder *nbuilder;
13650 struct GNUNET_PeerIdentity npid;
13651
13654
13655 if (NULL == GST_my_hello)
13658 "My current identity is `%s'\n",
13670 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13671 &npid);
13672 if (GNUNET_NO ==
13674 {
13676 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
13678 "Proposed address list:\n");
13681 "Current address list:\n");
13683 GNUNET_HELLO_builder_free (nbuilder);
13684 return;
13685 }
13687 GST_my_hello = nbuilder;
13689 "My new identity is `%s'\n",
13695 msg,
13697 sc);
13698 GNUNET_free (env);
13699}
13700
13701
13709static void
13710run (void *cls,
13711 const struct GNUNET_CONFIGURATION_Handle *c,
13713{
13714 (void) cls;
13715 (void) service;
13716 /* setup globals */
13719 GST_cfg = c;
13727 GNUNET_YES);
13732 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13734 "transport",
13735 "USE_BURST_NAT");
13736 if (GNUNET_SYSERR == use_burst)
13738 "Could not configure burst nat use. Default to no.\n");
13744 "transport",
13745 0,
13746 0,
13747 NULL,
13748 0,
13749 NULL,
13750 NULL,
13751 NULL);
13752 if (NULL == peerstore)
13753 {
13754 GNUNET_break (0);
13756 return;
13757 }
13760 NULL); // FIXME we need to wait for
13761 // our first peer id before
13762 // we can start the service
13763 // completely - PILS in turn
13764 // waits for the first
13765 // addresses from the
13766 // communicators in order to
13767 // be able to generate a
13768 // peer id
13769 if (NULL == pils)
13770 {
13771 GNUNET_break (0);
13773 return;
13774 }
13775}
13776
13777
13783 "transport",
13785 &run,
13788 NULL,
13789 /* communication with applications */
13790 GNUNET_MQ_hd_fixed_size (suggest,
13793 NULL),
13794 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13797 NULL),
13798 GNUNET_MQ_hd_var_size (request_hello_validation,
13801 NULL),
13802 /* communication with core */
13803 GNUNET_MQ_hd_fixed_size (client_start,
13805 struct StartMessage,
13806 NULL),
13807 GNUNET_MQ_hd_var_size (client_send,
13809 struct OutboundMessage,
13810 NULL),
13811 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13813 struct RecvOkMessage,
13814 NULL),
13815 /* communication with communicators */
13816 GNUNET_MQ_hd_var_size (communicator_available,
13819 NULL),
13820 GNUNET_MQ_hd_var_size (communicator_backchannel,
13823 NULL),
13824 GNUNET_MQ_hd_var_size (add_address,
13827 NULL),
13828 GNUNET_MQ_hd_fixed_size (del_address,
13831 NULL),
13832 GNUNET_MQ_hd_var_size (incoming_msg,
13835 NULL),
13836 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13839 NULL),
13840 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13843 NULL),
13844 GNUNET_MQ_hd_var_size (add_queue_message,
13847 NULL),
13848 GNUNET_MQ_hd_fixed_size (update_queue_message,
13851 NULL),
13852 GNUNET_MQ_hd_fixed_size (del_queue_message,
13855 NULL),
13856 GNUNET_MQ_hd_fixed_size (send_message_ack,
13859 NULL),
13860 GNUNET_MQ_hd_fixed_size (burst_finished,
13863 NULL),
13864 /* communication with monitors */
13865 GNUNET_MQ_hd_fixed_size (monitor_start,
13868 NULL),
13870
13871
13872/* end of file gnunet-service-transport.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition gnunet-arm.c:103
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static char * init
Set to the name of a service to start.
Definition gnunet-arm.c:73
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
static struct GNUNET_TESTING_Interpreter * is
static struct Queue * queue_head
Head of queue of messages to transmit.
static int prefix
If printing the value of PREFIX has been requested.
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct GNUNET_FS_Handle * ctx
static OpusEncoder * enc
OPUS encoder.
struct GNUNET_SCHEDULER_Task * shutdown_task
static void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
static int result
Global testing status.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static struct GNUNET_FS_SearchContext * sc
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static unsigned long long payload
How much data are we currently storing in the database?
static unsigned int ring_buffer_dv_head
Head of the ring buffer.
static void peerstore_store_validation_cb(void *cls, int success)
Function called when peerstore is done storing a validated address.
static void handle_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
#define DV_PATH_DISCOVERY_FREQUENCY
How long before paths expire would we like to (re)discover DV paths? Should be below DV_PATH_VALIDITY...
static struct PendingMessage * ring_buffer_dv[RING_BUFFER_SIZE]
Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virt...
static enum GNUNET_GenericReturnValue dv_decrypt(struct DVKeyState *key, void *out, const void *ciph, size_t out_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
static int dv_neighbour_transmission(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void reassembly_cleanup_task(void *cls)
Task run to clean up reassembly context of a neighbour that have expired.
static void pils_sign_addr_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static enum GNUNET_GenericReturnValue remove_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void backtalker_timeout_cb(void *cls)
Function called when it is time to clean up a backtalker.
static void handle_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static unsigned int calculate_fork_degree(unsigned int hops_taken, unsigned int neighbour_count, unsigned int eligible_count)
Computes the number of neighbours we should forward a DVInit message to given that it has so far take...
static void dv_key_clean(struct DVKeyState *key)
Clean up key material in key.
static struct GNUNET_SCHEDULER_Task * dvlearn_task
Task run to initiate DV learning.
static int check_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void handle_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static int check_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment box.
static unsigned int get_age()
Get an offset into the transmission history buffer for struct PerformanceData.
static void free_validation_state(struct ValidationState *vs)
Free validation state.
static struct PendingAcknowledgement * prepare_pending_acknowledgement(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Setup data structure waiting for acknowledgements.
static int check_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
static void hello_for_incoming_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
#define MAX_DV_DISCOVERY_SELECTION
Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiato...
#define QUEUE_ENTRY_TIMEOUT
static struct LearnLaunchEntry * lle_tail
Tail of a DLL sorted by launch time.
static struct GNUNET_CONTAINER_Heap * validation_heap
MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware ...
static void core_send_connect_info(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void send_dv_to_neighbour(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
static void harmonize_flight_round(struct PendingMessage *pm)
#define ACK_CUMMULATOR_TIMEOUT
How long until we forget about historic accumulators and thus reset the ACK counter?...
void pils_sign_address(struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
Build address record by signing raw information with private key of the peer identity.
static void free_queue(struct Queue *queue)
Free queue.
static void handle_del_address(void *cls, const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
Address of our peer deleted.
static struct LearnLaunchEntry * lle_head
Head of a DLL sorted by launch time.
#define EPHEMERAL_VALIDITY
How long are ephemeral keys valid?
static void free_fragment_tree(struct PendingMessage *root)
Free fragment tree below root, excluding root itself.
static unsigned int is_ring_buffer_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static struct IncomingRequest * ir_tail
Tail of DLL starting at ir_head.
static void pils_pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
Callback called when pils service updates us with our new peer identity.
static int free_pending_ack_cb(void *cls, const struct GNUNET_Uuid *key, void *value)
Free pending acknowledgement.
static int check_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
static void completed_pending_message(struct PendingMessage *pm)
We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment...
static void update_dvh_performance(struct DistanceVectorHop *dvh, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via dvh, update metrics.
struct GNUNET_NAT_Handle * nh
Handle for connect to the NAT service.
static int check_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static struct GNUNET_SCHEDULER_Task * pils_feed_task
Task to feed addresses to PILS.
static void client_send_response(struct PendingMessage *pm)
Send a response to the pm that we have processed a "send" request.
static void start_dv_learn(void *cls)
Task run when we CONSIDER initiating a DV learn process.
static int dv_neighbour_selection(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void start_address_validation(const struct GNUNET_PeerIdentity *pid, const char *address)
Start address validation.
static void handle_del_queue_message(void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
Queue to a peer went down.
#define QUEUE_LENGTH_LIMIT
How many messages can we have pending for a given queue (queue to a particular peer via a communicato...
static void update_backtalker_monotime(struct Backtalker *b)
The backtalker b monotonic time changed.
#define MAX_CUMMULATIVE_ACKS
Maximum number of messages we acknowledge together in one cumulative ACK.
#define MAX_DV_HOPS_ALLOWED
Maximum DV distance allowed ever.
static const char * get_client_type_name(enum ClientType type)
static void burst_timeout(void *cls)
#define BACKCHANNEL_INACTIVITY_TIMEOUT
How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
static struct GNUNET_TIME_Relative get_network_latency(const struct TransportDVLearnMessage *dvl)
static void hello_for_client_error_cb(void *cls)
static void check_for_global_natted(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
#define ADDRESS_VALIDATION_LIFETIME
How long do we consider an address valid if we just checked?
static void free_distance_vector_hop(struct DistanceVectorHop *dvh)
Free a dvh.
#define MAX_FC_RETRANSMIT_COUNT
Maximum number of FC retransmissions for a running retransmission task.
static void sign_ephemeral(struct DistanceVector *dv)
Sign ephemeral keys in our dv are current.
static void handle_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment.
static struct PendingMessage * fragment_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Fragment the given pm to the given mtu.
static void update_hello_from_pid_change_cb(void *cls, int success)
static struct GNUNET_SCHEDULER_Task * validation_task
Task to run address validation.
static void handle_suggest(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void cores_send_connect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we gained a connection.
static void cummulative_ack(const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
static void task_consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define DV_LEARN_QUALITY_THRESHOLD
How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiati...
static void free_neighbour(struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
Release memory used by neighbour.
PendingMessageType
Types of different pending messages.
@ PMT_FRAGMENT_BOX
Fragment box.
@ PMT_DV_BOX
Pending message created during forward_dv_box().
@ PMT_CORE
Ordinary message received from the CORE service.
@ PMT_RELIABILITY_BOX
Reliability box.
static struct GNUNET_TIME_Relative calculate_rtt(struct DistanceVector *dv)
static int check_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int stop_peer_request(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Stop the peer request in value.
static void handle_update_queue_message(void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
Handle updates to queues.
static void cores_send_disconnect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void handle_client_start(void *cls, const struct StartMessage *start)
Initialize a "CORE" client.
#define MAX_DV_PATHS_TO_TARGET
Maximum number of DV paths we keep simultaneously to the same target.
static void free_virtual_link(struct VirtualLink *vl)
Free virtual link.
RouteMessageOptions
Which transmission options are allowable for transmission? Interpreted bit-wise!
@ RMO_UNCONFIRMED_ALLOWED
We are allowed to use unconfirmed queues or DV routes for this message.
@ RMO_DV_ALLOWED
We are allowed to use DV routing for this hdr.
@ RMO_REDUNDANT
If we have multiple choices, it is OK to send this message over multiple channels at the same time to...
@ RMO_NONE
Only confirmed, non-DV direct neighbours.
@ RMO_ANYTHING_GOES
Reliable and unreliable, DV and non-DV are all acceptable.
static int notify_client_queues(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new MONITOR client about all existing queues to peers.
static struct AddressListEntry * create_address_entry(struct TransportClient *tc, struct GNUNET_TIME_Relative expiration, enum GNUNET_NetworkType nt, const char *address, uint32_t aid, size_t slen)
static void extract_box_cb(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void backtalker_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a backtalker by PEERSTORE.
static void queue_burst(void *cls)
static void handle_monitor_start(void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
Initialize a monitor client.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static void finish_cmc_handling(struct CommunicatorMessageContext *cmc)
static int learn_dv_path(const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
We have learned a path through the network to some other peer, add it to our DV data structure (retur...
static void store_pi(void *cls)
Ask peerstore to store our address.
#define FC_NO_CHANGE_REPLY_PROBABILITY
What is the 1:n chance that we send a Flow control response when receiving a flow control message tha...
static void notify_monitors(const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Send information in me about a peer's status with respect to some address to all monitors that care.
static struct GNUNET_TIME_Relative route_via_neighbour(const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Pick a queue of n under constraints options and schedule transmission of hdr.
#define RECV_WINDOW_SIZE
Window size.
static int check_known_challenge(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the challenge from cls.
static unsigned int check_for_queue_with_higher_prio(struct Queue *queue, struct Queue *queue_head)
Check if the communicator has another queue with higher prio ready for sending.
#define GOODPUT_AGING_SLOTS
Number of slots we keep of historic data for computation of goodput / message loss ratio.
static int free_validation_state_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free validation state.
static int free_neighbour_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free neighbour entry.
static void handle_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static void sign_dv_init_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static enum GNUNET_GenericReturnValue burst_running
Is there a burst running?
struct GNUNET_HELLO_Builder * GST_my_hello
Our HELLO.
static void start_burst(void *cls)
#define DV_QUALITY_RTT_THRESHOLD
We only consider queues as "quality" connections when suppressing the generation of DV initiation mes...
static struct TransportClient * clients_head
Head of linked list of all clients to this service.
static void handle_validation_challenge(void *cls, const struct TransportValidationChallengeMessage *tvc)
Communicator gave us a transport address validation challenge.
static void dv_hmac(const struct DVKeyState *key, struct GNUNET_HashCode *hmac, const void *data, size_t data_size)
Do HMAC calculation for backchannel messages over data using key material from key.
static struct PilsRequest * pils_requests_head
PILS Operation DLL.
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT
How many messages can we have pending for a given communicator process before we start to throttle th...
static void free_reassembly_context(struct ReassemblyContext *rc)
Free rc.
static struct VirtualLink * lookup_virtual_link(const struct GNUNET_PeerIdentity *pid)
Lookup virtual link for peer pid.
static int check_connection_quality(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counte...
static void reorder_root_pm(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
static void core_env_sent_cb(void *cls)
Function called when we are done giving a message of a certain size to CORE and should thus decrement...
static unsigned int ir_total
Length of the DLL starting at ir_head.
static int in_shutdown
Indication if we have received a shutdown signal and are in the process of cleaning up.
static void select_best_pending_from_link(struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
Select the best pending message from vl for transmission via queue.
static void suggest_to_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Signature of a function called with a communicator address of a peer pid that an application wants us...
static void free_timedout_queue_entry(void *cls)
static void sign_t_validation_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void handle_send_message_ack(void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
Message was transmitted.
static void update_pd_age(struct PerformanceData *pd, unsigned int age)
Check if we have advanced to another age since the last time.
#define DV_LEARN_BASE_FREQUENCY
What is the non-randomized base frequency at which we would initiate DV learn messages?
struct GNUNET_SCHEDULER_Task * burst_timeout_task
static void free_pending_acknowledgement(struct PendingAcknowledgement *pa)
Release pa data structure.
static struct GNUNET_CONTAINER_MultiUuidmap * pending_acks
Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgemen...
static struct GNUNET_CONTAINER_MultiShortmap * dvlearn_map
Map from challenges to struct LearnLaunchEntry values.
#define DV_FORWARD_TIMEOUT
If a DVBox could not be forwarded after this number of seconds we drop it.
static void finish_handling_raw_message(struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
static void handle_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static void update_queue_performance(struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via q, update metrics.
static void schedule_transmit_on_queue(struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
Called whenever something changed that might effect when we try to do the next transmission on queue ...
static void set_pending_message_uuid(struct PendingMessage *pm)
If necessary, generates the UUID for a pm.
static void free_pending_message(struct PendingMessage *pm)
Release memory associated with pm and remove pm from associated data structures.
static void revalidation_start_cb(void *cls)
static void backtalker_monotime_store_cb(void *cls, int success)
Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
static int free_reassembly_cb(void *cls, uint32_t key, void *value)
function called to free_reassembly_context().
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Called whenever a client connects.
#define DV_PATH_VALIDITY_TIMEOUT
How long do we consider a DV path valid if we see no further updates on it? Note: the value chosen he...
#define RING_BUFFER_SIZE
Size of ring buffer to cache CORE and forwarded DVBox messages.
static void check_vl_transmission(struct VirtualLink *vl)
There is a message at the head of the pending messages for vl which may be ready for transmission.
static int find_by_message_uuid(void *cls, uint32_t key, void *value)
Iterator called to find a reassembly context by the message UUID in the multihashmap32.
static struct TransportClient * lookup_communicator(const char *prefix)
Find transport client providing communication service for the protocol prefix.
static unsigned int ring_buffer_head
Head of the ring buffer.
#define MAX_ADDRESS_VALID_UNTIL
When do we forget an invalid address for sure?
static void handle_hello_for_client(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void sign_dhp_cp(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void handle_suggest_cancel(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void update_performance_data(struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully tran...
static void forward_dv_box(struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
Create a DV Box message and queue it for transmission to next_hop.
static void handle_validation_response(void *cls, const struct TransportValidationResponseMessage *tvr)
Communicator gave us a transport address validation response.
static void handle_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void send_msg_from_cache(struct VirtualLink *vl)
static void free_address_list_entry(struct AddressListEntry *ale)
Free ale.
static unsigned int pick_random_dv_hops(const struct DistanceVector *dv, enum RouteMessageOptions options, struct DistanceVectorHop **hops_array, unsigned int hops_array_length)
Pick hops_array_length random DV paths satisfying options.
static void handle_burst_finished(void *cls, const struct GNUNET_TRANSPORT_BurstFinished *bf)
The burst finished.
static void hello_for_incoming_sync_cb(void *cls)
static enum GNUNET_GenericReturnValue resume_communicators(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static struct PilsRequest * pils_requests_tail
PILS Operation DLL.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Map from PIDs to struct Neighbour entries.
static void transmit_on_queue(void *cls)
We believe we are ready to transmit a message on a queue.
static void handle_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void iterate_address_start_burst(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct Queue * find_queue(const struct GNUNET_PeerIdentity *pid, const char *address)
Find the queue matching pid and address.
static void activate_core_visible_dv_path(struct DistanceVectorHop *hop)
The hop is a validated path to the respective target peer and we should tell core about it – and sche...
static void free_dv_route(struct DistanceVector *dv)
Free entry in dv_routes.
static unsigned int is_ring_buffer_dv_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static int check_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
#define DEFAULT_WINDOW_SIZE
How big is the flow control window size by default; limits per-neighbour RAM utilization.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate transport service.
#define MAX_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges?
static void handle_queue_create_ok(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue "worked", that is setting up the queue is no...
static int notify_client_connect_info(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new CORE client about all existing connections to peers.
static void shc_cont(void *cls, int success)
static void handle_raw_message(void *cls, const struct GNUNET_MessageHeader *mh)
Communicator gave us an unencapsulated message to pass as-is to CORE.
static void handle_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
static unsigned long long logging_uuid_gen
Generator of logging_uuid in struct PendingMessage.
static int check_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Client notified us about transmission from a peer.
#define REASSEMBLY_EXPIRATION
How long do we keep partially reassembled messages around before giving up?
static void update_next_challenge_time(struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
Set the time for next_challenge of vs to new_time.
static struct Neighbour * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup neighbour for peer pid.
static void peerstore_store_own_cb(void *cls, int success)
Function called when peerstore is done storing our address.
static struct RingBufferEntry * ring_buffer[RING_BUFFER_SIZE]
Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
#define MIN_DELAY_ADDRESS_VALIDATION
What is the maximum frequency at which we do address validation? A random value between 0 and this va...
static void handle_acknowledged(struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
The pa was acknowledged, process the acknowledgement.
static struct GNUNET_CONTAINER_MultiPeerMap * backtalkers
Map from PIDs to struct Backtalker entries.
static struct GNUNET_TIME_Absolute hello_mono_time
Monotonic time we use for HELLOs generated at this time.
static int check_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static void handle_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct GNUNET_CONTAINER_MultiHashMap * revalidation_map
Map from addresses to struct ValidationState entries describing addresses we are aware of and their v...
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
static enum GNUNET_GenericReturnValue revalidate_map_it(void *cls, const struct GNUNET_HashCode *key, void *value)
#define DEFAULT_ACK_WAIT_DURATION
Default value for how long we wait for reliability ack.
static struct PendingMessage * reliability_box_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Reliability-box the given pm.
static int free_backtalker_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Callback to free backtalker records.
static enum GNUNET_GenericReturnValue contains_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void path_cleanup_cb(void *cls)
Task called when we should check if any of the DV paths we have learned to a target are due for garba...
#define FAST_VALIDATION_CHALLENGE_FREQ
What is the fastest rate at which we send challenges if we keep learning an address (gossip,...
static int check_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void demultiplex_with_cmc(struct CommunicatorMessageContext *cmc)
Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the ri...
#define MAX_DV_LEARN_PENDING
Maximum number of DV learning activities we may have pending at the same time.
static void hello_for_client_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void validation_start_cb(void *cls)
Task run periodically to validate some address based on validation_heap.
#define VALIDATION_RTT_BUFFER_FACTOR
How many network RTTs before an address validation expires should we begin trying to revalidate?...
static void handle_client_recv_ok(void *cls, const struct RecvOkMessage *rom)
Client confirms that it is done handling message(s) to a particular peer.
static void feed_addresses_to_pils(void *cls)
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
static int check_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static int check_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct TransportClient * clients_tail
Tail of linked list of all clients to this service.
static struct GNUNET_CONTAINER_MultiPeerMap * ack_cummulators
Map from PIDs to struct AcknowledgementCummulators.
static void transmit_cummulative_ack_cb(void *cls)
Do the transmission of a cumulative acknowledgement now.
static int check_validation_request_pending(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
A new queue has been created, check if any address validation requests have been waiting for it.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static struct GNUNET_SCHEDULER_Task * burst_task
The task to start the burst.
void print_address_list(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_TIME_Relative encapsulate_for_dv(struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
Pick a path of dv under constraints options and schedule transmission of hdr.
static void neighbour_store_dvmono_cb(void *cls, int success)
Function called when peerstore is done storing a DV monotonic time.
static void handle_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
A client encountered an address of another peer.
static void free_queue_entry(struct QueueEntry *qe, struct TransportClient *tc)
static void pils_sign_hello_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Get HELLO signature and create message to store in PEERSTORE.
static void check_for_global_natted_sync_cb(void *cls)
static void handle_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void notify_monitor(struct TransportClient *tc, const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Notify monitor tc about an event.
static void check_for_burst_address(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
static unsigned int check_next_attempt_tree(struct PendingMessage *pm, struct PendingMessage *root)
static void hello_for_incoming_error_cb(void *cls)
static void queue_send_msg(struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
Send the message payload on queue.
static void dv_setup_key_state_from_km(const struct GNUNET_ShortHashCode *km, const struct GNUNET_ShortHashCode *iv, struct DVKeyState *key)
Given the key material in km and the initialization vector iv, setup the key material for the backcha...
static void handle_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void handle_hello_for_incoming(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static int check_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void sign_dv_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void dv_encrypt(struct DVKeyState *key, const void *in, void *dst, size_t in_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
static void iterate_address_and_compare_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validi...
static int free_dv_routes_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free DV route entry.
static enum GNUNET_GenericReturnValue add_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR
Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope...
static void handle_queue_create_fail(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue failed.
static void check_link_down(void *cls)
Task run to check whether the hops of the cls still are validated, or if we need to core about discon...
static void check_for_global_natted_error_cb(void *cls)
static void finish_cmc_handling_with_continue(struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
Send ACK to communicator (if requested) and free cmc.
static void forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
Build and forward a DV learn message to next_hop.
static void handle_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Incoming message.
static void validation_transmit_on_queue(struct Queue *q, struct ValidationState *vs)
The queue q (which matches the peer and address in vs) is ready for queueing.
static int free_ack_cummulator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free acknowledgement cummulator.
static void update_pm_next_attempt(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission ...
#define PILS_FEED_ADDRESSES_DELAY
Delay between added/removed addresses and PILS feed call.
static int check_known_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the address from cls.
enum GNUNET_GenericReturnValue use_burst
static struct GNUNET_CONTAINER_MultiPeerMap * dv_routes
Map from PIDs to struct DistanceVector entries describing known paths to the peer.
static struct GNUNET_TIME_Relative route_control_message_without_fc(struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
We need to transmit hdr to target.
static void free_incoming_request(struct IncomingRequest *ir)
Release ir data structure.
#define MAX_INCOMING_REQUEST
For how many incoming connections do we try to create a virtual link for (at the same time!...
static void neighbour_dv_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a DV initiator by PEERSTORE.
static struct GNUNET_PILS_Handle * pils
Service that manages our peer id.
void(* DVMessageHandler)(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void decaps_dv_box_cb(void *cls, const struct GNUNET_ShortHashCode *km)
static char * get_address_without_port(const char *address)
Get the IP address without the port number.
ClientType
What type of client is the struct TransportClient about?
@ CT_APPLICATION
"Application" telling us where to connect (i.e.
@ CT_MONITOR
It is a monitor, forward monitor data.
@ CT_NONE
We do not know yet (client is fresh).
@ CT_CORE
Is the CORE service, we need to forward traffic to it.
@ CT_COMMUNICATOR
It is a communicator, use for communication.
static int validate_dv_initiator_signature(struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, const struct GNUNET_PeerIdentity *init, const struct GNUNET_CRYPTO_ChallengeNonceP *challenge, const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
static struct IncomingRequest * ir_head
List of incoming connections where we are trying to get a connection back established.
static void free_backtalker(struct Backtalker *b)
Free data structures associated with b.
static void hello_for_client_sync_cb(void *cls)
static void destroy_ack_cummulator(void *cls)
Clean up an idle cumulative acknowledgement data structure.
static void consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
static unsigned int bsize
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
static struct GNUNET_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
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Helper library for handling HELLO URIs.
API to the peerstore service.
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:465
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:488
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_hello(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *builder, struct GNUNET_TIME_Absolute et, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Create HELLO signature.
Definition pils_api.c:703
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:623
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_by_peer_identity(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_SignaturePurpose *purpose, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Sign data with the peer id.
Definition pils_api.c:528
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:727
struct GNUNET_PILS_Operation * GNUNET_PILS_kem_decaps(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, GNUNET_PILS_DecapsResultCallback cb, void *cb_cls)
Decaps an encapsulated key with our private key.
Definition pils_api.c:568
void GNUNET_PILS_feed_addresses(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *addresses_builder)
Feed a set of addresses to pils so that it will generate a new peer id based on the given set of addr...
Definition pils_api.c:669
uint32_t dim
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE
Signature by a peer affirming that it received a challenge (and stating how long it expects the addre...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
Signature by a peer affirming that the given ephemeral key is currently in use by that peer's transpo...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
Signature by a peer affirming that it originated the DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
Signature by a peer affirming that it is on a DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS
Signature by a peer affirming that this is one of its addresses for the given time period.
API to create, modify and access statistics.
API of the transport service towards the communicator processes.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
GNUNET_TRANSPORT_CommunicatorCharacteristics
What characteristics does this communicator have?
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_CS_DOWN
Connection is down.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_CONTAINER_MDLL_remove(mdll, head, tail, element)
Remove an element from a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_tail(mdll, head, tail, element)
Insert an element at the tail of a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_after(mdll, head, tail, other, element)
Insert an element into a MDLL after the given other element.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_MDLL_insert(mdll, head, tail, element)
Insert an element at the head of a MDLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
#define GNUNET_CRYPTO_hkdf_expand(result, out_len, prk,...)
HKDF-Expand using SHA256.
struct GNUNET_CONTAINER_MultiUuidmap * GNUNET_CONTAINER_multiuuidmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_remove(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_remove(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, const void *value)
Remove the given key-value pair from the map.
void GNUNET_CONTAINER_multiuuidmap_destroy(struct GNUNET_CONTAINER_MultiUuidmap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_iterate(struct GNUNET_CONTAINER_MultiUuidmap *map, GNUNET_CONTAINER_MultiUuidmapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_put(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multiuuidmap_get(const struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:380
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:398
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:344
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition hello-uri.c:992
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_parser(const struct GNUNET_HELLO_Parser *parser, struct GNUNET_PeerIdentity *pid)
Allocate builder from parser.
Definition hello-uri.c:361
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:1011
struct GNUNET_MQ_Envelope * GNUNET_HELLO_parser_to_env(const struct GNUNET_HELLO_Parser *parser)
Generate envelope with GNUnet HELLO message (including peer ID) from a parser.
Definition hello-uri.c:939
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_address_list_cmp(const struct GNUNET_HELLO_Builder *abuilder, const struct GNUNET_HELLO_Builder *bbuilder)
Compare address lists of two builders.
Definition hello-uri.c:1366
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_del_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Remove individual address from the builder.
Definition hello-uri.c:968
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:354
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid)
Parse msg.
Definition hello-uri.c:416
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:660
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:1098
struct GNUNET_MQ_Envelope * GNUNET_HELLO_builder_to_env(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration_time)
Generate envelope with GNUnet HELLO message (including peer ID) from a builder.
Definition hello-uri.c:1178
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
#define GNUNET_CRYPTO_kdf_arg_string(d)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
GNUNET_SCHEDULER_Priority
Valid task priorities.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_CRYPTO_kdf_arg_auto(d)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_EXTRA_LOGGING
define GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source tree where gnunet_config....
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_check_boxed_message(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition mq.c:205
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition mq.c:655
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:896
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
@ GNUNET_MQ_PRIO_BACKGROUND
Lowest priority, i.e.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
@ GNUNET_MQ_PREF_LOW_LATENCY
Flag to indicate that low latency is important.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition nat.c:89
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
void GNUNET_NAT_add_global_address(struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
Add global address to the list of addresses and notify clients.
Definition nat_api.c:460
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
#define GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME
Key used to store sender's monotonic time from backchannel messages.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
#define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME
Key used to store sender's monotonic time from DV learn messages.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY
Key used for storing HELLOs in the peerstore.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
struct GNUNET_PEERSTORE_StoreHelloContext * GNUNET_PEERSTORE_hello_add(struct GNUNET_PEERSTORE_Handle *h, const struct GNUNET_MessageHeader *msg, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Add hello to peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
P2P message: transport requests confirmation that an address works.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK
transport acknowledges processing an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN
inform transport that a queue was torn down
#define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
Type of the 'struct RequestHelloValidationMessage' send by clients to TRANSPORT to trigger validation...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START
Message from the core saying that the transport server should start giving it messages.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA
Message sent to indicate to a monitor about events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR
Message sent to indicate to the transport which address prefix is supported by a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
Message telling transport to limit its receive rate.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
Type of a fragment of a CORE message created by transport to adjust message length to a queue's MTU.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL
Response from communicator: address bogus, will not try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
Source-routed transport message based DV information gathered.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
Wrapper around non-fragmented CORE message used to measure RTT and ensure reliability.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to abandon bandwidth prefe...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
Message from TRANSPORT notifying about a message that was received.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION
Message type used between transport services when they internally forward communicator backchannel me...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE
transport tells communicator it wants a queue
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
Message sent for topology discovery at transport level.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
Tell transport that it should assist with exchanging a message between communicators.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
Message from TRANSPORT notifying about a client that disconnected from us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG
inform transport about an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK
Response from communicator: will try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK
communicator tells transports that message was sent
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS
inform transport to add an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START
Message sent to indicate to the transport that a monitor wants to observe certain events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS
inform transport to delete an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
P2P message: transport proves that an address worked.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG
transport tells communicator it wants to transmit
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
Request to TRANSPORT to transmit a message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
Confirmation from TRANSPORT that message for transmission has been queued (and that the next message ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
Confirmation for a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP
inform transport that a queue was setup to talk to some peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to establish bandwidth pre...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE
inform transport that a queue was updated
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1260
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1213
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2528
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition strings.c:1623
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition time.c:344
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition time.c:264
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition time.c:626
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
#define GNUNET_TIME_relative_cmp(t1, op, t2)
Compare two relative times.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition time.c:368
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:604
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Relative GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIME_Relative threshold)
Randomized exponential back-off, starting at 1 ms and going up by a factor of 2+r,...
Definition time.c:830
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition time.c:601
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply_double(struct GNUNET_TIME_Relative rel, double factor)
Multiply relative time by a given factor.
Definition time.c:506
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition time.c:583
struct GNUNET_TIME_Relative GNUNET_TIME_randomize(struct GNUNET_TIME_Relative r)
Return a random time value between 0.5*r and 1.5*r.
Definition time.c:851
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition time.c:471
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition time.c:360
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition time.c:616
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition time.c:452
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:860
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition time.c:548
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:665
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition peer.c:68
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition socks.c:330
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
Data structure in which we track acknowledgements still to be sent to the.
struct GNUNET_SCHEDULER_Task * task
Task scheduled either to transmit the cumulative ACK message, or to clean up this data structure afte...
struct GNUNET_TIME_Absolute min_transmission_time
When is task run (only used if num_acks is non-zero)?
struct TransportCummulativeAckPayload ack_uuids[64]
ACK data being accumulated.
struct GNUNET_PeerIdentity target
Target peer for which we are accumulating ACKs here.
unsigned int num_acks
Number of entries used in ack_uuids.
uint32_t ack_counter
Counter to produce the ack_counter in the struct TransportReliabilityAckMessage.
Unique identifier to map an acknowledgement to a transmission.
struct GNUNET_Uuid value
The UUID value.
One of the addresses of this peer.
struct GNUNET_TIME_Relative expiration
What is a typical lifetime the communicator expects this address to have? (Always from now....
uint32_t aid
Address identifier used by the communicator.
size_t signed_address_len
Signed address length.
enum GNUNET_NetworkType nt
Network type offered by this address.
struct AddressListEntry * prev
Kept in a DLL.
struct TransportClient * tc
Which communicator provides this address?
struct AddressListEntry * next
Kept in a DLL.
struct GNUNET_PEERSTORE_StoreHelloContext * shc
Store hello handle.
void * signed_address
Signed address.
const char * address
The actual address.
struct GNUNET_SCHEDULER_Task * st
Task to periodically do st operation.
struct GNUNET_PEERSTORE_StoreContext * sc
Current context for storing this address in the peerstore.
A Backtalker is a peer sending us backchannel messages.
struct GNUNET_TIME_Absolute timeout
When will this entry time out?
struct CommunicatorMessageContext * cmc
Communicator context waiting on this backchannel's get, or NULL.
struct GNUNET_CRYPTO_HpkeEncapsulation last_ephemeral
Last (valid) ephemeral key received from this sender.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation for this pid's monotonic_time.
struct GNUNET_SCHEDULER_Task * task
Task associated with this backtalker.
size_t body_size
Number of bytes of the original message body that follows after this struct.
struct GNUNET_TIME_Absolute monotonic_time
Last (valid) monotonic time received from this sender.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch monotonic_time information from the PEERSTORE, or NULL.
struct GNUNET_PeerIdentity pid
Peer this is about.
Closure for check_known_address.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const char * address
Set to the address we are looking for.
Closure for check_known_challenge.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const struct GNUNET_CRYPTO_ChallengeNonceP * challenge
Set to the challenge we are looking for.
Context from handle_incoming_msg().
struct CommunicatorMessageContext * next
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
uint16_t total_hops
Number of hops the message has travelled (if DV-routed).
struct GNUNET_TRANSPORT_IncomingMessage im
Additional information for flow control and about the sender.
unsigned int continue_send
Did we already call GNUNET_SERVICE_client_continue and send ACK to communicator?
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
struct CommunicatorMessageContext * prev
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
struct TransportClient * tc
Which communicator provided us with the message.
Message from the transport service to the library informing about neighbors.
Definition transport.h:89
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition transport.h:112
Closure for core_env_sent_cb.
uint16_t isize
By how much should we increment vl's incoming_fc_window_size_used once we are done sending to CORE?...
struct CoreSentContext * next
Kept in a DLL to clear vl in case vl is lost.
struct VirtualLink * vl
Virtual link this is about.
struct CoreSentContext * prev
Kept in a DLL to clear vl in case vl is lost.
uint16_t size
How big was the message.
Structure of the key material used to encrypt backchannel messages.
struct GNUNET_CRYPTO_AuthKey hmac_key
Key used for HMAC calculations (via GNUNET_CRYPTO_hmac()).
gcry_cipher_hd_t cipher
State of our block cipher.
char aes_key[256/8]
Symmetric key to use for encryption.
char aes_ctr[128/8]
Counter value to use during setup.
struct DVKeyState::@73 material
Actual key material.
An entry describing a peer on a path in a struct TransportDVLearnMessage message.
struct GNUNET_CRYPTO_EddsaSignature hop_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity hop
Identity of a peer on the path.
const struct TransportDVBoxMessage * dvb
struct PilsRequest * pr
struct CommunicatorMessageContext * cmc
Message from the transport service to the library informing about disconnects.
Definition transport.h:121
One possible hop towards a DV target.
struct PerformanceData pd
Performance data for this transmission possibility.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used our path.
unsigned int distance
Number of hops in total to the target (excluding next_hop and target itself).
struct DistanceVectorHop * next_neighbour
Kept in a MDLL.
struct Neighbour * next_hop
What would be the next hop to target?
struct GNUNET_TIME_Absolute timeout
At what time do we forget about this path unless we see it again while learning?
struct DistanceVector * dv
Distance vector entry this hop belongs with.
const struct GNUNET_PeerIdentity * path
Array of distance hops to the target, excluding next_hop.
struct DistanceVectorHop * next_dv
Kept in a MDLL, sorted by timeout.
struct GNUNET_TIME_Absolute path_valid_until
For how long is the validation of this path considered valid? Set to ZERO if the path is learned by s...
struct DistanceVectorHop * prev_dv
Kept in a MDLL, sorted by timeout.
struct DistanceVectorHop * prev_neighbour
Kept in a MDLL.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used our path.
Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer.
struct DistanceVectorHop * dv_head
Known paths to target.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct GNUNET_TIME_Absolute monotime
What time was sender_sig created.
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature affirming ephemeral_key of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct DistanceVectorHop * dv_tail
Known paths to target.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Our ephemeral key.
struct GNUNET_ShortHashCode * km
Master secret for the setup of the Key material for the backchannel.
struct GNUNET_PeerIdentity target
To which peer is this a route?
struct GNUNET_TIME_Absolute ephemeral_validity
How long is sender_sig valid.
struct GNUNET_SCHEDULER_Task * timeout_task
Task scheduled to purge expired paths from dv_head MDLL.
Content signed by each peer during DV learning.
struct GNUNET_PeerIdentity pred
Identity of the previous peer on the path.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
Body by which a peer confirms that it is using an ephemeral key.
struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time
How long is this signature over the ephemeral key valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_PeerIdentity target
Target's peer identity.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
Application client to TRANSPORT service: we would like to have address suggestions for this peer.
Definition transport.h:807
Closure for find_by_message_uuid.
struct ReassemblyContext * rc
Set to the reassembly context if found.
struct MessageUUIDP message_uuid
UUID to look for.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
Wrapper struct with the average RTT of message to some peer and if this peer und us is ready to sync.
enum GNUNET_GenericReturnValue sync_ready
Is this peer already ready to sync.
struct GNUNET_TIME_RelativeNBO rtt_average
The average RTT for the peer to communicate with.
Handle to a node in a heap.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
type for (message) authentication keys
Type of a nonce used for challenges.
struct GNUNET_ShortHashCode value
The value of the nonce.
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Context for building (or parsing) HELLO URIs.
Definition hello-uri.c:185
Context for parsing HELLOs.
Definition hello-uri.c:233
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Message handler for a specific message type.
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
Handle to the PEERSTORE service.
Context for a iterate request.
Context for a store request.
Context for a add hello uri request.
A handle for the PILS service.
Definition pils_api.c:82
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition scheduler.c:141
Handle to a client that is connected to a service.
Definition service.c:249
Handle to a service.
Definition service.c:116
Handle for the service.
A 256-bit hashcode.
Struct wrapping information we use for starting the burst.
struct VirtualLink * vl
The VirtualLink of the peer to which we like to burst with.
struct GNUNET_TIME_Relative delay
The delay - calculate from the RTT and which peer was ready to sync first, after we will start the bu...
unsigned int sync_ready
We are ready to start the burst.
struct GNUNET_TIME_Relative rtt
The average RTT between the peers.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds and in network byte order.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Add address to the list.
Definition transport.h:288
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
Definition transport.h:292
struct GNUNET_TIME_RelativeNBO expiration
When does the address expire?
Definition transport.h:302
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:307
uint32_t aid
Address identifier (used during deletion).
Definition transport.h:297
Add queue to the transport.
Definition transport.h:402
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:421
uint32_t mtu
Maximum transmission unit, in NBO.
Definition transport.h:426
uint64_t q_len
Queue length, in NBO.
Definition transport.h:432
uint32_t qid
Queue identifier (used to identify the queue).
Definition transport.h:411
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:416
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
Definition transport.h:406
uint32_t cs
An enum GNUNET_TRANSPORT_ConnectionStatus in NBO.
Definition transport.h:442
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
Definition transport.h:268
uint32_t cc
NBO encoding of enum GNUNET_TRANSPORT_CommunicatorCharacteristics
Definition transport.h:273
uint32_t can_burst
The communicator can do burst msgs.
Definition transport.h:278
Message from transport to communicator passing along a backchannel message from the given peer pid.
Definition transport.h:656
struct GNUNET_PeerIdentity pid
Origin peer.
Definition transport.h:671
Message from communicator to transport service asking for transmission of a backchannel message with ...
Definition transport.h:627
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL.
Definition transport.h:631
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:641
Communicator tells transport how queue creation went down.
Definition transport.h:546
uint32_t request_id
Unique ID for the request.
Definition transport.h:556
Transport tells communicator that it wants a new queue.
Definition transport.h:522
uint32_t request_id
Unique ID for the request.
Definition transport.h:531
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:536
Remove address from the list.
Definition transport.h:317
uint32_t aid
Address identifier.
Definition transport.h:326
Remove queue, it is no longer available.
Definition transport.h:500
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:514
uint32_t qid
Address identifier.
Definition transport.h:509
Transport informs us about being done with an incoming message.
Definition transport.h:375
struct GNUNET_PeerIdentity sender
Sender identifier of the original message.
Definition transport.h:394
uint64_t fc_id
Which message is being ACKed?
Definition transport.h:389
uint32_t reserved
Reserved (0)
Definition transport.h:384
Inform transport about an incoming message.
Definition transport.h:334
struct GNUNET_PeerIdentity neighbour_sender
Direct neighbour sender identifier.
Definition transport.h:364
struct GNUNET_TIME_RelativeNBO expected_address_validity
How long does the communicator believe the address on which the message was received to remain valid?
Definition transport.h:354
struct GNUNET_PeerIdentity sender
Sender identifier.
Definition transport.h:359
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
Definition transport.h:338
uint32_t fc_on
Do we use flow control or not?
Definition transport.h:343
uint64_t fc_id
64-bit number to identify the matching ACK.
Definition transport.h:348
uint32_t num_msg_pending
Messages pending (in NBO).
Definition transport.h:767
struct GNUNET_PeerIdentity peer
Target identifier.
Definition transport.h:745
struct GNUNET_TIME_AbsoluteNBO valid_until
Definition transport.h:751
struct GNUNET_TIME_AbsoluteNBO last_validation
Definition transport.h:750
uint32_t num_bytes_pending
Bytes pending (in NBO).
Definition transport.h:772
struct GNUNET_TIME_AbsoluteNBO next_validation
Definition transport.h:752
uint32_t nt
Network type (an enum GNUNET_NetworkType in NBO).
Definition transport.h:740
struct GNUNET_TIME_RelativeNBO rtt
Current round-trip time estimate.
Definition transport.h:757
uint32_t cs
Connection status (in NBO).
Definition transport.h:762
Request to start monitoring.
Definition transport.h:709
Inform transport that message was sent.
Definition transport.h:593
uint64_t mid
Message ID of the original message.
Definition transport.h:607
uint32_t qid
Queue ID for the queue which was used to send the message.
Definition transport.h:612
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:617
Inform communicator about transport's desire to send a message.
Definition transport.h:564
uint32_t qid
Which queue should we use?
Definition transport.h:573
uint64_t mid
Message ID, used for flow control.
Definition transport.h:578
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
Definition transport.h:568
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:583
Message from transport to communicator to start a burst.
Definition transport.h:681
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST.
Definition transport.h:685
struct GNUNET_TIME_RelativeNBO rtt
Definition transport.h:692
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:690
A UUID, a 128 bit "random" value.
Message used to notify the transport API about a message received from the network.
Definition transport.h:144
struct GNUNET_PeerIdentity peer
Which peer sent the message?
Definition transport.h:153
Another peer attempted to talk to us, we should try to establish a connection in the other direction.
struct IncomingRequest * next
Kept in a DLL.
struct IncomingRequest * prev
Kept in a DLL.
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
When did we launch this DV learning activity?
struct LearnLaunchEntry * next
Kept (also) in a DLL sorted by launch time.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge that uniquely identifies this activity.
struct LearnLaunchEntry * prev
Kept (also) in a DLL sorted by launch time.
struct GNUNET_TIME_Absolute launch_time
When did we transmit the DV learn message (used to calculate RTT) and determine freshness of paths le...
Unique identifier we attach to a message.
uint64_t uuid
Unique value, generated by incrementing the message_uuid_ctr of struct Neighbour.
Details about what to notify monitors about.
enum GNUNET_TRANSPORT_ConnectionStatus cs
Connection status.
struct GNUNET_TIME_Absolute last_validation
struct GNUNET_TIME_Absolute next_validation
struct GNUNET_TIME_Absolute valid_until
struct GNUNET_TIME_Relative rtt
Current round-trip time estimate.
uint32_t num_msg_pending
Messages pending.
uint32_t num_bytes_pending
Bytes pending.
Closure for dv_neighbour_selection and dv_neighbour_transmission.
const struct TransportDVLearnMessage * dvl
Original message we received.
struct GNUNET_TIME_Absolute in_time
Time we received the message.
const struct DVPathEntryP * hops
The hops taken.
uint16_t bi_history
Bitmap of bidirectional connections encountered.
unsigned int num_eligible
Number of peers eligible for selection.
unsigned int num_selections
Number of peers that were selected for forwarding.
uint32_t selections[MAX_DV_DISCOVERY_SELECTION]
Offsets of the selected peers.
uint16_t nhops
Number of hops in hops.
A neighbour that at least one communicator is connected to.
size_t size_of_global_addresses
Size of all global natted addresses for this neighbour.
struct DistanceVectorHop * dv_tail
Tail of MDLL of DV hops that have this neighbour as next hop.
struct GNUNET_CONTAINER_MultiPeerMap * natted_addresses
Map of struct TransportGlobalNattedAddress for this neighbour.
struct GNUNET_TIME_Absolute last_dv_learn_monotime
Latest DVLearn monotonic time seen from this peer.
int dv_monotime_available
Do we have the latest value for last_dv_learn_monotime from PEERSTORE yet, or are we still waiting fo...
unsigned int number_of_addresses
Number of global natted addresses for this neighbour.
struct Queue * queue_tail
Tail of DLL of queues to this peer.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation to store this pid's last_dv_learn_monotime.
struct DistanceVectorHop * dv_head
Head of MDLL of DV hops that have this neighbour as next hop.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct Queue * queue_head
Head of DLL of queues to this peer.
struct GNUNET_PeerIdentity pid
Which peer is this about?
enum GNUNET_GenericReturnValue is_global_natted
A queue of this neighbour has a global natted address.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch last_dv_learn_monotime information from the PEERSTORE,...
Message used to notify the transport service about a message to be transmitted to another peer.
Definition transport.h:230
uint32_t priority
An enum GNUNET_MQ_PriorityPreferences in NBO.
Definition transport.h:239
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND.
Definition transport.h:234
struct GNUNET_PeerIdentity peer
Which peer should receive the message?
Definition transport.h:253
Information per peer and request.
struct GNUNET_BANDWIDTH_Value32NBO bw
How much bandwidth would this tc like to see?
struct TransportClient * tc
Client responsible for the request.
enum GNUNET_MQ_PriorityPreferences pk
What kind of performance preference does this tc have?
struct GSF_PendingRequest * pr
Handle to generic request (generic: from peer or local client).
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
Data structure kept when we are waiting for an acknowledgement.
struct AcknowledgementUUIDP ack_uuid
Unique identifier for this transmission operation.
unsigned int num_send
How often the PendingMessage was send via the Queue of this PendingAcknowledgement.
struct PendingAcknowledgement * next_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingMessage * pm
Message that was transmitted, may be NULL if the message was ACKed via another channel.
struct PendingAcknowledgement * next_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
struct PendingAcknowledgement * next_pa
Pointers for the DLL of all pending acknowledgements.
struct PendingAcknowledgement * next_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct GNUNET_TIME_Absolute transmission_time
Time of the transmission, for RTT calculation.
struct Queue * queue
Queue used for transmission, NULL if the queue has been destroyed (which may happen before we get an ...
struct DistanceVectorHop * dvh
Distance vector path chosen for this transmission, NULL if transmission was to a direct neighbour OR ...
uint16_t message_size
Number of bytes of the original message (to calculate bandwidth).
struct PendingAcknowledgement * prev_pa
Pointers for the DLL of all pending acknowledgements.
struct PendingAcknowledgement * prev_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct PendingAcknowledgement * prev_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingAcknowledgement * prev_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
Context for select_best_pending_from_link().
struct GNUNET_TIME_Relative to_early_retry_delay
When will we try to transmit the message again for which it was to early to retry.
struct PendingMessage * best
Set to the best message that was found, NULL for none.
int to_early
There are pending messages, but it was to early to send one of them.
unsigned int consideration_counter
Number of pending messages we seriously considered this time.
struct DistanceVectorHop * dvh
DVH that best should take, or NULL for direct transmission.
size_t real_overhead
What is the estimated total overhead for this message?
unsigned int frags_in_flight
There is a pending messages we are sending fragments at the moment.
int frag
Did we have to fragment?
int relb
Did we have to reliability box?
List containing all messages that are yet to be send.
struct PendingMessage * tail_frag
Tail of a MDLL of fragments created for this core message.
struct PendingMessage * frag_parent
Our parent in the fragmentation tree.
enum GNUNET_MQ_PriorityPreferences prefs
Preferences for this message.
struct TransportClient * client
Client that issued the transmission request, if pmt is PMT_CORE.
struct QueueEntry * qe
Set to non-NULL value if this message is currently being given to a communicator and we are awaiting ...
struct MessageUUIDP msg_uuid
UUID to use for this message (used for reassembly of fragments, only initialized if msg_uuid_set is G...
struct PendingMessage * head_frag
Head of a MDLL of fragments created for this core message.
uint16_t bytes_msg
Size of the original message.
enum PendingMessageType pmt
Type of the pending message.
struct PendingMessage * prev_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
struct PendingMessage * prev_vl
Kept in a MDLL of messages for this vl.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs for this pending message.
struct PendingMessage * next_vl
Kept in a MDLL of messages for this vl.
struct VirtualLink * vl
Target of the request (always the ultimate destination!).
struct PendingAcknowledgement * pa_head
Head of DLL of PAs for this pending message.
struct DistanceVectorHop * used_dvh
If pmt is of type PMT_DV_BOX we store the used path here.
int16_t msg_uuid_set
GNUNET_YES once msg_uuid was initialized
uint32_t frags_in_flight_round
The round we are (re)-sending fragments.
struct PendingMessage * next_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
uint32_t frags_in_flight
Are we sending fragments at the moment?
uint16_t frag_off
Offset at which we should generate the next fragment.
struct PendingMessage * next_frag
Kept in a MDLL of messages from this cpm (if pmt is #PMT_FRAGMENT_BOx)
uint64_t logging_uuid
UUID we use to identify this message in our logs.
uint16_t frag_count
How many fragments do we have?
struct PendingMessage * prev_frag
Kept in a MDLL of messages from this cpm (if pmt is PMT_FRAGMENT_BOX)
struct PendingMessage * bpm
This message, reliability or DV-boxed.
struct GNUNET_TIME_Absolute next_attempt
What is the earliest time for us to retry transmission of this message?
struct GNUNET_TIME_Absolute timeout
At what time should we give up on the transmission (and no longer retry)?
struct GNUNET_PeerIdentity target
In case of a not validated neighbour, we store the target peer.
Performance data for a transmission possibility.
struct GNUNET_TIME_Relative aged_rtt
Weighted average for the RTT.
struct TransmissionHistoryEntry the[4]
Historic performance data, using a ring buffer of::GOODPUT_AGING_SLOTS entries.
unsigned int last_age
What was the last age when we wrote to the? Used to clear old entries when the age advances.
Helper context struct for HELLO update.
struct GNUNET_TIME_Absolute et
Signature expiration.
struct AddressListEntry * ale
The ale to update.
struct PilsRequest * req
Any pending PILS requests.
struct GNUNET_PILS_Operation * op
The pils operation.
struct PilsRequest * next
DLL.
struct PilsRequest * prev
DLL.
Entry identifying transmission in one of our struct Queue which still awaits an ACK.
struct QueueEntry * next
Kept as a DLL.
struct QueueEntry * prev
Kept as a DLL.
struct GNUNET_TIME_Absolute creation_timestamp
Timestamp this QueueEntry was created.
uint64_t mid
Message ID used for this message with the queue used for transmission.
struct PendingMessage * pm
Pending message this entry is for, or NULL for none.
struct Queue * queue
Queue this entry is queued with.
Closure for check_connection_quality.
unsigned int k
Decremented for each queue, for selection of the k-th queue in q.
struct Queue * q
Set to the k'th queue encountered.
unsigned int num_queues
Set to the total number of queues encountered.
unsigned int quality_count
Set to the number of quality queues encountered.
Handle for a queue.
uint32_t qid
Unique identifier of this queue with the communicator.
struct QueueEntry * queue_tail
End of DLL of unacked transmission requests.
struct Queue * prev_client
Kept in a MDLL.
unsigned int queue_length
Length of the DLL starting at queue_head.
uint32_t num_msg_pending
Messages pending.
struct GNUNET_PEERSTORE_Monitor * mo
Handle for an operation to iterate through all hellos to compare the hello addresses with address whi...
uint64_t q_capacity
Capacity of the queue.
struct Queue * next_neighbour
Kept in a MDLL.
uint32_t num_bytes_pending
Bytes pending.
uint32_t priority
Queue priority.
struct Neighbour * neighbour
Which neighbour is this queue for?
int idle
Set to GNUNET_YES if this queue is idle waiting for some virtual link to give it a pending message.
struct Queue * prev_neighbour
Kept in a MDLL.
struct PerformanceData pd
Performance data for this queue.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_SCHEDULER_Task * transmit_task
Task scheduled for the time when this queue can (likely) transmit the next message.
struct QueueEntry * queue_head
Head of DLL of unacked transmission requests.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used this queue.
struct TransportClient * tc
Which communicator offers this queue?
struct Queue * next_client
Kept in a MDLL.
enum GNUNET_GenericReturnValue is_global_natted
Set to GNUNET_YES, if this queues address is a global natted one.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
uint32_t mtu
Maximum transmission unit supported by this queue.
unsigned int unlimited_length
Is this queue of unlimited length.
enum GNUNET_TRANSPORT_ConnectionStatus cs
The connection status of this queue.
uint64_t mid_gen
Message ID generator for transmissions on this queue to the communicator.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used this queue.
const char * address
Address served by the queue.
Information we keep for a message that we are reassembling.
struct GNUNET_CONTAINER_HeapNode * hn
Entry in the reassembly heap (sorted by expiration).
struct GNUNET_TIME_Absolute last_frag
Time we received the last fragment.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct VirtualLink * virtual_link
Which neighbour is this context for?
uint8_t * bitfield
Bitfield with msg_size bits representing the positions where we have received fragments.
uint16_t msg_size
How big is the message we are reassembling in total?
struct GNUNET_TIME_Absolute reassembly_timeout
At what time will we give up reassembly of this message?
uint16_t msg_missing
How many bytes of the message are still missing? Defragmentation is complete when msg_missing == 0.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:206
struct GNUNET_PeerIdentity peer
Which peer can CORE handle more from now?
Definition transport.h:221
uint32_t increase_window_delta
Number of messages by which to increase the window, greater or equal to one.
Definition transport.h:216
We got an address of another peer, TRANSPORT service should validate it.
Definition transport.h:838
Entry for the ring buffer caching messages send to core, when virtual link is available.
struct CommunicatorMessageContext * cmc
Communicator context for this ring buffer entry.
struct GNUNET_MessageHeader * mh
The message in this entry.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:162
struct GNUNET_PeerIdentity peer
Which peer can send more now?
Definition transport.h:196
struct DVPathEntryP * dhops
struct PilsRequest * pr
struct TransportDVLearnMessage * fwd
const struct GNUNET_PeerIdentity * next_hop
struct PilsRequest * req
struct DistanceVector * dv
struct PilsRequest * pr
struct QueueQualityContext qqc
struct TransportDVLearnMessage dvl
struct LearnLaunchEntry * lle
struct TransportValidationResponseMessage tvr
struct CommunicatorMessageContext * cmc
Binary block we sign when we sign an address.
struct GNUNET_TIME_AbsoluteNBO mono_time
When was the address generated.
struct GNUNET_HashCode addr_hash GNUNET_PACKED
Hash of the address.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS.
Message from the transport service to the library asking to check if both processes agree about this ...
Definition transport.h:62
Information we keep per GOODPUT_AGING_SLOTS about historic (or current) transmission performance.
uint64_t bytes_received
Number of bytes received and acknowledged by the other peer in the interval.
uint64_t bytes_sent
Number of bytes actually sent in the interval.
Outer layer of an encapsulated backchannel message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
Client connected to the transport service.
enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc
Characteristics of this communicator.
struct PendingMessage * pending_msg_head
Head of list of messages pending for this client, sorted by transmission time ("next_attempt" + possi...
enum ClientType type
What type of client is this?
struct AddressListEntry * addr_tail
Tail of list of the addresses of this peer offered by this communicator.
union TransportClient::@68 details
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::@68::@72 application
Information for type CT_APPLICATION.
struct TransportClient::@68::@70 monitor
Information for type CT_MONITOR.
struct Queue * queue_head
Head of DLL of queues offered by this communicator.
struct AddressListEntry * addr_head
Head of list of the addresses of this peer offered by this communicator.
struct TransportClient::@68::@69 core
Information for type CT_CORE.
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of requests for peers the given client application would like to see connections for.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct TransportClient * prev
Kept in a DLL.
struct TransportClient::@68::@71 communicator
Information for type CT_COMMUNICATOR.
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.
unsigned int total_queue_length
Number of queue entries in all queues to this communicator.
int one_shot
Is this a one-shot monitor?
struct GNUNET_PeerIdentity peer
Peer identity to monitor the addresses of.
enum GNUNET_GenericReturnValue can_burst
Can be used for burst messages.
struct GNUNET_TIME_RelativeNBO ack_delay
How long was the ACK delayed for generating cumulative ACKs? Used to calculate the correct network RT...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
struct GNUNET_TIME_Absolute receive_time
When did we receive the message we are ACKing? Used to calculate the delay we introduced by cummulati...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
Outer layer of an encapsulated message send over multiple hops.
struct GNUNET_HashCode hmac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX.
uint16_t num_hops
Number of hops this messages includes.
uint16_t orig_size
Size this msg had initially.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
unsigned int without_fc
Flag if the payload is a control message.
struct GNUNET_ShortHashCode iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
uint16_t total_hops
Number of total hops this messages travelled.
Plaintext of the variable-size payload that is encrypted within a struct TransportBackchannelEncapsul...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature of the sender over an GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Current monotonic time of the sending transport service.
struct GNUNET_PeerIdentity sender
Sender's peer identity.
Internal message used by transport for distance vector learning.
struct GNUNET_PeerIdentity initiator
Identity of the peer that started this learning activity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN.
struct GNUNET_TIME_RelativeNBO non_network_delay
Peers receiving this message and delaying forwarding to other peers for any reason should increment t...
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EddsaSignature init_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
uint16_t num_hops
Number of hops this messages has travelled, in NBO.
uint16_t bidirectional
Bitmask of the last 16 hops indicating whether they are confirmed available (without DV) in both dire...
Message for Transport-to-Transport Flow control.
uint64_t outbound_window_size
Latest flow control window size we learned from the other peer, in bytes, in NBO.
unsigned int number_of_addresses
Number of TransportGlobalNattedAddress following the struct.
size_t size_of_addresses
Size of all the addresses attached to all TransportGlobalNattedAddress.
uint64_t inbound_window_size
Flow control window size in bytes, in NBO.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender.
uint32_t seq
Sequence number of the flow control message.
uint64_t outbound_sent
How many bytes has the sender sent that count for flow control at this time.
struct GNUNET_TIME_RelativeNBO rtt
Average RTT for the DistanceVector of the VirtualLink we tell the target.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL.
unsigned int sync_ready
We tell the target, if we are ready to start the burst.
Outer layer of an encapsulated fragmented application message.
uint16_t frag_off
Offset of this fragment in the overall message.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct AcknowledgementUUIDP ack_uuid
Unique ID of this fragment (and fragment transmission!).
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT.
uint16_t msg_size
Total size of the message that is being fragmented.
struct TransportGlobalNattedAddress * tgna
The struct TransportGlobalNattedAddress to set.
unsigned int address_length
Length of the address following the struct in NBO.
Confirmation that the receiver got a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
uint32_t ack_counter
Counter of ACKs transmitted by the sender to us.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK.
Outer layer of an encapsulated unfragmented application message sent over an unreliable channel.
uint32_t ack_countdown
Number of messages still to be sent before a commulative ACK is requested.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
struct AcknowledgementUUIDP ack_uuid
Unique ID of the message used for signalling receipt of messages sent over possibly unreliable channe...
Message send to another peer to validate that it can indeed receive messages at a particular address.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge to be signed by the receiving peer.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender, to be copied into the reply to allow sender to calculate RTT.
Message signed by a peer to confirm that it can indeed receive messages at a particular address.
struct GNUNET_TIME_RelativeNBO validity_duration
How long does the sender believe the address on which the challenge was received to remain valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge signed by the receiving peer.
Message send to a peer to respond to a #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
The challenge that was signed by the receiving peer.
struct GNUNET_CRYPTO_EddsaSignature signature
The peer's signature matching the GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
struct GNUNET_PEERSTORE_StoreHelloContext * sc
State we keep for validation activities.
struct GNUNET_TIME_Absolute valid_until
How long did the peer claim this address to be valid? Capped at minimum of MAX_ADDRESS_VALID_UNTIL re...
struct GNUNET_PeerIdentity pid
For which peer is address to be validated (or possibly valid)? Serves as key in the validation_map.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
common internal definitions for transport service