GNUnet 0.28.0-dev.3-20-gf1136b0b8
 
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 "platform.h"
76#include "gnunet_common.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] =
4507 GNUNET_CRYPTO_random_u64 (num_dv);
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
5037 sel1 = GNUNET_CRYPTO_random_u32 (candidates);
5038 if (0 == (options & RMO_REDUNDANT))
5039 sel2 = candidates; /* picks none! */
5040 else
5041 sel2 = GNUNET_CRYPTO_random_u32 (candidates);
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
5077typedef void (*DVMessageHandler) (void *cls,
5078 struct Neighbour *next_hop,
5079 const struct GNUNET_MessageHeader *hdr,
5081
5096static struct GNUNET_TIME_Relative
5098 unsigned int num_dvhs,
5099 struct DistanceVectorHop **dvhs,
5100 const struct GNUNET_MessageHeader *hdr,
5101 DVMessageHandler use,
5102 void *use_cls,
5104 enum GNUNET_GenericReturnValue without_fc)
5105{
5106 const struct GNUNET_PeerIdentity *my_identity;
5107 struct TransportDVBoxMessage box_hdr;
5108 struct TransportDVBoxPayloadP *payload_hdr;
5109 uint16_t body_len_hbo = ntohs (hdr->size);
5110 unsigned char pt[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5112 unsigned char ct[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5114 struct GNUNET_TIME_Relative rtt;
5116
5117 payload_hdr = (struct TransportDVBoxPayloadP*) pt;
5120
5121 /* Encrypt payload */
5123 box_hdr.total_hops = htons (0);
5124 box_hdr.without_fc = htons (without_fc);
5125 // update_ephemeral (dv);
5126 if (0 ==
5127 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5128 {
5129 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5130 &dv->ephemeral_key,
5131 (struct GNUNET_ShortHashCode*) &km);
5132 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5133 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5134 sign_ephemeral (dv);
5135 }
5136 box_hdr.ephemeral_key = dv->ephemeral_key;
5137 payload_hdr->sender_sig = dv->sender_sig;
5138 memcpy (&payload_hdr[1], hdr, body_len_hbo);
5140 sizeof(box_hdr.iv));
5141 payload_hdr->sender = *my_identity;
5142 payload_hdr->monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5143 GNUNET_CRYPTO_aead_encrypt (sizeof pt,
5144 pt,
5145 0,
5146 NULL,
5147 &km,
5148 &box_hdr.iv,
5149 ct,
5150 &box_hdr.mac);
5152 /* For each selected path, take the pre-computed header and body
5153 and add the path in the middle of the message; then send it. */
5154 for (unsigned int i = 0; i < num_dvhs; i++)
5155 {
5156 struct DistanceVectorHop *dvh = dvhs[i];
5157 unsigned int num_hops = dvh->distance + 1;
5158 char buf[sizeof(struct TransportDVBoxMessage)
5159 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5160 + sizeof(struct TransportDVBoxPayloadP)
5161 + body_len_hbo] GNUNET_ALIGN;
5162 struct GNUNET_PeerIdentity *dhops;
5163
5164 box_hdr.header.size = htons (sizeof(buf));
5165 box_hdr.orig_size = htons (sizeof(buf));
5166 box_hdr.num_hops = htons (num_hops);
5167 memcpy (buf, &box_hdr, sizeof(box_hdr));
5168 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5169 memcpy (dhops,
5170 dvh->path,
5171 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5172 dhops[dvh->distance] = dv->target;
5173 if (GNUNET_EXTRA_LOGGING > 0)
5174 {
5175 char *path;
5176
5178 for (unsigned int j = 0; j < num_hops; j++)
5179 {
5180 char *tmp;
5181
5182 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5183 GNUNET_free (path);
5184 path = tmp;
5185 }
5187 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5188 ntohs (hdr->type),
5189 GNUNET_i2s (&dv->target),
5190 i + 1,
5191 num_dvhs,
5192 path);
5193 GNUNET_free (path);
5194 }
5195 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5196 memcpy (&dhops[num_hops], ct, sizeof(ct));
5197 use (use_cls,
5198 dvh->next_hop,
5199 (const struct GNUNET_MessageHeader *) buf,
5200 options);
5201 }
5202 return rtt;
5203}
5204
5205
5215static void
5217 struct Neighbour *next_hop,
5218 const struct GNUNET_MessageHeader *hdr,
5220{
5221 (void) cls;
5222 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5223}
5224
5225
5237static struct GNUNET_TIME_Relative
5239// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5240 const struct GNUNET_MessageHeader *hdr,
5242{
5243 // struct VirtualLink *vl;
5244 struct Neighbour *n;
5245 struct DistanceVector *dv;
5246 struct GNUNET_TIME_Relative rtt1;
5247 struct GNUNET_TIME_Relative rtt2;
5248 const struct GNUNET_PeerIdentity *target = &vl->target;
5249
5251 "Trying to route message of type %u to %s without fc\n",
5252 ntohs (hdr->type),
5253 GNUNET_i2s (target));
5254
5255 // TODO Do this elsewhere. vl should be given as parameter to method.
5256 // vl = lookup_virtual_link (target);
5257 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5258 if (NULL == vl)
5260 n = vl->n;
5261 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5262 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5263 {
5264 /* if confirmed is required, and we do not have anything
5265 confirmed, drop respective options */
5266 if (NULL == n)
5267 n = lookup_neighbour (target);
5268 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5270 }
5271 if ((NULL == n) && (NULL == dv))
5272 {
5274 "Cannot route message of type %u to %s: no route\n",
5275 ntohs (hdr->type),
5276 GNUNET_i2s (target));
5278 "# Messages dropped in routing: no acceptable method",
5279 1,
5280 GNUNET_NO);
5282 }
5284 "Routing message of type %u to %s with options %X\n",
5285 ntohs (hdr->type),
5286 GNUNET_i2s (target),
5287 (unsigned int) options);
5288 /* If both dv and n are possible and we must choose:
5289 flip a coin for the choice between the two; for now 50/50 */
5290 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5291 {
5292 if (0 == GNUNET_CRYPTO_random_u32 (2))
5293 n = NULL;
5294 else
5295 dv = NULL;
5296 }
5297 if ((NULL != n) && (NULL != dv))
5298 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5299 enough for redundancy, so clear the flag. */
5302 if (NULL != n)
5303 {
5305 "Try to route message of type %u to %s without fc via neighbour\n",
5306 ntohs (hdr->type),
5307 GNUNET_i2s (target));
5308 rtt1 = route_via_neighbour (n, hdr, options);
5309 }
5310 if (NULL != dv)
5311 {
5312 struct DistanceVectorHop *hops[2];
5313 unsigned int res;
5314
5316 options,
5317 hops,
5318 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5319 if (0 == res)
5320 {
5322 "Failed to route message, could not determine DV path\n");
5323 return rtt1;
5324 }
5326 "encapsulate_for_dv 1\n");
5327 rtt2 = encapsulate_for_dv (dv,
5328 res,
5329 hops,
5330 hdr,
5332 NULL,
5334 GNUNET_YES);
5335 }
5336 return GNUNET_TIME_relative_min (rtt1, rtt2);
5337}
5338
5339
5340static void
5341consider_sending_fc (void *cls);
5342
5349static void
5351{
5352 struct VirtualLink *vl = cls;
5353 vl->fc_retransmit_task = NULL;
5354 consider_sending_fc (cls);
5355}
5356
5357
5358static char *
5359get_address_without_port (const char *address);
5360
5361
5363{
5364 size_t off;
5365 char *tgnas;
5366};
5367
5368
5369static enum GNUNET_GenericReturnValue
5371 const struct GNUNET_PeerIdentity *pid,
5372 void *value)
5373{
5374 struct AddGlobalAddressesContext *ctx = cls;
5375 struct TransportGlobalNattedAddress *tgna = value;
5376 char *addr = (char *) &tgna[1];
5377
5379 "sending address %s length %u\n",
5380 addr,
5381 ntohl (tgna->address_length));
5382 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5384 + ntohl (tgna->address_length));
5385 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5387
5388 return GNUNET_OK;
5389}
5390
5391
5392static struct GNUNET_TIME_Relative
5393calculate_rtt (struct DistanceVector *dv);
5394
5395
5402static void
5404{
5405 struct VirtualLink *vl = cls;
5406 struct GNUNET_TIME_Absolute monotime;
5407 struct TransportFlowControlMessage *fc;
5409 struct GNUNET_TIME_Relative rtt;
5410 struct GNUNET_TIME_Relative rtt_average;
5411 struct Neighbour *n = vl->n;
5412
5413 if (NULL != n && 0 < n->number_of_addresses)
5414 {
5415 size_t addresses_size =
5416 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5417 ->size_of_global_addresses;
5418 char *tgnas = GNUNET_malloc (addresses_size);
5420 ctx.off = 0;
5421 ctx.tgnas = tgnas;
5422
5424 + addresses_size);
5425 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5426 + addresses_size);
5427 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5428 fc->number_of_addresses = htonl (n->number_of_addresses);
5429 GNUNET_CONTAINER_multipeermap_iterate (n->natted_addresses,
5431 &ctx);
5434 }
5435 else
5436 {
5437 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5438 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5439 }
5440
5442 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5443 it always! */
5444 /* For example, we should probably ONLY do this if a bit more than
5445 an RTT has passed, or if the window changed "significantly" since
5446 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5447 need an estimate for the bandwidth-delay-product for the entire
5448 VL, as that determines "significantly". We have the delay, but
5449 the bandwidth statistics need to be added for the VL!*/(void) duration;
5450
5451 if (NULL != vl->dv)
5452 rtt_average = calculate_rtt (vl->dv);
5453 else
5454 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5455 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5457 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5458 (unsigned int) vl->fc_seq_gen,
5459 GNUNET_i2s (&vl->target),
5460 (unsigned long long) vl->incoming_fc_window_size,
5461 (unsigned long) rtt_average.rel_value_us,
5462 vl->sync_ready);
5464 vl->last_fc_transmission = monotime;
5465 fc->sync_ready = vl->sync_ready;
5467 fc->seq = htonl (vl->fc_seq_gen++);
5468 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5471 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5472 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5473 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5475 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5476 {
5479 "FC retransmission to %s failed, will retry in %s\n",
5480 GNUNET_i2s (&vl->target),
5483 }
5484 else
5485 {
5486 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5487 vl->last_fc_rtt = rtt;
5488 }
5489 if (NULL != vl->fc_retransmit_task)
5492 {
5494 vl->fc_retransmit_count = 0;
5495 }
5496 vl->fc_retransmit_task =
5498 vl->fc_retransmit_count++;
5499 GNUNET_free (fc);
5500}
5501
5502
5519static void
5521{
5522 struct Neighbour *n = vl->n;
5523 struct DistanceVector *dv = vl->dv;
5524 struct GNUNET_TIME_Absolute now;
5525 struct VirtualLink *vl_next_hop;
5526 int elig;
5527
5529 "check_vl_transmission to target %s\n",
5530 GNUNET_i2s (&vl->target));
5531 /* Check that we have an eligible pending message!
5532 (cheaper than having #transmit_on_queue() find out!) */
5533 elig = GNUNET_NO;
5534 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5535 pm = pm->next_vl)
5536 {
5538 "check_vl_transmission loop\n");
5539 if (NULL != pm->qe)
5540 continue; /* not eligible, is in a queue! */
5541 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5543 {
5545 "Stalled message %" PRIu64
5546 " transmission on VL %s due to flow control: %llu < %llu\n",
5547 pm->logging_uuid,
5548 GNUNET_i2s (&vl->target),
5549 (unsigned long long) vl->outbound_fc_window_size,
5550 (unsigned long long) (pm->bytes_msg
5553 return; /* We have a message, but flow control says "nope" */
5554 }
5556 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5557 GNUNET_i2s (&vl->target));
5558 /* Notify queues at direct neighbours that we are interested */
5559 now = GNUNET_TIME_absolute_get ();
5560 if (NULL != n)
5561 {
5562 for (struct Queue *queue = n->queue_head; NULL != queue;
5563 queue = queue->next_neighbour)
5564 {
5565 if ((GNUNET_YES == queue->idle) &&
5566 (queue->validated_until.abs_value_us > now.abs_value_us))
5567 {
5569 "Direct neighbour %s not stalled\n",
5570 GNUNET_i2s (&n->pid));
5572 queue,
5574 elig = GNUNET_YES;
5575 }
5576 else
5578 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5579 queue->qid,
5580 queue->idle);
5581 }
5582 }
5583 /* Notify queues via DV that we are interested */
5584 if (NULL != dv)
5585 {
5586 /* Do DV with lower scheduler priority, which effectively means that
5587 IF a neighbour exists and is available, we prefer it. */
5588 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5589 pos = pos->next_dv)
5590 {
5591 struct Neighbour *nh_iter = pos->next_hop;
5592
5593
5594 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5595 continue; /* skip this one: path not validated */
5596 else
5597 {
5598 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5599 GNUNET_assert (NULL != vl_next_hop);
5600 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5601 vl_next_hop->outbound_fc_window_size)
5602 {
5604 "Stalled message %" PRIu64
5605 " transmission on next hop %s due to flow control: %llu < %llu\n",
5606 pm->logging_uuid,
5607 GNUNET_i2s (&vl_next_hop->target),
5608 (unsigned long
5609 long) vl_next_hop->outbound_fc_window_size,
5610 (unsigned long long) (pm->bytes_msg
5611 + vl_next_hop->
5612 outbound_fc_window_size_used));
5613 consider_sending_fc (vl_next_hop);
5614 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5615 }
5616 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5617 queue = queue->next_neighbour)
5618 if ((GNUNET_YES == queue->idle) &&
5619 (queue->validated_until.abs_value_us > now.abs_value_us))
5620 {
5622 "Next hop neighbour %s not stalled\n",
5623 GNUNET_i2s (&nh_iter->pid));
5625 queue,
5627 elig = GNUNET_YES;
5628 }
5629 else
5631 "DV Queue QID: %u (%u) busy or invalid\n",
5632 queue->qid,
5633 queue->idle);
5634 }
5635 }
5636 }
5637 if (GNUNET_YES == elig)
5639 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5640 pm->logging_uuid,
5641 pm->bytes_msg,
5642 GNUNET_i2s (&vl->target),
5643 (unsigned long long) vl->outbound_fc_window_size,
5644 (unsigned long long) (pm->bytes_msg
5646 break;
5647 }
5648}
5649
5650
5657static void
5658handle_client_send (void *cls, const struct OutboundMessage *obm)
5659{
5660 struct TransportClient *tc = cls;
5661 struct PendingMessage *pm;
5662 const struct GNUNET_MessageHeader *obmm;
5663 uint32_t bytes_msg;
5664 struct VirtualLink *vl;
5666
5667 GNUNET_assert (CT_CORE == tc->type);
5668 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5669 bytes_msg = ntohs (obmm->size);
5670 pp = ntohl (obm->priority);
5671 vl = lookup_virtual_link (&obm->peer);
5672 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5673 {
5675 "Don't have %s as a neighbour (anymore).\n",
5676 GNUNET_i2s (&obm->peer));
5677 /* Failure: don't have this peer as a neighbour (anymore).
5678 Might have gone down asynchronously, so this is NOT
5679 a protocol violation by CORE. Still count the event,
5680 as this should be rare. */
5683 "# messages dropped (neighbour unknown)",
5684 1,
5685 GNUNET_NO);
5686 return;
5687 }
5688
5689 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5691 "1 created pm %p storing vl %p\n",
5692 pm,
5693 vl);
5694 pm->logging_uuid = logging_uuid_gen++;
5695 pm->prefs = pp;
5696 pm->client = tc;
5697 pm->vl = vl;
5698 pm->bytes_msg = bytes_msg;
5699 memcpy (&pm[1], obmm, bytes_msg);
5701 "Sending message of type %u with %u bytes as <%" PRIu64
5702 "> to %s\n",
5703 ntohs (obmm->type),
5704 bytes_msg,
5705 pm->logging_uuid,
5706 GNUNET_i2s (&obm->peer));
5708 tc->details.core.pending_msg_head,
5709 tc->details.core.pending_msg_tail,
5710 pm);
5712 vl->pending_msg_head,
5713 vl->pending_msg_tail,
5714 pm);
5717}
5718
5719
5729static void
5731 void *cls,
5733{
5734 struct Neighbour *n;
5735 struct VirtualLink *vl;
5736 struct TransportClient *tc = cls;
5737 const struct GNUNET_MessageHeader *inbox =
5738 (const struct GNUNET_MessageHeader *) &cb[1];
5739 uint16_t isize = ntohs (inbox->size);
5740 const char *is = ((const char *) &cb[1]) + isize;
5741 size_t slen = strlen (is) + 1;
5742 char
5743 mbuf[slen + isize
5744 + sizeof(struct
5748
5749 /* 0-termination of 'is' was checked already in
5750 #check_communicator_backchannel() */
5752 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5753 GNUNET_i2s (&cb->pid),
5754 is,
5755 ntohs (inbox->type),
5756 ntohs (inbox->size));
5757 /* encapsulate and encrypt message */
5758 be->header.type =
5760 be->header.size = htons (sizeof(mbuf));
5761 memcpy (&be[1], inbox, isize);
5762 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5763 + isize],
5764 is,
5765 strlen (is) + 1);
5766 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5767 vl = lookup_virtual_link (&cb->pid);
5768 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5769 {
5771 }
5772 else
5773 {
5774 /* Use route via neighbour */
5775 n = lookup_neighbour (&cb->pid);
5776 if (NULL != n)
5778 n,
5779 &be->header,
5780 RMO_NONE);
5781 }
5783}
5784
5785
5793static int
5795 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5796{
5797 struct TransportClient *tc = cls;
5798
5799 if (CT_COMMUNICATOR != tc->type)
5800 {
5801 GNUNET_break (0);
5802 return GNUNET_SYSERR;
5803 }
5805 return GNUNET_OK;
5806}
5807
5808
5814static void
5815store_pi (void *cls);
5816
5817
5822{
5823
5828
5833
5834
5839};
5840
5841
5842static void
5843shc_cont (void *cls, int success)
5844{
5845 struct PilsAddressSignContext *pc = cls;
5846
5847 GNUNET_assert (NULL == pc->req);
5848 if (GNUNET_OK != success)
5849 {
5851 "Failed to store our address `%s' with peerstore\n",
5852 pc->ale->address);
5853 if (NULL == pc->ale->st)
5854 {
5856 &store_pi,
5857 pc->ale);
5858 }
5859 }
5860 GNUNET_free (pc);
5861}
5862
5863
5867static void
5869 const struct GNUNET_PeerIdentity *pid,
5870 const struct GNUNET_CRYPTO_EddsaSignature *sig)
5871{
5872 struct PilsAddressSignContext *pc = cls;
5873 struct GNUNET_MQ_Envelope *env;
5874 const struct GNUNET_MessageHeader *msg;
5875
5876 pc->req->op = NULL;
5879 pc->req);
5880 GNUNET_free (pc->req);
5881 pc->req = NULL;
5884 pid,
5885 sig,
5886 pc->et);
5889 "store_pi 1\n");
5891 msg,
5892 shc_cont,
5893 pc);
5894 GNUNET_free (env);
5895}
5896
5897
5904static void
5905peerstore_store_own_cb (void *cls, int success)
5906{
5907 struct PilsAddressSignContext *pc = cls;
5908
5909 pc->ale->sc = NULL;
5910 if (GNUNET_YES != success)
5912 "Failed to store our own address `%s' in peerstore!\n",
5913 pc->ale->address);
5914 else
5916 "Successfully stored our own address `%s' in peerstore!\n",
5917 pc->ale->address);
5918 /* refresh period is 1/4 of expiration time, that should be plenty
5919 without being excessive. */
5920 if (NULL == pc->ale->st)
5921 {
5922 pc->ale->st =
5924 GNUNET_TIME_relative_divide (pc->ale->expiration,
5925 4ULL),
5926 &store_pi,
5927 pc->ale);
5928 }
5929
5930 /* Now we have to update our HELLO! */
5932 pc->req = GNUNET_new (struct PilsRequest);
5935 pc->req);
5936 pc->req->op = GNUNET_PILS_sign_hello (pils,
5938 pc->et,
5940 pc);
5941}
5942
5943
5944// This function
5945static void
5947 const struct GNUNET_PeerIdentity *pid,
5948 const struct GNUNET_CRYPTO_EddsaSignature *sig)
5949{
5950 struct PilsAddressSignContext *pc = cls;
5951 char *sig_str;
5952 void *result;
5953 size_t result_size;
5954
5955 pc->req->op = NULL;
5958 pc->req);
5959 GNUNET_free (pc->req);
5960 sig_str = NULL;
5961 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
5962 result_size =
5963 1 + GNUNET_asprintf (
5964 (char **) &result,
5965 "%s;%llu;%u;%s",
5966 sig_str,
5967 (unsigned long long) pc->et.abs_value_us,
5968 (unsigned int) pc->ale->nt,
5969 pc->ale->address);
5970 GNUNET_free (sig_str);
5971
5973 "Build our HELLO URI `%s'\n",
5974 (char*) result);
5975
5976 pc->ale->signed_address = result;
5977 pc->ale->signed_address_len = result_size;
5979
5980 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
5982 "transport",
5983 pid,
5985 result,
5986 result_size,
5987 expiration,
5990 pc);
5991}
5992
5993
6014
6015
6029void
6031 struct AddressListEntry *ale,
6032 struct GNUNET_TIME_Absolute mono_time)
6033{
6034 struct SignedAddress sa;
6035 struct PilsAddressSignContext *pc;
6036
6038 sa.purpose.size = htonl (sizeof(sa));
6039 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6040 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6042 pc->ale = ale;
6043 pc->et = mono_time;
6044 pc->req = GNUNET_new (struct PilsRequest);
6046 &sa.purpose,
6048 pc);
6051 pc->req);
6052}
6053
6054
6060static void
6061store_pi (void *cls)
6062{
6063 struct AddressListEntry *ale = cls;
6064 const char *dash;
6065 char *address_uri;
6066 char *prefix;
6067 unsigned int add_success;
6068
6069 if (NULL == GNUNET_PILS_get_identity (pils))
6070 {
6072 &store_pi,
6073 ale);
6074 return;
6075 }
6077 dash = strchr (ale->address, '-');
6078 GNUNET_assert (NULL != dash);
6079 dash++;
6080 GNUNET_asprintf (&address_uri,
6081 "%s://%s",
6082 prefix,
6083 dash);
6085 ale->st = NULL;
6087 "Storing our address `%s' in peerstore until %s!\n",
6088 ale->address,
6091 address_uri);
6092 if (GNUNET_OK != add_success)
6093 {
6095 "Storing our address `%s' %s\n",
6096 address_uri,
6097 GNUNET_NO == add_success ? "not done" : "failed");
6098 GNUNET_free (address_uri);
6099 return;
6100 }
6101 else
6102 {
6103
6105 "Storing our address `%s'\n",
6106 address_uri);
6107 }
6108 // FIXME hello_mono_time used here?? What about expiration in ale?
6109 pils_sign_address (ale,
6111 // TODO keep track of op and potentially cancel/clean
6112 GNUNET_free (address_uri);
6113}
6114
6115
6116static struct AddressListEntry *
6120 const char *address,
6121 uint32_t aid,
6122 size_t slen)
6123{
6124 struct AddressListEntry *ale;
6125 char *address_without_port;
6126
6127 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6128 ale->tc = tc;
6129 ale->address = (const char *) &ale[1];
6130 ale->expiration = expiration;
6131 ale->aid = aid;
6132 ale->nt = nt;
6133 memcpy (&ale[1], address, slen);
6134 address_without_port = get_address_without_port (ale->address);
6136 "Is this %s a local address (%s)\n",
6137 address_without_port,
6138 ale->address);
6139 if (0 != strcmp ("127.0.0.1", address_without_port))
6140 {
6141 if (NULL != ale->st)
6142 {
6144 }
6145 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6146 }
6147 GNUNET_free (address_without_port);
6148
6149 return ale;
6150}
6151
6152
6153static void
6155{
6156
6158 "Feeding addresses to PILS\n");
6159 pils_feed_task = NULL;
6160
6162 GST_my_hello);
6163}
6164
6165
6172static void
6174 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6175{
6176 struct TransportClient *tc = cls;
6177 struct AddressListEntry *ale;
6178 size_t slen;
6179 char *address;
6180
6181 /* 0-termination of &aam[1] was checked in #check_add_address */
6183 "Communicator added address `%s'!\n",
6184 (const char *) &aam[1]);
6185 slen = ntohs (aam->header.size) - sizeof(*aam);
6186 address = GNUNET_malloc (slen);
6187 memcpy (address, &aam[1], slen);
6188 ale = create_address_entry (tc,
6190 ntohl (aam->nt),
6191 address,
6192 aam->aid,
6193 slen);
6194 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6195 tc->details.communicator.addr_tail,
6196 ale);
6197 {
6198 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6199 (NULL != iter && NULL != iter->next);
6200 iter = iter->next)
6201 {
6202 char *address_uri;
6203 const char *dash = strchr (ale->address, '-');
6205 GNUNET_assert (NULL != dash);
6206 dash++;
6207 GNUNET_asprintf (&address_uri,
6208 "%s://%s",
6209 prefix,
6210 dash);
6213 GNUNET_free (address_uri);
6214 }
6215 if (NULL != pils_feed_task)
6219 NULL);
6220 }
6223}
6224
6225
6232static void
6234 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6235{
6236 struct TransportClient *tc = cls;
6237 struct AddressListEntry *alen;
6238
6239 if (CT_COMMUNICATOR != tc->type)
6240 {
6241 GNUNET_break (0);
6243 return;
6244 }
6245 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6246 NULL != ale;
6247 ale = alen)
6248 {
6249 alen = ale->next;
6250 if (dam->aid != ale->aid)
6251 continue;
6252 GNUNET_assert (ale->tc == tc);
6254 "Communicator deleted address `%s'!\n",
6255 ale->address);
6257 ale->address);
6258 if (NULL != pils_feed_task)
6262 NULL);
6265 return;
6266 }
6268 "Communicator removed address we did not even have.\n");
6270 // GNUNET_SERVICE_client_drop (tc->client);
6271}
6272
6273
6281static void
6283
6284
6292static void
6294{
6295 struct CoreSentContext *ctx = cls;
6296 struct VirtualLink *vl = ctx->vl;
6297
6298 if (NULL == vl)
6299 {
6300 /* lost the link in the meantime, ignore */
6301 GNUNET_free (ctx);
6302 return;
6303 }
6306 vl->incoming_fc_window_size_ram -= ctx->size;
6307 vl->incoming_fc_window_size_used += ctx->isize;
6309 GNUNET_free (ctx);
6310}
6311
6312
6313static void
6315 const struct GNUNET_MessageHeader *mh,
6316 struct CommunicatorMessageContext *cmc,
6317 unsigned int free_cmc)
6318{
6319 uint16_t size = ntohs (mh->size);
6320 int have_core;
6321
6322 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6323 {
6325 "# CORE messages dropped (FC arithmetic overflow)",
6326 1,
6327 GNUNET_NO);
6329 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6330 (unsigned int) ntohs (mh->type),
6331 (unsigned int) ntohs (mh->size));
6332 if (GNUNET_YES == free_cmc)
6334 return;
6335 }
6337 {
6339 "# CORE messages dropped (FC window overflow)",
6340 1,
6341 GNUNET_NO);
6343 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6344 (unsigned int) ntohs (mh->type),
6345 (unsigned int) ntohs (mh->size));
6346 if (GNUNET_YES == free_cmc)
6348 return;
6349 }
6350
6351 /* Forward to all CORE clients */
6352 have_core = GNUNET_NO;
6353 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6354 {
6355 struct GNUNET_MQ_Envelope *env;
6356 struct InboundMessage *im;
6357 struct CoreSentContext *ctx;
6358
6359 if (CT_CORE != tc->type)
6360 continue;
6363 ctx = GNUNET_new (struct CoreSentContext);
6364 ctx->vl = vl;
6365 ctx->size = size;
6366 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6367 have_core = GNUNET_YES;
6370 im->peer = cmc->im.sender;
6371 memcpy (&im[1], mh, size);
6372 GNUNET_MQ_send (tc->mq, env);
6374 }
6375 if (GNUNET_NO == have_core)
6376 {
6378 "Dropped message to CORE: no CORE client connected!\n");
6379 /* Nevertheless, count window as used, as it is from the
6380 perspective of the other peer! */
6382 /* TODO-M1 */
6384 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6385 (unsigned int) ntohs (mh->type),
6386 (unsigned int) ntohs (mh->size));
6387 if (GNUNET_YES == free_cmc)
6389 return;
6390 }
6392 "Delivered message from %s of type %u to CORE recv window %d\n",
6393 GNUNET_i2s (&cmc->im.sender),
6394 ntohs (mh->type),
6396 if (vl->core_recv_window > 0)
6397 {
6398 if (GNUNET_YES == free_cmc)
6400 return;
6401 }
6402 /* Wait with calling #finish_cmc_handling(cmc) until the message
6403 was processed by CORE MQs (for CORE flow control)! */
6404 if (GNUNET_YES == free_cmc)
6406}
6407
6408
6417static void
6419{
6420 struct CommunicatorMessageContext *cmc = cls;
6421 // struct CommunicatorMessageContext *cmc_copy =
6422 // GNUNET_new (struct CommunicatorMessageContext);
6423 struct GNUNET_MessageHeader *mh_copy;
6424 struct RingBufferEntry *rbe;
6425 struct VirtualLink *vl;
6426 uint16_t size = ntohs (mh->size);
6427
6429 "Handling raw message of type %u with %u bytes\n",
6430 (unsigned int) ntohs (mh->type),
6431 (unsigned int) ntohs (mh->size));
6432
6433 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6434 (size < sizeof(struct GNUNET_MessageHeader)))
6435 {
6436 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6437
6438 GNUNET_break (0);
6439 finish_cmc_handling (cmc);
6441 return;
6442 }
6443 vl = lookup_virtual_link (&cmc->im.sender);
6444 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6445 {
6446 /* FIXME: sender is giving us messages for CORE but we don't have
6447 the link up yet! I *suspect* this can happen right now (i.e.
6448 sender has verified us, but we didn't verify sender), but if
6449 we pass this on, CORE would be confused (link down, messages
6450 arrive). We should investigate more if this happens often,
6451 or in a persistent manner, and possibly do "something" about
6452 it. Thus logging as error for now. */
6453
6454 mh_copy = GNUNET_malloc (size);
6455 rbe = GNUNET_new (struct RingBufferEntry);
6456 rbe->cmc = cmc;
6457 /*cmc_copy->tc = cmc->tc;
6458 cmc_copy->im = cmc->im;*/
6459 GNUNET_memcpy (mh_copy, mh, size);
6460
6461 rbe->mh = mh_copy;
6462
6464 {
6465 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6466 GNUNET_free (rbe_old->cmc);
6467 GNUNET_free (rbe_old->mh);
6468 GNUNET_free (rbe_old);
6469 }
6470 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6471 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6472 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6474 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6475 GNUNET_i2s (&cmc->im.sender),
6476 (unsigned int) ntohs (mh->type),
6477 (unsigned int) ntohs (mh_copy->type),
6481 {
6482 ring_buffer_head = 0;
6484 }
6485 else
6487
6489 "%u items stored in ring buffer\n",
6492
6493 /*GNUNET_break_op (0);
6494 GNUNET_STATISTICS_update (GST_stats,
6495 "# CORE messages dropped (virtual link still down)",
6496 1,
6497 GNUNET_NO);
6498
6499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6500 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6501 (unsigned int) ntohs (mh->type),
6502 (unsigned int) ntohs (mh->size));
6503 finish_cmc_handling (cmc);*/
6506 // GNUNET_free (cmc);
6507 return;
6508 }
6510}
6511
6512
6520static int
6522{
6523 uint16_t size = ntohs (fb->header.size);
6524 uint16_t bsize = size - sizeof(*fb);
6525
6526 (void) cls;
6527 if (0 == bsize)
6528 {
6529 GNUNET_break_op (0);
6530 return GNUNET_SYSERR;
6531 }
6532 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6533 {
6534 GNUNET_break_op (0);
6535 return GNUNET_SYSERR;
6536 }
6537 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6538 {
6539 GNUNET_break_op (0);
6540 return GNUNET_SYSERR;
6541 }
6542 return GNUNET_YES;
6543}
6544
6545
6551static void
6553{
6554 struct AcknowledgementCummulator *ac = cls;
6555
6556 ac->task = NULL;
6557 GNUNET_assert (0 == ac->num_acks);
6559 GNUNET_YES ==
6561 GNUNET_free (ac);
6562}
6563
6564
6570static void
6572{
6573 struct Neighbour *n;
6574 struct VirtualLink *vl;
6575 struct AcknowledgementCummulator *ac = cls;
6576 char buf[sizeof(struct TransportReliabilityAckMessage)
6577 + ac->num_acks
6579 struct TransportReliabilityAckMessage *ack =
6580 (struct TransportReliabilityAckMessage *) buf;
6582
6583 ac->task = NULL;
6585 "Sending ACK with %u components to %s\n",
6586 ac->num_acks,
6587 GNUNET_i2s (&ac->target));
6588 GNUNET_assert (0 < ac->num_acks);
6590 ack->header.size =
6591 htons (sizeof(*ack)
6592 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6593 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6594 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6595 for (unsigned int i = 0; i < ac->num_acks; i++)
6596 {
6597 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6600 }
6601 /*route_control_message_without_fc (
6602 &ac->target,
6603 &ack->header,
6604 RMO_DV_ALLOWED);*/
6605 vl = lookup_virtual_link (&ac->target);
6606 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6607 {
6609 vl,
6610 &ack->header,
6612 }
6613 else
6614 {
6615 /* Use route via neighbour */
6616 n = lookup_neighbour (&ac->target);
6617 if (NULL != n)
6619 n,
6620 &ack->header,
6621 RMO_NONE);
6622 }
6623 ac->num_acks = 0;
6626 ac);
6627}
6628
6629
6638static void
6640 const struct AcknowledgementUUIDP *ack_uuid,
6641 struct GNUNET_TIME_Absolute max_delay)
6642{
6643 struct AcknowledgementCummulator *ac;
6644
6646 "Scheduling ACK %s for transmission to %s\n",
6647 GNUNET_uuid2s (&ack_uuid->value),
6648 GNUNET_i2s (pid));
6650 if (NULL == ac)
6651 {
6653 ac->target = *pid;
6654 ac->min_transmission_time = max_delay;
6658 &ac->target,
6659 ac,
6661 }
6662 else
6663 {
6664 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6665 {
6666 /* must run immediately, ack buffer full! */
6668 }
6672 }
6675 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6676 ac->num_acks++;
6679 ac);
6680}
6681
6682
6698
6699
6709static int
6710find_by_message_uuid (void *cls, uint32_t key, void *value)
6711{
6712 struct FindByMessageUuidContext *fc = cls;
6713 struct ReassemblyContext *rc = value;
6714
6715 (void) key;
6716 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6717 {
6718 fc->rc = rc;
6719 return GNUNET_NO;
6720 }
6721 return GNUNET_YES;
6722}
6723
6724
6732static void
6734{
6735 struct CommunicatorMessageContext *cmc = cls;
6736 struct VirtualLink *vl;
6737 struct ReassemblyContext *rc;
6738 const struct GNUNET_MessageHeader *msg;
6739 uint16_t msize;
6740 uint16_t fsize;
6741 uint16_t frag_off;
6742 char *target;
6743 struct GNUNET_TIME_Relative cdelay;
6744 struct FindByMessageUuidContext fc;
6745
6746 vl = lookup_virtual_link (&cmc->im.sender);
6747 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6748 {
6749 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6750
6752 "No virtual link for %s to handle fragment\n",
6753 GNUNET_i2s (&cmc->im.sender));
6754 GNUNET_break (0);
6755 finish_cmc_handling (cmc);
6757 return;
6758 }
6759 if (NULL == vl->reassembly_map)
6760 {
6762 vl->reassembly_heap =
6767 vl);
6768 }
6769 msize = ntohs (fb->msg_size);
6770 fc.message_uuid = fb->msg_uuid;
6771 fc.rc = NULL;
6773 fb->msg_uuid.uuid,
6775 &fc);
6776 fsize = ntohs (fb->header.size) - sizeof(*fb);
6777 if (NULL == (rc = fc.rc))
6778 {
6779 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6780 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6781 rc->msg_uuid = fb->msg_uuid;
6782 rc->virtual_link = vl;
6783 rc->msg_size = msize;
6784 rc->reassembly_timeout =
6788 rc,
6792 vl->reassembly_map,
6793 rc->msg_uuid.uuid,
6794 rc,
6796 target = (char *) &rc[1];
6797 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6798 if (fsize != rc->msg_size)
6799 rc->msg_missing = rc->msg_size;
6800 else
6801 rc->msg_missing = 0;
6803 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6804 PRIu64 "\n",
6805 fsize,
6806 ntohs (fb->frag_off),
6807 msize,
6808 rc->msg_missing,
6809 GNUNET_i2s (&cmc->im.sender),
6810 fb->msg_uuid.uuid);
6811 }
6812 else
6813 {
6814 target = (char *) &rc[1];
6816 "Received fragment at offset %u/%u from %s for message %u\n",
6817 ntohs (fb->frag_off),
6818 msize,
6819 GNUNET_i2s (&cmc->im.sender),
6820 (unsigned int) fb->msg_uuid.uuid);
6821 }
6822 if (msize != rc->msg_size)
6823 {
6824 GNUNET_break (0);
6825 finish_cmc_handling (cmc);
6826 return;
6827 }
6828
6829 /* reassemble */
6830 if (0 == fsize)
6831 {
6832 GNUNET_break (0);
6833 finish_cmc_handling (cmc);
6834 return;
6835 }
6836 frag_off = ntohs (fb->frag_off);
6837 if (frag_off + fsize > msize)
6838 {
6839 /* Fragment (plus fragment size) exceeds message size! */
6840 GNUNET_break_op (0);
6841 finish_cmc_handling (cmc);
6842 return;
6843 }
6844 memcpy (&target[frag_off], &fb[1], fsize);
6845 /* update bitfield and msg_missing */
6846 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6847 {
6848 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6849 {
6850 rc->bitfield[i / 8] |= (1 << (i % 8));
6851 rc->msg_missing--;
6852 }
6853 }
6854
6855 /* Compute cumulative ACK */
6857 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6858 if (0 == rc->msg_missing)
6859 cdelay = GNUNET_TIME_UNIT_ZERO;
6860 cummulative_ack (&cmc->im.sender,
6861 &fb->ack_uuid,
6864 /* is reassembly complete? */
6865 if (0 != rc->msg_missing)
6866 {
6867 finish_cmc_handling (cmc);
6868 return;
6869 }
6870 /* reassembly is complete, verify result */
6871 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6872 if (ntohs (msg->size) != rc->msg_size)
6873 {
6874 GNUNET_break (0);
6876 finish_cmc_handling (cmc);
6877 return;
6878 }
6879 /* successful reassembly */
6881 "Fragment reassembly complete for message %u\n",
6882 (unsigned int) fb->msg_uuid.uuid);
6883 /* FIXME: check that the resulting msg is NOT a
6884 DV Box or Reliability Box, as that is NOT allowed! */
6885 cmc->mh = msg;
6887 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6888 en-route and we forget that we finished this reassembly immediately!
6889 -> keep around until timeout?
6890 -> shorten timeout based on ACK? */
6892}
6893
6894
6902static int
6904 const struct TransportReliabilityBoxMessage *rb)
6905{
6906 const struct GNUNET_MessageHeader *box = (const struct
6907 GNUNET_MessageHeader *) &rb[1];
6908 (void) cls;
6909
6911 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6912 ntohs (rb->header.size),
6913 ntohs (box->type),
6914 ntohs (box->size),
6915 sizeof (struct TransportReliabilityBoxMessage),
6916 sizeof (struct GNUNET_MessageHeader));
6918 return GNUNET_YES;
6919}
6920
6921
6929static void
6931 const struct TransportReliabilityBoxMessage *rb)
6932{
6933 struct CommunicatorMessageContext *cmc = cls;
6934 const struct GNUNET_MessageHeader *inbox =
6935 (const struct GNUNET_MessageHeader *) &rb[1];
6936 struct GNUNET_TIME_Relative rtt;
6937
6939 "Received reliability box from %s with UUID %s of type %u\n",
6940 GNUNET_i2s (&cmc->im.sender),
6942 (unsigned int) ntohs (inbox->type));
6943 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6944 do not really have an RTT for the
6945 * incoming* queue (should we have
6946 the sender add it to the rb message?) */
6948 &cmc->im.sender,
6949 &rb->ack_uuid,
6950 (0 == ntohl (rb->ack_countdown))
6953 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6954 /* continue with inner message */
6955 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6956 reliability box (not allowed!) */
6957 cmc->mh = inbox;
6959}
6960
6961
6970static void
6971update_pd_age (struct PerformanceData *pd, unsigned int age)
6972{
6973 unsigned int sage;
6974
6975 if (age == pd->last_age)
6976 return; /* nothing to do */
6977 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6978 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6979 {
6980 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6981
6982 the->bytes_sent = 0;
6983 the->bytes_received = 0;
6984 }
6985 pd->last_age = age;
6986}
6987
6988
6997static void
6999 struct GNUNET_TIME_Relative rtt,
7000 uint16_t bytes_transmitted_ok)
7001{
7002 uint64_t nval = rtt.rel_value_us;
7003 uint64_t oval = pd->aged_rtt.rel_value_us;
7004 unsigned int age = get_age ();
7005 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7006
7007 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7008 pd->aged_rtt = rtt;
7009 else
7010 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7011 update_pd_age (pd, age);
7012 the->bytes_received += bytes_transmitted_ok;
7013}
7014
7015
7023static void
7025 struct GNUNET_TIME_Relative rtt,
7026 uint16_t bytes_transmitted_ok)
7027{
7028 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7029}
7030
7031
7039static void
7041 struct GNUNET_TIME_Relative rtt,
7042 uint16_t bytes_transmitted_ok)
7043{
7044 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7045}
7046
7047
7055static void
7057{
7058 struct PendingMessage *pos;
7059
7061 "Complete transmission of message %" PRIu64 " %u\n",
7062 pm->logging_uuid,
7063 pm->pmt);
7064 switch (pm->pmt)
7065 {
7066 case PMT_CORE:
7068 /* Full message sent, we are done */
7070 return;
7071
7072 case PMT_FRAGMENT_BOX:
7073 /* Fragment sent over reliable channel */
7074 pos = pm->frag_parent;
7078 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7079 (unsigned long) pos->frag_off,
7080 (unsigned long) pos->bytes_msg,
7081 pos->pmt,
7082 NULL == pos->frag_parent ? 1 : 0);
7083 /* check if subtree is done */
7084 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7085 - sizeof(struct
7087 &&
7088 (NULL != pos->frag_parent))
7089 {
7090 pm = pos;
7091 pos = pm->frag_parent;
7092 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7093 {
7095 return;
7096 }
7097 else if (PMT_DV_BOX == pm->pmt)
7098 {
7100 return;
7101 }
7104 }
7105
7106 /* Was this the last applicable fragment? */
7107 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7108 pos->pmt) &&
7109 (pos->frag_off == pos->bytes_msg))
7111 return;
7112
7113 case PMT_DV_BOX:
7115 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7116 pm->logging_uuid);
7117 if (NULL != pm->frag_parent)
7118 {
7119 pos = pm->frag_parent;
7121 pos->bpm = NULL;
7123 }
7124 else
7126 return;
7127 }
7128}
7129
7130
7138static void
7140 struct GNUNET_TIME_Relative ack_delay)
7141{
7142 struct GNUNET_TIME_Relative delay;
7143
7145 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7146 if (NULL != pa->queue && 1 == pa->num_send)
7148 if (NULL != pa->dvh && 1 == pa->num_send)
7149 update_dvh_performance (pa->dvh, delay, pa->message_size);
7150 if (NULL != pa->pm)
7153}
7154
7155
7163static int
7165 const struct TransportReliabilityAckMessage *ra)
7166{
7167 unsigned int n_acks;
7168
7169 (void) cls;
7170 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7171 / sizeof(struct TransportCummulativeAckPayloadP);
7172 if (0 == n_acks)
7173 {
7174 GNUNET_break_op (0);
7175 return GNUNET_SYSERR;
7176 }
7177 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7178 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7179 {
7180 GNUNET_break_op (0);
7181 return GNUNET_SYSERR;
7182 }
7183 return GNUNET_OK;
7184}
7185
7186
7194static void
7196 const struct TransportReliabilityAckMessage *ra)
7197{
7198 struct CommunicatorMessageContext *cmc = cls;
7199 const struct TransportCummulativeAckPayloadP *ack;
7200 unsigned int n_acks;
7201 uint32_t ack_counter;
7202
7203 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7204 / sizeof(struct TransportCummulativeAckPayloadP);
7205 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7206 for (unsigned int i = 0; i < n_acks; i++)
7207 {
7208 struct PendingAcknowledgement *pa =
7210 if (NULL == pa)
7211 {
7213 "Received ACK from %s with UUID %s which is unknown to us!\n",
7214 GNUNET_i2s (&cmc->im.sender),
7215 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7217 GST_stats,
7218 "# FRAGMENT_ACKS dropped, no matching pending message",
7219 1,
7220 GNUNET_NO);
7221 continue;
7222 }
7224 "Received ACK from %s with UUID %s\n",
7225 GNUNET_i2s (&cmc->im.sender),
7226 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7227 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7228 }
7229
7230 ack_counter = htonl (ra->ack_counter);
7231 (void) ack_counter; /* silence compiler warning for now */
7232 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7233 // (DV and/or Neighbour?)
7234 finish_cmc_handling (cmc);
7235}
7236
7237
7245static int
7247 void *cls,
7249{
7250 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7251 const struct GNUNET_MessageHeader *inbox =
7252 (const struct GNUNET_MessageHeader *) &be[1];
7253 const char *is;
7254 uint16_t isize;
7255
7256 (void) cls;
7257 if (ntohs (inbox->size) >= size)
7258 {
7259 GNUNET_break_op (0);
7260 return GNUNET_SYSERR;
7261 }
7262 isize = ntohs (inbox->size);
7263 is = ((const char *) inbox) + isize;
7264 size -= isize;
7265 if ('\0' != is[size - 1])
7266 {
7267 GNUNET_break_op (0);
7268 return GNUNET_SYSERR;
7269 }
7270 return GNUNET_YES;
7271}
7272
7273
7282static void
7284 void *cls,
7286{
7287 const struct GNUNET_PeerIdentity *my_identity;
7288 struct CommunicatorMessageContext *cmc = cls;
7290 struct GNUNET_MQ_Envelope *env;
7291 struct TransportClient *tc;
7292 const struct GNUNET_MessageHeader *inbox =
7293 (const struct GNUNET_MessageHeader *) &be[1];
7294 uint16_t isize = ntohs (inbox->size);
7295 const char *target_communicator = ((const char *) inbox) + isize;
7296 char *sender;
7297 char *self;
7298
7301
7302 GNUNET_asprintf (&sender,
7303 "%s",
7304 GNUNET_i2s (&cmc->im.sender));
7305 GNUNET_asprintf (&self,
7306 "%s",
7308
7309 /* Find client providing this communicator */
7310 for (tc = clients_head; NULL != tc; tc = tc->next)
7311 if ((CT_COMMUNICATOR == tc->type) &&
7312 (0 ==
7313 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7314 break;
7315 if (NULL == tc)
7316 {
7317 char *stastr;
7318
7320 &stastr,
7321 "# Backchannel message dropped: target communicator `%s' unknown",
7322 target_communicator);
7324 GNUNET_free (stastr);
7325 finish_cmc_handling (cmc);
7326 return;
7327 }
7328 /* Finally, deliver backchannel message to communicator */
7330 "Delivering backchannel message from %s to %s of type %u to %s\n",
7331 sender,
7332 self,
7333 ntohs (inbox->type),
7334 target_communicator);
7336 cbi,
7337 isize,
7339 cbi->pid = cmc->im.sender;
7340 memcpy (&cbi[1], inbox, isize);
7341 GNUNET_MQ_send (tc->mq, env);
7342 finish_cmc_handling (cmc);
7343}
7344
7345
7355static void
7357{
7358 struct DistanceVector *dv = cls;
7359 struct DistanceVectorHop *pos;
7360
7361 dv->timeout_task = NULL;
7362 while (NULL != (pos = dv->dv_head))
7363 {
7364 GNUNET_assert (dv == pos->dv);
7366 break;
7368 }
7369 if (NULL == pos)
7370 {
7371 free_dv_route (dv);
7372 return;
7373 }
7374 dv->timeout_task =
7376}
7377
7378
7379static void
7381{
7382
7383 const struct GNUNET_PeerIdentity target = vl->target;
7384
7385
7387 {
7388 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7389 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7390 0;
7391 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7394 struct CommunicatorMessageContext *cmc;
7395 struct RingBufferEntry *rbe;
7396 struct GNUNET_MessageHeader *mh;
7397
7399 "Sending from ring buffer, which has %u items\n",
7400 head);
7401
7402 ring_buffer_head = 0;
7403 for (unsigned int i = 0; i < head; i++)
7404 {
7405 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7406 cmc = rbe->cmc;
7407 mh = rbe->mh;
7408
7409 im = cmc->im;
7410 // mh = cmc->mh;
7412 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7413 mh->type,
7414 GNUNET_i2s (&im.sender),
7415 GNUNET_i2s2 (&target),
7416 (i + tail) % RING_BUFFER_SIZE);
7417 if (0 == GNUNET_memcmp (&target, &im.sender))
7418 {
7420 "Finish handling message of type %u and size %u\n",
7421 (unsigned int) ntohs (mh->type),
7422 (unsigned int) ntohs (mh->size));
7424 GNUNET_free (mh);
7425 GNUNET_free (rbe->cmc);
7426 GNUNET_free (rbe);
7427 }
7428 else
7429 {
7430 ring_buffer_copy[ring_buffer_head] = rbe;
7432 }
7433 }
7434
7437 {
7439 }
7440
7441 for (unsigned int i = 0; i < ring_buffer_head; i++)
7442 {
7443 ring_buffer[i] = ring_buffer_copy[i];
7445 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7446 i,
7447 ring_buffer_copy[i]->mh->type);
7449 "ring_buffer[i]->mh->type for i %u %u\n",
7450 i,
7451 ring_buffer[i]->mh->type);
7452 }
7453
7455 "%u items still in ring buffer\n",
7457 }
7458
7460 {
7461 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7462 struct PendingMessage *pm;
7463 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7465 0;
7466 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7469
7471 "Sending from ring buffer dv, which has %u items\n",
7472 head);
7473
7475 for (unsigned int i = 0; i < head; i++)
7476 {
7477 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7478
7480 "Sending to ring buffer target %s using vl target %s\n",
7481 GNUNET_i2s (&pm->target),
7482 GNUNET_i2s2 (&target));
7483 if (0 == GNUNET_memcmp (&target, &pm->target))
7484 {
7486 "Adding PendingMessage to vl, checking transmission.\n");
7487 pm->vl = vl;
7491 pm);
7492
7494 }
7495 else
7496 {
7497 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7499 }
7500 }
7501
7503 {
7505 }
7506
7507 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7508 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7509
7511 "%u items still in ring buffer dv.\n",
7513
7514 }
7515}
7516
7517
7525static void
7527{
7528 struct DistanceVector *dv = hop->dv;
7529 struct VirtualLink *vl;
7530
7531 vl = lookup_virtual_link (&dv->target);
7532 if (NULL == vl)
7533 {
7534
7535 vl = GNUNET_new (struct VirtualLink);
7537 "Creating new virtual link %p to %s using DV!\n",
7538 vl,
7539 GNUNET_i2s (&dv->target));
7540 vl->burst_addr = NULL;
7541 vl->confirmed = GNUNET_YES;
7542 vl->message_uuid_ctr =
7543 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
7544 vl->target = dv->target;
7550 links,
7551 &vl->target,
7552 vl,
7554 vl->dv = dv;
7555 dv->vl = vl;
7556 vl->visibility_task =
7559 /* We lacked a confirmed connection to the target
7560 before, so tell CORE about it (finally!) */
7563 }
7564 else
7565 {
7566 /* Link was already up, remember dv is also now available and we are done */
7567 vl->dv = dv;
7568 dv->vl = vl;
7569 if (GNUNET_NO == vl->confirmed)
7570 {
7571 vl->confirmed = GNUNET_YES;
7572 vl->visibility_task =
7575 /* We lacked a confirmed connection to the target
7576 before, so tell CORE about it (finally!) */
7579 }
7580 else
7582 "Virtual link to %s could now also use DV!\n",
7583 GNUNET_i2s (&dv->target));
7584 }
7585}
7586
7587
7613static int
7615 unsigned int path_len,
7616 struct GNUNET_TIME_Relative network_latency,
7617 struct GNUNET_TIME_Absolute path_valid_until)
7618{
7619 const struct GNUNET_PeerIdentity *my_identity;
7620 struct DistanceVectorHop *hop;
7621 struct DistanceVector *dv;
7622 struct Neighbour *next_hop;
7623 unsigned int shorter_distance;
7624
7625 if (path_len < 3)
7626 {
7627 /* what a boring path! not allowed! */
7628 GNUNET_break (0);
7629 return GNUNET_SYSERR;
7630 }
7631
7634
7635 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
7636 next_hop = lookup_neighbour (&path[1]);
7637 if (NULL == next_hop)
7638 {
7639 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7640 GNUNET_break (0);
7641 return GNUNET_SYSERR;
7642 }
7643 for (unsigned int i = 2; i < path_len; i++)
7644 {
7645 struct Neighbour *n = lookup_neighbour (&path[i]);
7646 struct GNUNET_TIME_Absolute q_timeout;
7647
7648 if (NULL != n)
7649 {
7650 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7651 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7652 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7654 "remaining %lu to %s\n",
7655 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7656 .rel_value_us,
7657 GNUNET_i2s (&n->pid));
7658 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7659 {
7660 /* Useless path: we have a direct active connection to some hop
7661 in the middle of the path, so this one is not even
7662 terribly useful for redundancy */
7664 "Path of %u hops useless: directly link to hop %u (%s)\n",
7665 path_len,
7666 i,
7667 GNUNET_i2s (&path[i]));
7669 "# Useless DV path ignored: hop is neighbour",
7670 1,
7671 GNUNET_NO);
7672 return GNUNET_SYSERR;
7673 }
7674 }
7675 }
7676 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7677 if (NULL == dv)
7678 {
7679 dv = GNUNET_new (struct DistanceVector);
7680 dv->target = path[path_len - 1];
7683 dv);
7686 dv_routes,
7687 &dv->target,
7688 dv,
7690 }
7691 /* Check if we have this path already! */
7692 shorter_distance = 0;
7693 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7694 pos = pos->next_dv)
7695 {
7696 if (pos->distance < path_len - 3)
7697 shorter_distance++;
7698 /* Note that the distances in 'pos' excludes us (path[0]),
7699 the next_hop (path[1]) and the target so we need to subtract three
7700 and check next_hop explicitly */
7701 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7702 {
7703 int match = GNUNET_YES;
7704
7705 for (unsigned int i = 0; i < pos->distance; i++)
7706 {
7707 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7708 {
7709 match = GNUNET_NO;
7710 break;
7711 }
7712 }
7713 if (GNUNET_YES == match)
7714 {
7715 struct GNUNET_TIME_Relative last_timeout;
7716
7717 /* Re-discovered known path, update timeout */
7719 "# Known DV path refreshed",
7720 1,
7721 GNUNET_NO);
7722 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7723 pos->timeout =
7725 pos->path_valid_until =
7726 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7727 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7728 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7729 if (0 <
7732 if (last_timeout.rel_value_us <
7735 .rel_value_us)
7736 {
7737 /* Some peer send DV learn messages too often, we are learning
7738 the same path faster than it would be useful; do not forward! */
7740 "Rediscovered path too quickly, not forwarding further\n")
7741 ;
7742 return GNUNET_NO;
7743 }
7745 "Refreshed known path to %s valid until %s, forwarding further\n",
7746 GNUNET_i2s (&dv->target),
7748 pos->path_valid_until));
7749 return GNUNET_YES;
7750 }
7751 }
7752 }
7753 /* Count how many shorter paths we have (incl. direct
7754 neighbours) before simply giving up on this one! */
7755 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7756 {
7757 /* We have a shorter path already! */
7759 "Have many shorter DV paths %s, not forwarding further\n",
7760 GNUNET_i2s (&dv->target));
7761 return GNUNET_NO;
7762 }
7763 /* create new DV path entry */
7765 "Discovered new DV path to %s valid until %s\n",
7766 GNUNET_i2s (&dv->target),
7767 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7768 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7769 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7770 hop->next_hop = next_hop;
7771 hop->dv = dv;
7772 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7773 memcpy (&hop[1],
7774 &path[2],
7775 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7777 hop->path_valid_until = path_valid_until;
7778 hop->distance = path_len - 3;
7779 hop->pd.aged_rtt = network_latency;
7780 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7782 next_hop->dv_head,
7783 next_hop->dv_tail,
7784 hop);
7785 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7787 return GNUNET_YES;
7788}
7789
7790
7798static int
7799check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7800{
7801 const struct GNUNET_PeerIdentity *my_identity;
7802 uint16_t size = ntohs (dvl->header.size);
7803 uint16_t num_hops = ntohs (dvl->num_hops);
7804 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7805
7806 (void) cls;
7807 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7808 {
7809 GNUNET_break_op (0);
7810 return GNUNET_SYSERR;
7811 }
7812 if (num_hops > MAX_DV_HOPS_ALLOWED)
7813 {
7814 GNUNET_break_op (0);
7815 return GNUNET_SYSERR;
7816 }
7817
7820
7821 for (unsigned int i = 0; i < num_hops; i++)
7822 {
7823 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7824 {
7825 GNUNET_break_op (0);
7826 return GNUNET_SYSERR;
7827 }
7828 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
7829 {
7830 GNUNET_break_op (0);
7831 return GNUNET_SYSERR;
7832 }
7833 }
7834 return GNUNET_YES;
7835}
7836
7837
7846
7847
7848static void
7849sign_dhp_cp (void *cls,
7850 const struct GNUNET_PeerIdentity *pid,
7851 const struct GNUNET_CRYPTO_EddsaSignature *sig)
7852{
7853 struct SignDhpCls *sign_dhp_cls = cls;
7854 struct VirtualLink *vl;
7855 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
7856 uint16_t nhops = sign_dhp_cls->nhops;
7857 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
7858 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
7859 struct Neighbour *n;
7860
7861 sign_dhp_cls->pr->op = NULL;
7864 sign_dhp_cls->pr);
7865 GNUNET_free (sign_dhp_cls->pr);
7866 dhops[nhops].hop_sig = *sig;
7867
7868 /*route_control_message_without_fc (next_hop,
7869 &fwd->header,
7870 RMO_UNCONFIRMED_ALLOWED);*/
7871 vl = lookup_virtual_link (next_hop);
7872 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7873 {
7875 &fwd->header,
7877 }
7878 else
7879 {
7880 /* Use route via neighbour */
7881 n = lookup_neighbour (next_hop);
7882 if (NULL != n)
7884 n,
7885 &fwd->header,
7887 }
7888 GNUNET_free (sign_dhp_cls);
7889}
7890
7891
7903static void
7905 const struct TransportDVLearnMessage *msg,
7906 uint16_t bi_history,
7907 uint16_t nhops,
7908 const struct DVPathEntryP *hops,
7909 struct GNUNET_TIME_Absolute in_time)
7910{
7911 struct DVPathEntryP *dhops;
7912 char buf[sizeof(struct TransportDVLearnMessage)
7913 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7914 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7915 struct GNUNET_TIME_Relative nnd;
7916 const struct GNUNET_PeerIdentity *my_identity;
7917
7918 /* compute message for forwarding */
7920 "Forwarding DV learn message originating from %s to %s\n",
7921 GNUNET_i2s (&msg->initiator),
7922 GNUNET_i2s2 (next_hop));
7925 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7926 + (nhops + 1) * sizeof(struct DVPathEntryP));
7927 fwd->num_hops = htons (nhops + 1);
7928 fwd->bidirectional = htons (bi_history);
7931 msg->non_network_delay));
7933 fwd->init_sig = msg->init_sig;
7934 fwd->initiator = msg->initiator;
7935 fwd->challenge = msg->challenge;
7936 fwd->monotonic_time = msg->monotonic_time;
7937
7940
7941 dhops = (struct DVPathEntryP *) &fwd[1];
7942 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7943 dhops[nhops].hop = *my_identity;
7944 {
7945 struct DvHopPS dhp = {
7947 .purpose.size = htonl (sizeof(dhp)),
7948 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7949 .succ = *next_hop,
7950 .challenge = msg->challenge
7951 };
7952 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
7953 sign_dhp_cls->dhops = dhops;
7954 sign_dhp_cls->nhops = nhops;
7955 sign_dhp_cls->next_hop = next_hop;
7956 sign_dhp_cls->fwd = fwd;
7957 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
7960 sign_dhp_cls->pr);
7961 sign_dhp_cls->pr->op =
7963 &dhp.purpose,
7965 sign_dhp_cls);
7966 }
7967}
7968
7969
7979static int
7981 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
7982 const struct GNUNET_PeerIdentity *init,
7983 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
7984 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
7985{
7986 struct DvInitPS ip = { .purpose.purpose = htonl (
7988 .purpose.size = htonl (sizeof(ip)),
7989 .monotonic_time = sender_monotonic_time,
7990 .challenge = *challenge };
7991
7992 if (
7993 GNUNET_OK !=
7995 &ip,
7996 init_sig,
7997 &init->public_key))
7998 {
7999 GNUNET_break_op (0);
8000 return GNUNET_SYSERR;
8001 }
8002 return GNUNET_OK;
8003}
8004
8005
8010{
8015
8019 const struct DVPathEntryP *hops;
8020
8025
8030
8034 unsigned int num_eligible;
8035
8039 unsigned int num_selections;
8040
8044 uint16_t nhops;
8045
8049 uint16_t bi_history;
8050};
8051
8052
8061static int
8063 const struct GNUNET_PeerIdentity *pid,
8064 void *value)
8065{
8066 struct NeighbourSelectionContext *nsc = cls;
8067
8068 (void) value;
8069 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8070 return GNUNET_YES; /* skip initiator */
8071 for (unsigned int i = 0; i < nsc->nhops; i++)
8072 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8073 return GNUNET_YES;
8074 /* skip peers on path */
8075 nsc->num_eligible++;
8076 return GNUNET_YES;
8077}
8078
8079
8090static int
8092 const struct GNUNET_PeerIdentity *pid,
8093 void *value)
8094{
8095 struct NeighbourSelectionContext *nsc = cls;
8096
8098 "transmission %s\n",
8099 GNUNET_i2s (pid));
8100 (void) value;
8101 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8102 return GNUNET_YES; /* skip initiator */
8103 for (unsigned int i = 0; i < nsc->nhops; i++)
8104 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8105 return GNUNET_YES;
8106 /* skip peers on path */
8107 for (unsigned int i = 0; i < nsc->num_selections; i++)
8108 {
8109 if (nsc->selections[i] == nsc->num_eligible)
8110 {
8112 nsc->dvl,
8113 nsc->bi_history,
8114 nsc->nhops,
8115 nsc->hops,
8116 nsc->in_time);
8117 break;
8118 }
8119 }
8120 nsc->num_eligible++;
8121 return GNUNET_YES;
8122}
8123
8124
8168static unsigned int
8169calculate_fork_degree (unsigned int hops_taken,
8170 unsigned int neighbour_count,
8171 unsigned int eligible_count)
8172{
8173 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8174 double eligible_ratio =
8175 ((double) eligible_count) / ((double) neighbour_count);
8176 double boost_factor = eligible_ratio * eligible_ratio;
8177 unsigned int rnd;
8178 double left;
8179
8180 if (hops_taken >= 64)
8181 {
8182 GNUNET_break (0);
8183 return 0; /* precaution given bitshift below */
8184 }
8185 for (unsigned int i = 1; i < hops_taken; i++)
8186 {
8187 /* For each hop, subtract the expected number of targets
8188 reached at distance d (so what remains divided by 2^d) */
8189 target_total -= (target_total * boost_factor / (1LLU << i));
8190 }
8191 rnd =
8192 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8193 /* round up or down probabilistically depending on how close we were
8194 when floor()ing to rnd */
8195 left = target_total - (double) rnd;
8196 if (UINT32_MAX * left >
8197 GNUNET_CRYPTO_random_u64 (UINT32_MAX))
8198 rnd++; /* round up */
8200 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8201 hops_taken,
8202 rnd,
8203 eligible_count,
8204 neighbour_count);
8205 return rnd;
8206}
8207
8208
8215static void
8216neighbour_store_dvmono_cb (void *cls, int success)
8217{
8218 struct Neighbour *n = cls;
8219
8220 n->sc = NULL;
8221 if (GNUNET_YES != success)
8223 "Failed to store other peer's monotonic time in peerstore!\n");
8224}
8225
8226
8227static struct GNUNET_TIME_Relative
8229{
8230 struct GNUNET_TIME_Relative host_latency_sum;
8231 struct GNUNET_TIME_Relative latency;
8232 struct GNUNET_TIME_Relative network_latency;
8233 uint16_t nhops = ntohs (dvl->num_hops);;
8234
8235 /* We initiated this, learn the forward path! */
8236 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8237
8238 // Need also something to lookup initiation time
8239 // to compute RTT! -> add RTT argument here?
8241 dvl->monotonic_time));
8242 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8243 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8244 // (based on dvl->challenge, we can identify time of origin!)
8245
8246 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8247 /* assumption: latency on all links is the same */
8248 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8249
8250 return network_latency;
8251}
8252
8253
8261static void
8262handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8263{
8264 struct CommunicatorMessageContext *cmc = cls;
8266 int bi_hop;
8267 uint16_t nhops;
8268 uint16_t bi_history;
8269 const struct DVPathEntryP *hops;
8270 int do_fwd;
8271 int did_initiator;
8272 struct GNUNET_TIME_Absolute in_time;
8273 struct Neighbour *n;
8274 const struct GNUNET_PeerIdentity *my_identity;
8275
8276 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8277 bi_history = ntohs (dvl->bidirectional);
8278 hops = (const struct DVPathEntryP *) &dvl[1];
8279 if (0 == nhops)
8280 {
8281 /* sanity check */
8282 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8283 {
8284 GNUNET_break (0);
8285 finish_cmc_handling (cmc);
8286 return;
8287 }
8288 }
8289 else
8290 {
8292 "handle dv learn message last hop %s\n",
8293 GNUNET_i2s (&hops[nhops - 1].hop));
8294 /* sanity check */
8295 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8296 {
8297 GNUNET_break (0);
8298 finish_cmc_handling (cmc);
8299 return;
8300 }
8301 }
8302
8304 cc = cmc->tc->details.communicator.cc;
8305 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8306 cc); // FIXME: add bi-directional flag to cc?
8307 in_time = GNUNET_TIME_absolute_get ();
8308
8309 /* continue communicator here, everything else can happen asynchronous! */
8310 finish_cmc_handling (cmc);
8311
8312 n = lookup_neighbour (&dvl->initiator);
8313 if (NULL != n)
8314 {
8315 if ((n->dv_monotime_available == GNUNET_YES) &&
8318 {
8320 "DV learn from %s discarded due to time travel",
8321 GNUNET_i2s (&dvl->initiator));
8323 "# DV learn discarded due to time travel",
8324 1,
8325 GNUNET_NO);
8326 return;
8327 }
8329 &dvl->initiator,
8330 &dvl->challenge,
8331 &dvl->init_sig))
8332 {
8334 "DV learn signature from %s invalid\n",
8335 GNUNET_i2s (&dvl->initiator));
8336 GNUNET_break_op (0);
8337 return;
8338 }
8341 {
8342 if (NULL != n->sc)
8343 {
8345 "store cancel\n");
8347 }
8348 n->sc =
8350 "transport",
8351 &dvl->initiator,
8353 &dvl->monotonic_time,
8354 sizeof(dvl->monotonic_time),
8358 n);
8359 }
8360 }
8361
8364
8365 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8366 If signature verification load too high, implement random drop strategy */
8367 for (unsigned int i = 0; i < nhops; i++)
8368 {
8369 struct DvHopPS dhp = { .purpose.purpose =
8371 .purpose.size = htonl (sizeof(dhp)),
8372 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8373 .succ = (nhops == i + 1) ? *my_identity
8374 : hops[i + 1].hop,
8375 .challenge = dvl->challenge };
8376
8377 if (GNUNET_OK !=
8379 &dhp,
8380 &hops[i].hop_sig,
8381 &hops[i].hop.public_key))
8382 {
8384 "DV learn from %s signature of hop %u invalid\n",
8385 GNUNET_i2s (&dvl->initiator),
8386 i);
8388 "signature of hop %s invalid\n",
8389 GNUNET_i2s (&hops[i].hop));
8391 "pred %s\n",
8392 GNUNET_i2s (&dhp.pred));
8394 "succ %s\n",
8395 GNUNET_i2s (&dhp.succ));
8397 "hash %s\n",
8398 GNUNET_sh2s (&dhp.challenge.value));
8399 GNUNET_break_op (0);
8400 return;
8401 }
8402 }
8403 if (GNUNET_EXTRA_LOGGING > 0)
8404 {
8405 char *path;
8406
8407 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8408 for (unsigned int i = 0; i < nhops; i++)
8409 {
8410 char *tmp;
8411
8412 GNUNET_asprintf (&tmp,
8413 "%s%s%s",
8414 path,
8415 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8416 GNUNET_i2s (&hops[i].hop));
8417 GNUNET_free (path);
8418 path = tmp;
8419 }
8421 "Received DVInit via %s%s%s\n",
8422 path,
8423 bi_hop ? "<->" : "-->",
8425 GNUNET_free (path);
8426 }
8427 do_fwd = GNUNET_YES;
8428 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
8429 {
8430 struct GNUNET_PeerIdentity path[nhops + 1];
8431 struct GNUNET_TIME_Relative network_latency;
8432
8433 /* We initiated this, learn the forward path! */
8434 path[0] = *my_identity;
8435 path[1] = hops[0].hop;
8436
8437 network_latency = get_network_latency (dvl);
8438
8439 for (unsigned int i = 2; i <= nhops; i++)
8440 {
8441 struct GNUNET_TIME_Relative ilat;
8442
8443 /* assumption: linear latency increase per hop */
8444 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8445 path[i] = hops[i - 1].hop;
8447 "Learned path with %u hops to %s with latency %s\n",
8448 i,
8449 GNUNET_i2s (&path[i]),
8451 learn_dv_path (path,
8452 i + 1,
8453 ilat,
8456 }
8457 /* as we initiated, do not forward again (would be circular!) */
8458 do_fwd = GNUNET_NO;
8459 return;
8460 }
8461 if (bi_hop)
8462 {
8463 /* last hop was bi-directional, we could learn something here! */
8464 struct GNUNET_PeerIdentity path[nhops + 2];
8465 struct GNUNET_TIME_Relative ilat;
8466 struct GNUNET_TIME_Relative network_latency;
8467
8468 path[0] = *my_identity;
8469 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8470 for (unsigned int i = 0; i < nhops; i++)
8471 {
8472 int iret;
8473
8474 if (0 == (bi_history & (1 << i)))
8475 break; /* i-th hop not bi-directional, stop learning! */
8476 if (i == nhops - 1)
8477 {
8478 path[i + 2] = dvl->initiator;
8479 }
8480 else
8481 {
8482 path[i + 2] = hops[nhops - i - 2].hop;
8483 }
8484
8486 "Learned inverse path with %u hops to %s\n",
8487 i + 2,
8488 GNUNET_i2s (&path[i + 2]));
8489 network_latency = get_network_latency (dvl);
8490 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8491 iret = learn_dv_path (path,
8492 i + 3,
8493 ilat,
8496 if (GNUNET_SYSERR == iret)
8497 {
8498 /* path invalid or too long to be interesting for US, thus should also
8499 not be interesting to our neighbours, cut path when forwarding to
8500 'i' hops, except of course for the one that goes back to the
8501 initiator */
8503 "# DV learn not forwarded due invalidity of path",
8504 1,
8505 GNUNET_NO);
8506 do_fwd = GNUNET_NO;
8507 break;
8508 }
8509 if ((GNUNET_NO == iret) && (nhops == i + 1))
8510 {
8511 /* we have better paths, and this is the longest target,
8512 so there cannot be anything interesting later */
8514 "# DV learn not forwarded, got better paths",
8515 1,
8516 GNUNET_NO);
8517 do_fwd = GNUNET_NO;
8518 break;
8519 }
8520 }
8521 }
8522 if (MAX_DV_HOPS_ALLOWED == nhops)
8523 {
8524 /* At limit, we're out of here! */
8525 return;
8526 }
8527
8528 /* Forward to initiator, if path non-trivial and possible */
8529 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8530 did_initiator = GNUNET_NO;
8531 if ((1 <= nhops) &&
8532 (GNUNET_YES ==
8534 {
8535 /* send back to origin! */
8537 "Sending DVL back to initiator %s\n",
8538 GNUNET_i2s (&dvl->initiator));
8539 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8540 did_initiator = GNUNET_YES;
8541 }
8542 /* We forward under two conditions: either we still learned something
8543 ourselves (do_fwd), or the path was darn short and thus the initiator is
8544 likely to still be very interested in this (and we did NOT already
8545 send it back to the initiator) */
8546 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8547 (GNUNET_NO == did_initiator)))
8548 {
8549 /* Pick random neighbours that are not yet on the path */
8550 struct NeighbourSelectionContext nsc;
8551 unsigned int n_cnt;
8552
8554 nsc.nhops = nhops;
8555 nsc.dvl = dvl;
8556 nsc.bi_history = bi_history;
8557 nsc.hops = hops;
8558 nsc.in_time = in_time;
8559 nsc.num_eligible = 0;
8562 &nsc);
8563 if (0 == nsc.num_eligible)
8564 return; /* done here, cannot forward to anyone else */
8566 nsc.num_selections =
8569 "Forwarding DVL to %u other peers\n",
8570 nsc.num_selections);
8571 for (unsigned int i = 0; i < nsc.num_selections; i++)
8572 nsc.selections[i] =
8573 (nsc.num_selections == n_cnt)
8574 ? i /* all were selected, avoid collisions by chance */
8575 : GNUNET_CRYPTO_random_u32 (n_cnt);
8576 nsc.num_eligible = 0;
8579 &nsc);
8580 }
8581}
8582
8583
8591static int
8592check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8593{
8594 uint16_t size = ntohs (dvb->header.size);
8595 uint16_t num_hops = ntohs (dvb->num_hops);
8596 const struct GNUNET_PeerIdentity *hops =
8597 (const struct GNUNET_PeerIdentity *) &dvb[1];
8598 const struct GNUNET_PeerIdentity *my_identity;
8599
8600 (void) cls;
8601 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8602 + sizeof(struct GNUNET_MessageHeader))
8603 {
8604 GNUNET_break_op (0);
8605 return GNUNET_SYSERR;
8606 }
8607
8610
8611 /* This peer must not be on the path */
8612 for (unsigned int i = 0; i < num_hops; i++)
8613 if (0 == GNUNET_memcmp (&hops[i], my_identity))
8614 {
8615 GNUNET_break_op (0);
8616 return GNUNET_SYSERR;
8617 }
8618 return GNUNET_YES;
8619}
8620
8621
8634static void
8635forward_dv_box (struct Neighbour *next_hop,
8636 struct TransportDVBoxMessage *hdr,
8637 uint16_t total_hops,
8638 uint16_t num_hops,
8639 const struct GNUNET_PeerIdentity *hops,
8640 const void *enc_payload,
8641 uint16_t enc_payload_size)
8642{
8643 struct VirtualLink *vl = next_hop->vl;
8644 struct PendingMessage *pm;
8645 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8646 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8647 + enc_payload_size;
8648 char *buf;
8649 char msg_buf[msg_size] GNUNET_ALIGN;
8650 struct GNUNET_PeerIdentity *dhops;
8651
8652 hdr->num_hops = htons (num_hops);
8653 hdr->total_hops = htons (total_hops);
8654 hdr->header.size = htons (msg_size);
8655 memcpy (msg_buf, hdr, sizeof(*hdr));
8656 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8658 ;
8659 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8660 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8661
8662 if (GNUNET_YES == ntohs (hdr->without_fc))
8663 {
8665 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8666 enc_payload_size,
8667 GNUNET_i2s (&next_hop->pid),
8668 (unsigned int) num_hops,
8669 (unsigned int) total_hops);
8670 route_via_neighbour (next_hop, (const struct
8671 GNUNET_MessageHeader *) msg_buf,
8673 }
8674 else
8675 {
8676 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8678 "2 created pm %p storing vl %p \n",
8679 pm,
8680 vl);
8681 pm->pmt = PMT_DV_BOX;
8682 pm->vl = vl;
8683 pm->target = next_hop->pid;
8685 pm->logging_uuid = logging_uuid_gen++;
8687 pm->bytes_msg = msg_size;
8688 buf = (char *) &pm[1];
8689 memcpy (buf, msg_buf, msg_size);
8690
8692 "Created pending message %" PRIu64
8693 " for DV Box with next hop %s (%u/%u)\n",
8694 pm->logging_uuid,
8695 GNUNET_i2s (&next_hop->pid),
8696 (unsigned int) num_hops,
8697 (unsigned int) total_hops);
8698
8699 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8700 {
8702 vl->pending_msg_head,
8703 vl->pending_msg_tail,
8704 pm);
8705
8707 }
8708 else
8709 {
8711 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8712
8714 {
8716
8717 GNUNET_free (pm_old);
8718 }
8721 {
8724 }
8725 else
8727
8729 "%u items stored in DV ring buffer\n",
8732 }
8733 }
8734}
8735
8736
8742static void
8744{
8745 if (NULL != b->get)
8746 {
8748 b->get = NULL;
8749 GNUNET_assert (NULL != b->cmc);
8751 b->cmc = NULL;
8752 }
8753 if (NULL != b->task)
8754 {
8756 b->task = NULL;
8757 }
8758 if (NULL != b->sc)
8759 {
8761 "store cancel\n");
8763 b->sc = NULL;
8764 }
8766 "Removing backtalker for %s\n",
8767 GNUNET_i2s (&b->pid));
8769 GNUNET_YES ==
8771 GNUNET_free (b);
8772}
8773
8774
8783static int
8785 const struct GNUNET_PeerIdentity *pid,
8786 void *value)
8787{
8788 struct Backtalker *b = value;
8789
8790 (void) cls;
8791 (void) pid;
8792 free_backtalker (b);
8793 return GNUNET_OK;
8794}
8795
8796
8802static void
8804{
8805 struct Backtalker *b = cls;
8806
8808 "backtalker timeout.\n");
8809 b->task = NULL;
8811 {
8813 return;
8814 }
8815 GNUNET_assert (NULL == b->sc);
8816 free_backtalker (b);
8817}
8818
8819
8828static void
8830 const struct GNUNET_PEERSTORE_Record *record,
8831 const char *emsg)
8832{
8833 struct Backtalker *b = cls;
8834 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8835 struct GNUNET_TIME_Absolute mt;
8836
8837 (void) emsg;
8838 if (NULL == record)
8839 {
8840 /* we're done with #backtalker_monotime_cb() invocations,
8841 continue normal processing */
8842 b->get = NULL;
8843 GNUNET_assert (NULL != b->cmc);
8844 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8845 if (0 != b->body_size)
8847 else
8849 b->cmc = NULL;
8850 return;
8851 }
8852 if (sizeof(*mtbe) != record->value_size)
8853 {
8855 GNUNET_break (0);
8856 return;
8857 }
8858 mtbe = record->value;
8859 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8861 {
8863 "Backtalker message from %s dropped, monotime in the past\n",
8864 GNUNET_i2s (&b->pid));
8866 GST_stats,
8867 "# Backchannel messages dropped: monotonic time not increasing",
8868 1,
8869 GNUNET_NO);
8870 b->monotonic_time = mt;
8871 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8872 */
8873 b->body_size = 0;
8874 }
8876}
8877
8878
8886static void
8887backtalker_monotime_store_cb (void *cls, int success)
8888{
8889 struct Backtalker *b = cls;
8890
8891 if (GNUNET_OK != success)
8892 {
8894 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8895 }
8896 b->sc = NULL;
8897 if (NULL != b->task)
8898 {
8900 b->task = NULL;
8901 }
8903}
8904
8905
8911static void
8913{
8914 struct GNUNET_TIME_AbsoluteNBO mtbe;
8915
8916 if (NULL != b->sc)
8917 {
8919 "store cancel before store with sc %p\n",
8920 b->sc);
8921 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8922 b->sc = NULL;*/
8924 "store cancel before store with sc %p is null\n",
8925 b->sc);
8926 }
8927 else
8928 {
8930 b->task = NULL;
8931 }
8933 b->sc =
8935 "transport",
8936 &b->pid,
8938 &mtbe,
8939 sizeof(mtbe),
8943 b);
8944}
8945
8946
8953
8954
8955static void
8956decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
8957{
8958 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
8959 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
8960 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
8961 const unsigned char *hdr;
8962 size_t hdr_len;
8964
8965 decaps_dv_box_cls->pr->op = NULL;
8968 decaps_dv_box_cls->pr);
8969 GNUNET_free (decaps_dv_box_cls->pr);
8970 if (NULL == km)
8971 {
8972 GNUNET_break_op (0);
8973 finish_cmc_handling (cmc);
8974 return;
8975 }
8976 key = (struct GNUNET_CRYPTO_AeadSecretKey*) km;
8977 hdr = (const unsigned char *) &dvb[1];
8978 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8980 * ntohs (dvb->total_hops);
8981
8982 /* begin actual decryption */
8983 {
8984 struct Backtalker *b;
8985 struct GNUNET_TIME_Absolute monotime;
8986 struct TransportDVBoxPayloadP *ppay;
8987 unsigned char pt[hdr_len + sizeof *ppay] GNUNET_ALIGN;
8988 unsigned char *body;
8989 const struct GNUNET_MessageHeader *mh;
8990
8991 ppay = (struct TransportDVBoxPayloadP *) pt;
8992 body = &pt[sizeof *ppay];
8993 GNUNET_assert (hdr_len >=
8994 sizeof(*ppay) + sizeof(struct GNUNET_MessageHeader));
8995 if (GNUNET_OK != GNUNET_CRYPTO_aead_decrypt (hdr_len,
8996 hdr,
8997 0,
8998 NULL,
8999 key,
9000 &dvb->iv,
9001 &dvb->mac,
9002 pt))
9003 {
9005 "Error decrypting DV payload header\n");
9006 GNUNET_break_op (0);
9007 finish_cmc_handling (cmc);
9008 return;
9009 }
9010 mh = (const struct GNUNET_MessageHeader *) body;
9011 if (ntohs (mh->size) != sizeof(body))
9012 {
9013 GNUNET_break_op (0);
9014 finish_cmc_handling (cmc);
9015 return;
9016 }
9017 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9018 switch (ntohs (mh->type))
9019 {
9021 GNUNET_break_op (0);
9022 finish_cmc_handling (cmc);
9023 return;
9024
9026 GNUNET_break_op (0);
9027 finish_cmc_handling (cmc);
9028 return;
9029
9030 default:
9031 /* permitted, continue */
9032 break;
9033 }
9034 monotime = GNUNET_TIME_absolute_ntoh (ppay->monotonic_time);
9036 "Decrypted backtalk from %s\n",
9037 GNUNET_i2s (&ppay->sender));
9039 &ppay->sender);
9040 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9041 {
9043 GST_stats,
9044 "# Backchannel messages dropped: monotonic time not increasing",
9045 1,
9046 GNUNET_NO);
9047 finish_cmc_handling (cmc);
9048 return;
9049 }
9050 if ((NULL == b) ||
9051 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9052 {
9053 /* Check signature */
9054 const struct GNUNET_PeerIdentity *my_identity;
9055 struct EphemeralConfirmationPS ec;
9056
9059
9061 ec.target = *my_identity;
9062 ec.ephemeral_key = dvb->ephemeral_key;
9063 ec.purpose.size = htonl (sizeof(ec));
9065 if (
9066 GNUNET_OK !=
9069 &ec,
9070 &ppay->sender_sig,
9071 &ppay->sender.public_key))
9072 {
9073 /* Signature invalid, discard! */
9074 GNUNET_break_op (0);
9075 finish_cmc_handling (cmc);
9076 return;
9077 }
9078 }
9079 /* Update sender, we now know the real origin! */
9081 "DVBox received for me from %s via %s\n",
9082 GNUNET_i2s2 (&ppay->sender),
9083 GNUNET_i2s (&cmc->im.sender));
9084 cmc->im.sender = ppay->sender;
9085
9086 if (NULL != b)
9087 {
9088 /* update key cache and mono time */
9089 b->last_ephemeral = dvb->ephemeral_key;
9090 b->monotonic_time = monotime;
9092 b->timeout =
9094 cmc->mh = mh;
9096 return;
9097 }
9098 /* setup data structure to cache signature AND check
9099 monotonic time with PEERSTORE before forwarding backchannel payload */
9100 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(hdr_len));
9101 b->pid = ppay->sender;
9102 b->body_size = hdr_len;
9103 memcpy (&b[1], body, hdr_len);
9107 &b->pid,
9108 b,
9110 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9111 b->cmc = cmc;
9112 b->timeout =
9115 b->get =
9117 "transport",
9118 &b->pid,
9121 b);
9122 } /* end actual decryption */
9123}
9124
9125
9133static void
9134handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9135{
9136 struct CommunicatorMessageContext *cmc = cls;
9137 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9138 uint16_t num_hops = ntohs (dvb->num_hops);
9139 const struct GNUNET_PeerIdentity *hops =
9140 (const struct GNUNET_PeerIdentity *) &dvb[1];
9141 const char *enc_payload = (const char *) &hops[num_hops];
9142 uint16_t enc_payload_size =
9143 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9144 struct DecapsDvBoxCls *decaps_dv_box_cls;
9145 const struct GNUNET_PeerIdentity *my_identity;
9146
9149
9150 if (GNUNET_EXTRA_LOGGING > 0)
9151 {
9152 char *path;
9153
9155 for (unsigned int i = 0; i < num_hops; i++)
9156 {
9157 char *tmp;
9158
9159 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9160 GNUNET_free (path);
9161 path = tmp;
9162 }
9164 "Received DVBox with remaining path %s\n",
9165 path);
9166 GNUNET_free (path);
9167 }
9168
9169 if (num_hops > 0)
9170 {
9171 /* We're trying from the end of the hops array, as we may be
9172 able to find a shortcut unknown to the origin that way */
9173 for (int i = num_hops - 1; i >= 0; i--)
9174 {
9175 struct Neighbour *n;
9176
9177 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9178 {
9179 GNUNET_break_op (0);
9180 finish_cmc_handling (cmc);
9181 return;
9182 }
9183 n = lookup_neighbour (&hops[i]);
9184 if (NULL == n)
9185 continue;
9187 "Skipping %u/%u hops ahead while routing DV Box\n",
9188 i,
9189 num_hops);
9190
9191 forward_dv_box (n,
9192 (struct TransportDVBoxMessage *) dvb,
9193 ntohs (dvb->total_hops) + 1,
9194 num_hops - i - 1, /* number of hops left */
9195 &hops[i + 1], /* remaining hops */
9196 enc_payload,
9197 enc_payload_size);
9199 "# DV hops skipped routing boxes",
9200 i,
9201 GNUNET_NO);
9203 "# DV boxes routed (total)",
9204 1,
9205 GNUNET_NO);
9206 finish_cmc_handling (cmc);
9207 return;
9208 }
9209 /* Woopsie, next hop not in neighbours, drop! */
9211 "# DV Boxes dropped: next hop unknown",
9212 1,
9213 GNUNET_NO);
9214 finish_cmc_handling (cmc);
9215 return;
9216 }
9217 /* We are the target. Unbox and handle message. */
9219 "# DV boxes opened (ultimate target)",
9220 1,
9221 GNUNET_NO);
9222 cmc->total_hops = ntohs (dvb->total_hops);
9223
9224 {
9225 // DH key derivation with received DV, could be garbage.
9226 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9227 decaps_dv_box_cls->cmc = cmc;
9228 decaps_dv_box_cls->dvb = dvb;
9229 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9230
9233 decaps_dv_box_cls->pr);
9234 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9235 &dvb->ephemeral_key,
9237 decaps_dv_box_cls);
9238 }
9239 // TODO keep track of cls and potentially clean
9240}
9241
9242
9250static int
9252 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9253{
9254 struct TransportClient *tc = cls;
9255
9256 if (CT_COMMUNICATOR != tc->type)
9257 {
9258 GNUNET_break (0);
9259 return GNUNET_SYSERR;
9260 }
9262 return GNUNET_OK;
9263}
9264
9265
9270{
9274 const char *address;
9275
9280};
9281
9282
9292static int
9294 const struct GNUNET_PeerIdentity *pid,
9295 void *value)
9296{
9297 struct CheckKnownAddressContext *ckac = cls;
9298 struct ValidationState *vs = value;
9299
9300 (void) pid;
9301 if (0 != strcmp (vs->address, ckac->address))
9302 return GNUNET_OK;
9303 ckac->vs = vs;
9304 return GNUNET_NO;
9305}
9306
9307
9313static void
9314validation_start_cb (void *cls);
9315
9316
9324static void
9326 struct GNUNET_TIME_Absolute new_time)
9327{
9329
9330 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9331 return; /* be lazy */
9332 vs->next_challenge = new_time;
9333 if (NULL == vs->hn)
9334 vs->hn =
9336 else
9339 (NULL != validation_task))
9340 return;
9341 if (NULL != validation_task)
9343 /* randomize a bit */
9346 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9349}
9350
9351
9358static void
9360 const char *address)
9361{
9362 struct GNUNET_TIME_Absolute now;
9363 struct ValidationState *vs;
9364 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9365
9367 pid,
9369 &ckac);
9370 if (NULL != (vs = ckac.vs))
9371 {
9372 /* if 'vs' is not currently valid, we need to speed up retrying the
9373 * validation */
9374 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9375 {
9376 /* reduce backoff as we got a fresh advertisement */
9377 vs->challenge_backoff =
9380 vs->challenge_backoff,
9381 2));
9384 vs->challenge_backoff));
9385 }
9386 return;
9387 }
9389 vs = GNUNET_new (struct ValidationState);
9390 vs->pid = *pid;
9391 vs->valid_until =
9393 vs->first_challenge_use = now;
9394 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9395 GNUNET_CRYPTO_random_block (&vs->challenge,
9396 sizeof(vs->challenge));
9397 vs->address = GNUNET_strdup (address);
9398 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9400 "Starting address validation `%s' of peer %s using challenge %s\n",
9401 address,
9402 GNUNET_i2s (pid),
9403 GNUNET_sh2s (&vs->challenge.value));
9407 &vs->pid,
9408 vs,
9411}
9412
9413
9414static struct Queue *
9415find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9416
9417
9418static void
9419suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9420
9421
9422static void
9424 const struct GNUNET_PeerIdentity *pid,
9425 const char *uri)
9426{
9427 struct Queue *q;
9428 int pfx_len;
9429 const char *eou;
9430 char *address;
9431 (void) cls;
9432
9433 eou = strstr (uri,
9434 "://");
9435 pfx_len = eou - uri;
9436 eou += 3;
9438 "%.*s-%s",
9439 pfx_len,
9440 uri,
9441 eou);
9442
9444 "helo for client %s\n",
9445 address);
9446 q = find_queue (pid, address);
9447 if (NULL == q)
9448 {
9450 }
9451 else
9454}
9455
9456
9464static void
9466 const struct GNUNET_PEERSTORE_Record *record,
9467 const char *emsg)
9468{
9469 struct IncomingRequest *ir = cls;
9470 struct GNUNET_HELLO_Parser *parser;
9471 struct GNUNET_MessageHeader *hello;
9472 const struct GNUNET_PeerIdentity *my_identity;
9473
9474 if (NULL != emsg)
9475 {
9477 "Got failure from PEERSTORE: %s\n",
9478 emsg);
9479 return;
9480 }
9481 hello = record->value;
9484 if (0 == GNUNET_memcmp (&record->peer, my_identity))
9485 {
9487 return;
9488 }
9489 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
9492 NULL);
9493 GNUNET_HELLO_parser_free (parser);
9494}
9495
9496
9497static void
9499{
9501 "Error in PEERSTORE monitoring\n");
9502}
9503
9504
9505static void
9507{
9509 "Done with initial PEERSTORE iteration during monitoring\n");
9510}
9511
9512
9519
9520
9521static void
9523 const struct GNUNET_PeerIdentity *pid,
9524 const struct GNUNET_CRYPTO_EddsaSignature *sig)
9525{
9526 struct SignTValidationCls *sign_t_validation_cls = cls;
9527 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9528 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9529 struct VirtualLink *vl;
9530 struct Neighbour *n;
9531 struct IncomingRequest *ir;
9532 struct GNUNET_PeerIdentity sender;
9533
9534 sign_t_validation_cls->pr->op = NULL;
9537 sign_t_validation_cls->pr);
9538 GNUNET_free (sign_t_validation_cls->pr);
9539 tvr.signature = *sig;
9540 sender = cmc->im.sender;
9541 vl = lookup_virtual_link (&sender);
9542 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9543 {
9544 // route_control_message_without_fc (&cmc->im.sender,
9546 &tvr.header,
9548 }
9549 else
9550 {
9551 /* Use route via neighbour */
9552 n = lookup_neighbour (&sender);
9553 if (NULL != n)
9554 route_via_neighbour (n, &tvr.header,
9557 }
9558
9559 finish_cmc_handling (cmc);
9560 if (NULL != vl)
9561 return;
9562
9563 /* For us, the link is still down, but we need bi-directional
9564 connections (for flow-control and for this to be useful for
9565 CORE), so we must try to bring the link up! */
9566
9567 /* (1) Check existing queues, if any, we may be lucky! */
9568 n = lookup_neighbour (&sender);
9569 if (NULL != n)
9570 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9571 start_address_validation (&sender, q->address);
9572 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9573 we could use */
9574 for (ir = ir_head; NULL != ir; ir = ir->next)
9575 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9576 return;
9577 /* we are already trying */
9578 ir = GNUNET_new (struct IncomingRequest);
9579 ir->pid = sender;
9581
9583 GNUNET_YES,
9584 "peerstore",
9585 NULL,
9588 NULL,
9590 NULL,
9592 ir);
9593 ir_total++;
9594 /* Bound attempts we do in parallel here, might otherwise get excessive */
9597};
9598
9599
9608static void
9610 void *cls,
9611 const struct TransportValidationChallengeMessage *tvc)
9612{
9613 struct CommunicatorMessageContext *cmc = cls;
9614 struct TransportValidationResponseMessage tvr = { 0 };
9615 struct GNUNET_TIME_RelativeNBO validity_duration;
9616
9617 /* DV-routed messages are not allowed for validation challenges */
9618 if (cmc->total_hops > 0)
9619 {
9620 GNUNET_break_op (0);
9621 finish_cmc_handling (cmc);
9622 return;
9623 }
9624 validity_duration = cmc->im.expected_address_validity;
9626 "Received address validation challenge %s\n",
9627 GNUNET_sh2s (&tvc->challenge.value));
9628 /* If we have a virtual link, we use this mechanism to signal the
9629 size of the flow control window, and to allow the sender
9630 to ask for increases. If for us the virtual link is still down,
9631 we will always give a window size of zero. */
9632 tvr.header.type =
9634 tvr.header.size = htons (sizeof(tvr));
9635 tvr.reserved = htonl (0);
9636 tvr.challenge = tvc->challenge;
9637 tvr.origin_time = tvc->sender_time;
9638 tvr.validity_duration = validity_duration;
9639 {
9640 /* create signature */
9641 struct TransportValidationPS tvp = {
9643 .purpose.size = htonl (sizeof(tvp)),
9644 .validity_duration = validity_duration,
9645 .challenge = tvc->challenge
9646 };
9647 struct SignTValidationCls *sign_t_validation_cls;
9648
9649 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9650 sign_t_validation_cls->cmc = cmc;
9651 sign_t_validation_cls->tvr = tvr;
9652 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9655 sign_t_validation_cls->pr);
9656 sign_t_validation_cls->pr->op =
9658 &tvp.purpose,
9660 sign_t_validation_cls);
9661 }
9662}
9663
9664
9680
9681
9691static int
9693 const struct GNUNET_PeerIdentity *pid,
9694 void *value)
9695{
9696 struct CheckKnownChallengeContext *ckac = cls;
9697 struct ValidationState *vs = value;
9698
9699 (void) pid;
9700 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9701 return GNUNET_OK;
9702 ckac->vs = vs;
9703 return GNUNET_NO;
9704}
9705
9706
9714static void
9715peerstore_store_validation_cb (void *cls, int success)
9716{
9717 struct ValidationState *vs = cls;
9718
9719 vs->sc = NULL;
9720 if (GNUNET_YES == success)
9721 return;
9723 "# Peerstore failed to store foreign address",
9724 1,
9725 GNUNET_NO);
9726}
9727
9728
9736static struct Queue *
9737find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9738{
9739 struct Neighbour *n;
9740
9741 n = lookup_neighbour (pid);
9742 if (NULL == n)
9743 return NULL;
9744 for (struct Queue *pos = n->queue_head; NULL != pos;
9745 pos = pos->next_neighbour)
9746 {
9747 if (0 == strcmp (pos->address, address))
9748 return pos;
9749 }
9750 return NULL;
9751}
9752
9753
9754static void
9756
9757static void
9759{
9760 struct ValidationState *vs = cls;
9761 struct Queue *q;
9762 struct GNUNET_TIME_Absolute now;
9763
9764 vs->revalidation_task = NULL;
9765 q = find_queue (&vs->pid, vs->address);
9766 if (NULL == q)
9767 {
9768 now = GNUNET_TIME_absolute_get ();
9769 vs->awaiting_queue = GNUNET_YES;
9770 suggest_to_connect (&vs->pid, vs->address);
9772 }
9773 else
9775}
9776
9777
9778static enum GNUNET_GenericReturnValue
9780 void *cls,
9781 const struct GNUNET_HashCode *key,
9782 void *value)
9783{
9784 (void) cls;
9786 "Key in revalidate map %s \n",
9787 GNUNET_h2s (key));
9788 return GNUNET_YES;
9789}
9790
9791
9800static void
9802 void *cls,
9803 const struct TransportValidationResponseMessage *tvr)
9804{
9805 struct CommunicatorMessageContext *cmc = cls;
9806 struct ValidationState *vs;
9807 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9808 .vs = NULL};
9809 struct GNUNET_TIME_Absolute origin_time;
9810 struct Queue *q;
9811 struct Neighbour *n;
9812 struct VirtualLink *vl;
9814 GST_cfg);
9815
9816 /* check this is one of our challenges */
9818 &cmc->im.sender,
9820 &ckac);
9821 if (NULL == (vs = ckac.vs))
9822 {
9823 /* This can happen simply if we 'forgot' the challenge by now,
9824 i.e. because we received the validation response twice */
9826 "# Validations dropped, challenge unknown",
9827 1,
9828 GNUNET_NO);
9830 "Validation response %s dropped, challenge unknown\n",
9831 GNUNET_sh2s (&tvr->challenge.value));
9832 finish_cmc_handling (cmc);
9833 return;
9834 }
9835
9836 /* sanity check on origin time */
9837 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9838 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9839 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9840 {
9842 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9843 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9844 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9845 GNUNET_break_op (0);
9846 finish_cmc_handling (cmc);
9847 return;
9848 }
9849
9850 {
9851 /* check signature */
9852 struct TransportValidationPS tvp = {
9854 .purpose.size = htonl (sizeof(tvp)),
9855 .validity_duration = tvr->validity_duration,
9856 .challenge = tvr->challenge
9857 };
9858
9859 if (
9860 GNUNET_OK !=
9862 &tvp,
9863 &tvr->signature,
9864 &cmc->im.sender.public_key))
9865 {
9866 GNUNET_break_op (0);
9867 finish_cmc_handling (cmc);
9868 return;
9869 }
9870 }
9871
9872 /* validity is capped by our willingness to keep track of the
9873 validation entry and the maximum the other peer allows */
9876 tvr->validity_duration),
9878 vs->validated_until =
9882 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9883 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9884 GNUNET_CRYPTO_random_block (&vs->challenge,
9885 sizeof(vs->challenge));
9886 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9887 vs->validated_until,
9888 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9890 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9891 {
9893 "First challenge use is now %" PRIu64 " %s \n",
9894 vs->first_challenge_use.abs_value_us,
9895 GNUNET_sh2s (&vs->challenge.value));
9896 vs->first_challenge_use = now;
9897 }
9898 else
9900 "First challenge use is later %" PRIu64 " %s \n",
9901 vs->first_challenge_use.abs_value_us,
9902 GNUNET_sh2s (&vs->challenge.value));
9903 vs->last_challenge_use =
9904 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
9905 update_next_challenge_time (vs, vs->first_challenge_use);
9907 "Validation response %s from %s accepted, address valid until %s\n",
9908 GNUNET_sh2s (&tvr->challenge.value),
9909 GNUNET_i2s (&cmc->im.sender),
9911 /*memcpy (&hkey,
9912 &hc,
9913 sizeof (hkey));*/
9915 "Key %s for address %s map size %u contains %u\n",
9916 GNUNET_h2s (&vs->hc),
9917 vs->address,
9920 &vs->hc));
9924 &vs->hc,
9925 vs,
9929 NULL);
9930 vs->revalidation_task =
9935 "transport",
9936 &cmc->im.sender,
9938 vs->address,
9939 strlen (vs->address) + 1,
9940 vs->valid_until,
9943 vs);
9944 finish_cmc_handling (cmc);
9945
9946 /* Finally, we now possibly have a confirmed (!) working queue,
9947 update queue status (if queue still is around) */
9948 q = find_queue (&vs->pid, vs->address);
9949 if (NULL == q)
9950 {
9952 "# Queues lost at time of successful validation",
9953 1,
9954 GNUNET_NO);
9955 return;
9956 }
9957 q->validated_until = vs->validated_until;
9958 q->pd.aged_rtt = vs->validation_rtt;
9959 n = q->neighbour;
9960 vl = lookup_virtual_link (&vs->pid);
9961 if (NULL == vl)
9962 {
9963 vl = GNUNET_new (struct VirtualLink);
9965 "Creating new virtual link %p to %s using direct neighbour!\n",
9966 vl,
9967 GNUNET_i2s (&vs->pid));
9968 vl->burst_addr = NULL;
9969 vl->confirmed = GNUNET_YES;
9970 vl->message_uuid_ctr =
9971 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
9972 vl->target = n->pid;
9978 links,
9979 &vl->target,
9980 vl,
9982 vl->n = n;
9983 n->vl = vl;
9984 q->idle = GNUNET_YES;
9985 vl->visibility_task =
9986 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9988 /* We lacked a confirmed connection to the target
9989 before, so tell CORE about it (finally!) */
9992 }
9993 else
9994 {
9995 /* Link was already up, remember n is also now available and we are done */
9996 if (NULL == vl->n)
9997 {
9998 vl->n = n;
9999 n->vl = vl;
10000 if (GNUNET_YES == vl->confirmed)
10002 "Virtual link to %s could now also use direct neighbour!\n",
10003 GNUNET_i2s (&vs->pid));
10004 }
10005 else
10006 {
10007 GNUNET_assert (n == vl->n);
10008 }
10009 if (GNUNET_NO == vl->confirmed)
10010 {
10011 vl->confirmed = GNUNET_YES;
10012 q->idle = GNUNET_YES;
10013 vl->visibility_task =
10014 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10016 /* We lacked a confirmed connection to the target
10017 before, so tell CORE about it (finally!) */
10020 }
10021 }
10022}
10023
10024
10030static void
10032 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10033{
10034 struct TransportClient *tc = cls;
10035 struct CommunicatorMessageContext *cmc =
10037
10038 cmc->tc = tc;
10039 cmc->im = *im;
10041 "Received message with size %u and flow control id %" PRIu64
10042 " via communicator from peer %s\n",
10043 ntohs (im->header.size),
10044 im->fc_id,
10045 GNUNET_i2s (&im->sender));
10046 cmc->im.neighbour_sender = cmc->im.sender;
10047 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10049}
10050
10051
10060static int
10062{
10063 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10064 (void) cls;
10065
10067 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10068 ntohs (fc->header.size),
10069 ntohl (fc->size_of_addresses),
10070 ntohl (fc->number_of_addresses),
10071 sizeof(struct TransportFlowControlMessage),
10072 sizeof (struct TransportGlobalNattedAddress));
10073
10074 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10076 + ntohl (fc->number_of_addresses) * sizeof (struct
10078 + ntohl (fc->size_of_addresses))
10079 return GNUNET_OK;
10080 else
10081 {
10082 GNUNET_break_op (0);
10083 return GNUNET_SYSERR;
10084 }
10085}
10086
10087
10088static struct GNUNET_TIME_Relative
10090{
10092 unsigned int n_hops = 0;
10093
10095 "calculate_rtt\n");
10096 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10097 pos = pos->next_dv)
10098 {
10100 "calculate_rtt %lu\n",
10101 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10102 n_hops++;
10104 aged_rtt, pos
10105 ->distance
10106 + 2), ret);
10107 }
10108
10109 GNUNET_assert (0 != n_hops);
10110
10111 return ret;
10112}
10113
10114
10115static void
10117 const struct GNUNET_PeerIdentity *pid,
10118 const char *uri)
10119{
10120 struct VirtualLink *vl = cls;
10121 const char *slash;
10122 char *address_uri;
10123 char *prefix;
10124 char *uri_without_port;
10125
10126 slash = strrchr (uri, '/');
10127 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10128 GNUNET_assert (NULL != slash);
10129 slash++;
10130 GNUNET_asprintf (&address_uri,
10131 "%s-%s",
10132 prefix,
10133 slash);
10134
10135 uri_without_port = get_address_without_port (address_uri);
10137 "iterate_address_start_burst %s %s %s %s\n",
10138 uri_without_port,
10139 uri,
10140 address_uri,
10141 slash);
10142 if (0 == strcmp (uri_without_port, slash))
10143 {
10144 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10145 );
10146 }
10147 else
10148 vl->burst_addr = NULL;
10149
10151 GNUNET_free (uri_without_port);
10152}
10153
10154
10155static void
10157 const struct GNUNET_PEERSTORE_Record *record,
10158 const char *emsg)
10159{
10160 struct GNUNET_StartBurstCls *sb_cls = cls;
10161 struct VirtualLink *vl = sb_cls->vl;
10162 struct GNUNET_MessageHeader *hello;
10163 struct GNUNET_HELLO_Parser *parser;
10164
10165 if (NULL != emsg)
10166 {
10168 "Got failure from PEERSTORE: %s\n",
10169 emsg);
10170 return;
10171 }
10172 if (NULL == record)
10173 {
10175 "Hello iteration end for %s\n",
10176 GNUNET_i2s (&vl->target));
10177 vl->ic = NULL;
10178 GNUNET_free (sb_cls);
10179 return;
10180 }
10181
10183 "check_for_burst_address\n");
10184 hello = record->value;
10185 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10188 vl);
10189 GNUNET_HELLO_parser_free (parser);
10190
10192 GNUNET_free (sb_cls);
10193}
10194
10195
10196static void
10197burst_timeout (void *cls)
10198{
10200}
10201
10202
10203static void
10204start_burst (void *cls)
10205{
10206 struct GNUNET_StartBurstCls *sb_cls = cls;
10207 struct VirtualLink *vl = sb_cls->vl;
10208 struct GNUNET_TRANSPORT_StartBurst *sb;
10209 struct GNUNET_MQ_Envelope *env;
10210 char *uri_without_port = vl->burst_addr;
10211
10212 burst_task = NULL;
10213 /*char buf[strlen (uri_without_port) + 1];
10214
10215 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10216 buf[strlen (uri_without_port)] = '\0';*/
10217 env =
10219 strlen (uri_without_port) + 1,
10221 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10222 sb->pid = vl->target;
10223 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10224 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10225 {
10227 "iterate_address_start_burst client tc prefix %s\n",
10228 tc->details.communicator.address_prefix);
10229 if (CT_COMMUNICATOR != tc->type)
10230 continue;
10231 if (GNUNET_YES == tc->details.communicator.can_burst)
10232 {
10234 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10235 uri_without_port,
10236 strlen (uri_without_port),
10237 ntohs (sb->header.size),
10238 (unsigned long) sb_cls->rtt.rel_value_us);
10239 GNUNET_MQ_send (tc->mq, env);
10243 60),
10245 NULL);
10246 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10247 break;
10248 }
10249 }
10250 GNUNET_free (env);
10251 GNUNET_free (sb_cls);
10252}
10253
10254
10255static void
10256queue_burst (void *cls)
10257{
10258 struct GNUNET_StartBurstCls *sb_cls = cls;
10259 struct VirtualLink *vl = sb_cls->vl;
10260
10261 if (GNUNET_YES != use_burst)
10262 return;
10264 "burst_task %p ready %s burst addr %s (%p)\n",
10265 burst_task,
10266 sb_cls->sync_ready ? "yes" : "no",
10267 vl->burst_addr,
10268 vl->burst_addr);
10269 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10270 {
10272 burst_task = NULL;
10274 return;
10275 }
10276 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10277 )
10278 {
10280 &start_burst,
10281 sb_cls);
10282 }
10283 else if (NULL == vl->burst_addr)
10284 {
10286 "peerstore",
10287 &vl->target,
10290 sb_cls);
10291 }
10292}
10293
10294
10303static void
10305{
10306 struct CommunicatorMessageContext *cmc = cls;
10307 struct VirtualLink *vl;
10309 uint32_t seq;
10310 struct GNUNET_TIME_Absolute st;
10311 uint64_t os;
10312 uint64_t wnd;
10313 uint32_t random;
10314
10316 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10317 vl = lookup_virtual_link (&cmc->im.sender);
10318 if (NULL == vl)
10319 {
10320 vl = GNUNET_new (struct VirtualLink);
10322 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10323 vl,
10324 GNUNET_i2s (&cmc->im.sender));
10325 vl->burst_addr = NULL;
10326 vl->confirmed = GNUNET_NO;
10327 vl->message_uuid_ctr =
10328 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
10329 vl->target = cmc->im.sender;
10335 links,
10336 &vl->target,
10337 vl,
10339 }
10340 if (NULL != vl->n)
10341 {
10342 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10343 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10344 }
10345
10347 "remaining %lu timeout for neighbour %p\n",
10348 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10349 rel_value_us,
10350 vl->n);
10351 if (NULL == vl->n ||
10352 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10353 {
10354 struct GNUNET_TIME_Relative rtt;
10355 struct GNUNET_BurstSync burst_sync;
10356 struct GNUNET_StartBurstCls *bcls;
10357
10358 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10359 bcls->vl = vl;
10360 vl->sb_cls = bcls;
10361 if (NULL != vl->dv)
10362 rtt = calculate_rtt (vl->dv);
10363 else
10365 burst_sync.rtt_average = fc->rtt;
10366 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10367 burst_sync.sync_ready = fc->sync_ready;
10368
10370 &burst_sync,
10371 &queue_burst,
10372 bcls);
10373 }
10374 if (0 != ntohl (fc->number_of_addresses))
10375 {
10376 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10377 const char *tgnas;
10378 unsigned int off = 0;
10379
10380 tgnas = (const char *) &fc[1];
10381
10382 for (int i = 1; i <= number_of_addresses; i++)
10383 {
10384 struct TransportGlobalNattedAddress *tgna;
10385 char *addr;
10386 unsigned int address_length;
10387
10388 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10389 addr = (char *) &tgna[1];
10390 address_length = ntohl (tgna->address_length);
10391 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10392
10394 "received address %s length %u\n",
10395 addr,
10396 ntohl (tgna->address_length));
10397
10398 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10399 }
10400 }
10402 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10403 {
10405 "FC dropped: Message out of order\n");
10406 /* out of order, drop */
10408 "# FC dropped: message out of order",
10409 1,
10410 GNUNET_NO);
10411 finish_cmc_handling (cmc);
10412 return;
10413 }
10414 seq = ntohl (fc->seq);
10415 if (seq < vl->last_fc_seq)
10416 {
10417 /* Wrap-around/reset of other peer; start all counters from zero */
10419 }
10420 vl->last_fc_seq = seq;
10421 vl->last_fc_timestamp = st;
10423 os = GNUNET_ntohll (fc->outbound_sent);
10425 (int64_t) (os - vl->incoming_fc_window_size_used);
10427 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10428 GNUNET_i2s (&vl->target),
10429 (unsigned int) seq,
10430 (unsigned long long) vl->outbound_fc_window_size,
10431 (long long) vl->incoming_fc_window_size_loss);
10433 random = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
10434 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10438 != wnd) ||
10439 (0 == random
10441 {
10443 "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",
10444 (unsigned long long) wnd,
10445 (unsigned long long) vl->incoming_fc_window_size,
10446 (unsigned long long) vl->last_outbound_window_size_received,
10449 }
10450 if ((wnd == vl->incoming_fc_window_size
10454 (NULL != vl->fc_retransmit_task))
10455 {
10457 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10458 GNUNET_i2s (&vl->target),
10459 (unsigned long long) wnd);
10461 vl->fc_retransmit_task = NULL;
10462 vl->fc_retransmit_count = 0;
10463 }
10465 /* FC window likely increased, check transmission possibilities! */
10467 finish_cmc_handling (cmc);
10468}
10469
10470
10478static void
10480{
10482 { GNUNET_MQ_hd_var_size (fragment_box,
10485 cmc),
10486 GNUNET_MQ_hd_var_size (reliability_box,
10489 cmc),
10490 GNUNET_MQ_hd_var_size (reliability_ack,
10493 cmc),
10494 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10497 cmc),
10498 GNUNET_MQ_hd_var_size (dv_learn,
10501 cmc),
10502 GNUNET_MQ_hd_var_size (dv_box,
10504 struct TransportDVBoxMessage,
10505 cmc),
10506 GNUNET_MQ_hd_var_size (flow_control,
10509 cmc),
10511 validation_challenge,
10514 cmc),
10516 validation_response,
10519 cmc),
10521 int ret;
10522 const struct GNUNET_MessageHeader *msg = cmc->mh;
10523
10525 "Handling message of type %u with %u bytes\n",
10526 (unsigned int) ntohs (msg->type),
10527 (unsigned int) ntohs (msg->size));
10529 if (GNUNET_SYSERR == ret)
10530 {
10531 GNUNET_break (0);
10533 GNUNET_free (cmc);
10534 return;
10535 }
10536 if (GNUNET_NO == ret)
10537 {
10538 /* unencapsulated 'raw' message */
10539 handle_raw_message (cmc, msg);
10540 }
10541}
10542
10543
10550static int
10552 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10553{
10554 struct TransportClient *tc = cls;
10555
10556 if (CT_COMMUNICATOR != tc->type)
10557 {
10558 GNUNET_break (0);
10559 return GNUNET_SYSERR;
10560 }
10562 return GNUNET_OK;
10563}
10564
10565
10571static void
10573{
10574 if (pm->msg_uuid_set)
10575 return;
10576 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10577 pm->msg_uuid_set = GNUNET_YES;
10578}
10579
10580
10589static struct PendingAcknowledgement *
10591 struct DistanceVectorHop *dvh,
10592 struct PendingMessage *pm)
10593{
10594 struct PendingAcknowledgement *pa;
10595
10596 pa = GNUNET_new (struct PendingAcknowledgement);
10597 pa->queue = queue;
10598 pa->dvh = dvh;
10599 pa->pm = pm;
10600 do
10601 {
10603 sizeof(pa->ack_uuid));
10604 }
10607 &pa->ack_uuid.value,
10608 pa,
10610 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10611 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10612 if (NULL != dvh)
10615 pa->message_size = pm->bytes_msg;
10617 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10619 pm->logging_uuid);
10620 return pa;
10621}
10622
10623
10635static struct PendingMessage *
10637 struct DistanceVectorHop *dvh,
10638 struct PendingMessage *pm)
10639{
10640 struct PendingAcknowledgement *pa;
10641 struct PendingMessage *ff;
10642 uint16_t mtu;
10643 uint16_t msize;
10644
10645 mtu = (UINT16_MAX == queue->mtu)
10646 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10647 : queue->mtu;
10649 "Fragmenting message <%" PRIu64
10650 "> with size %u to %s for MTU %u\n",
10651 pm->logging_uuid,
10652 pm->bytes_msg,
10653 GNUNET_i2s (&pm->vl->target),
10654 (unsigned int) mtu);
10657 "Fragmenting message %" PRIu64 " <%" PRIu64
10658 "> with size %u to %s for MTU %u\n",
10659 pm->msg_uuid.uuid,
10660 pm->logging_uuid,
10661 pm->bytes_msg,
10662 GNUNET_i2s (&pm->vl->target),
10663 (unsigned int) mtu);
10664
10665 /* This invariant is established in #handle_add_queue_message() */
10666 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10667
10668 /* select fragment for transmission, descending the tree if it has
10669 been expanded until we are at a leaf or at a fragment that is small
10670 enough
10671 */
10672 ff = pm;
10673 msize = ff->bytes_msg;
10674
10675 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10676 (ff->frag_off == msize) && (NULL != ff->head_frag))
10677 {
10678 ff = ff->head_frag; /* descent into fragmented fragments */
10679 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10680 }
10681
10682 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10683 {
10684 /* Did not yet calculate all fragments, calculate next fragment */
10685 struct PendingMessage *frag;
10686 struct TransportFragmentBoxMessage tfb;
10687 const char *orig;
10688 char *msg;
10689 uint16_t fragmax;
10690 uint16_t fragsize;
10691 uint16_t msize_ff;
10692 uint16_t xoff = 0;
10693 pm->frag_count++;
10694
10695 orig = (const char *) &ff[1];
10696 msize_ff = ff->bytes_msg;
10697 if (pm != ff)
10698 {
10699 const struct TransportFragmentBoxMessage *tfbo;
10700
10701 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10702 orig += sizeof(struct TransportFragmentBoxMessage);
10703 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10704 xoff = ntohs (tfbo->frag_off);
10705 }
10706 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10707 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10708 frag =
10709 GNUNET_malloc (sizeof(struct PendingMessage)
10710 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10712 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10713 frag,
10714 ff,
10715 pm->vl,
10716 pm);
10718 frag->vl = pm->vl;
10719 frag->frag_parent = ff;
10720 frag->timeout = pm->timeout;
10721 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10722 frag->pmt = PMT_FRAGMENT_BOX;
10723 msg = (char *) &frag[1];
10725 tfb.header.size =
10726 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10727 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10728 tfb.ack_uuid = pa->ack_uuid;
10729 tfb.msg_uuid = pm->msg_uuid;
10730 tfb.frag_off = htons (ff->frag_off + xoff);
10731 tfb.msg_size = htons (pm->bytes_msg);
10732 memcpy (msg, &tfb, sizeof(tfb));
10733 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10735 ff->tail_frag, frag);
10736 ff->frag_off += fragsize;
10737 ff = frag;
10738 }
10739
10740 /* Move head to the tail and return it */
10744 ff);
10748 ff);
10749
10750 return ff;
10751}
10752
10753
10766static struct PendingMessage *
10768 struct DistanceVectorHop *dvh,
10769 struct PendingMessage *pm)
10770{
10772 struct PendingAcknowledgement *pa;
10773 struct PendingMessage *bpm;
10774 char *msg;
10775
10776 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10777 return pm; /* already fragmented or reliability boxed, or control message:
10778 do nothing */
10779 if (NULL != pm->bpm)
10780 return pm->bpm; /* already computed earlier: do nothing */
10781 // TODO I guess we do not need this assertion. We might have a DLL with
10782 // fragments, because the MTU changed, and we do not need to fragment anymore.
10783 // But we should keep the fragments until message was completed, because
10784 // the MTU might change again.
10785 // GNUNET_assert (NULL == pm->head_frag);
10786 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10787 {
10788 /* failed hard */
10789 GNUNET_break (0);
10791 return NULL;
10792 }
10793
10795
10796 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10797 + pm->bytes_msg);
10799 "4 created pm %p storing vl %p from pm %p\n",
10800 bpm,
10801 pm->vl,
10802 pm);
10804 bpm->vl = pm->vl;
10805 bpm->frag_parent = pm;
10806 // Why was this needed?
10807 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10808 bpm->timeout = pm->timeout;
10810 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10813 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10814 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10815
10816 rbox.ack_uuid = pa->ack_uuid;
10817 msg = (char *) &bpm[1];
10818 memcpy (msg, &rbox, sizeof(rbox));
10819 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10820 pm->bpm = bpm;
10822 "Preparing reliability box for message <%" PRIu64
10823 "> of size %d (%d) to %s on queue %s\n",
10824 pm->logging_uuid,
10825 pm->bytes_msg,
10826 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10827 GNUNET_i2s (&pm->vl->target),
10828 queue->address);
10829 return bpm;
10830}
10831
10832
10833static void
10836{
10837 struct VirtualLink *vl = pm->vl;
10838 struct PendingMessage *pos;
10839
10840 /* re-insert sort in neighbour list */
10844 pm);
10845 pos = vl->pending_msg_tail;
10846 while ((NULL != pos) &&
10848 pos = pos->prev_vl;
10852 pos,
10853 pm);
10854}
10855
10856
10857static unsigned int
10859{
10860 struct PendingMessage *pos;
10862
10863 pos = pm->head_frag;
10864 while (NULL != pos)
10865 {
10866 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10867 GNUNET_NO == check_next_attempt_tree (pos, root))
10869 else
10870 {
10872 break;
10873 }
10874 pos = pos->next_frag;
10875 }
10876
10877 return frags_in_flight;
10878}
10879
10880
10881static void
10883{
10884 struct PendingMessage *pos;
10885
10886 pos = pm->head_frag;
10887 while (NULL != pos)
10888 {
10889 pos->frags_in_flight_round = pm->frags_in_flight_round;
10891 pos = pos->next_frag;
10892 }
10893}
10894
10895
10904static void
10907{
10908 if (NULL == pm->frag_parent)
10909 {
10912 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
10913 pm->logging_uuid,
10916 }
10917 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
10918 {
10919 struct PendingMessage *root = pm->frag_parent;
10920
10921 while (NULL != root->frag_parent)
10922 root = root->frag_parent;
10924 "Next attempt for root message <%" PRIu64 "> set to %s\n",
10925 root->logging_uuid,
10927 root->next_attempt = next_attempt;
10929 }
10930 else
10931 {
10932 struct PendingMessage *root = pm->frag_parent;
10933
10934 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10935 root = root->frag_parent;
10936
10938 "frag_count next attempt %u\n",
10939 root->frag_count);
10940
10941 if (GNUNET_NO == root->frags_in_flight)
10942 {
10943 root->next_attempt = next_attempt;
10945 root->frags_in_flight_round++;
10947 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
10948 ">)set to %" PRIu64 "\n",
10949 pm->logging_uuid,
10950 root->logging_uuid,
10952 }
10953
10954 pm->next_attempt = root->next_attempt;
10955 pm->frags_in_flight_round = root->frags_in_flight_round;
10957
10958 if (root->bytes_msg == root->frag_off)
10959 root->frags_in_flight = check_next_attempt_tree (root, root);
10960 else
10962
10963 if (GNUNET_NO == root->frags_in_flight)
10964 {
10966 "We have no fragments in flight for message %" PRIu64
10967 ", reorder root! Next attempt is %" PRIu64 "\n",
10968 root->logging_uuid,
10970 if (PMT_DV_BOX == root->pmt)
10971 root = root->frag_parent;
10972 reorder_root_pm (root, root->next_attempt);
10973 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
10974 }
10975 else
10976 {
10977 double factor = ((double) root->frag_count - 1)
10978 / (double) root->frag_count;
10979 struct GNUNET_TIME_Relative s1;
10980 struct GNUNET_TIME_Relative s2;
10981 struct GNUNET_TIME_Relative plus_mean =
10984 next_attempt);
10985
10987 "frag_count %u after factor\n",
10988 root->frag_count);
10990 factor);
10991 s2 = GNUNET_TIME_relative_divide (plus,
10992 root->frag_count);
10993 plus_mean = GNUNET_TIME_relative_add (s1, s2);
10996 "We have fragments in flight for message %" PRIu64
10997 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
10998 root->logging_uuid,
11000 }
11001 }
11002}
11003
11004
11009{
11014
11019
11024
11029
11033 int frag;
11034
11038 int relb;
11039
11044
11048 unsigned int frags_in_flight;
11049
11054};
11055
11056
11068static void
11070 struct Queue *queue,
11071 struct VirtualLink *vl,
11072 struct DistanceVectorHop *dvh,
11073 size_t overhead)
11074{
11075 struct GNUNET_TIME_Absolute now;
11076
11077 now = GNUNET_TIME_absolute_get ();
11078 sc->to_early = GNUNET_NO;
11079 sc->frags_in_flight = GNUNET_NO;
11080 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11081 pos = pos->next_vl)
11082 {
11083 size_t real_overhead = overhead;
11084 int frag;
11085 int relb;
11086
11087 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11088 {
11090 "DV messages must not be DV-routed to next hop!\n");
11091 continue; /* DV messages must not be DV-routed to next hop! */
11092 }
11093 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11094 {
11095 if (GNUNET_YES == pos->frags_in_flight)
11096 {
11097 sc->frags_in_flight = GNUNET_YES;
11099 "Fragments in flight for message %" PRIu64 "\n",
11100 pos->logging_uuid);
11101 }
11102 else
11103 {
11105 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11106 PRIu64 "\n",
11107 pos->logging_uuid);
11108 sc->to_early = GNUNET_YES;
11109 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11110 pos->next_attempt);
11111 continue;
11112 }
11113 // break; /* too early for all messages, they are sorted by next_attempt */
11114 }
11115 if (NULL != pos->qe)
11116 {
11118 "not eligible\n");
11119 continue; /* not eligible */
11120 }
11121 sc->consideration_counter++;
11122 /* determine if we have to fragment, if so add fragmentation
11123 overhead! */
11125 "check %" PRIu64 " for sc->best\n",
11126 pos->logging_uuid);
11127 frag = GNUNET_NO;
11128 if (((0 != queue->mtu) &&
11129 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11130 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11132 ||
11133 (NULL != pos->head_frag /* fragments already exist, should
11134 respect that even if MTU is UINT16_MAX for
11135 this queue */))
11136 {
11138 "fragment msg with size %u, realoverhead is %lu\n",
11139 pos->bytes_msg,
11140 real_overhead);
11141 frag = GNUNET_YES;
11142 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11143 {
11144 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11145 header without the ACK UUID when using a *reliable* channel! */
11146 }
11147 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11148 }
11149 /* determine if we have to reliability-box, if so add reliability box
11150 overhead */
11151 relb = GNUNET_NO;
11152 if ((GNUNET_NO == frag) &&
11153 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11154 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11155 {
11156 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11157
11158 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11159 {
11160 frag = GNUNET_YES;
11161 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11162 }
11163 else
11164 {
11165 relb = GNUNET_YES;
11166 }
11168 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11169 pos->bytes_msg,
11170 real_overhead,
11171 queue->mtu,
11172 frag,
11173 relb);
11174 }
11175
11176 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11177 message would beat it! */
11178 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11179 {
11180 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11181 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11182 experimentally validated. There may be some huge potential for
11183 improvement here. Also, we right now only compare how well the
11184 given message fits _this_ queue, and do not consider how well other
11185 queues might suit the message. Taking other queues into consideration
11186 may further improve the result, but could also be expensive
11187 in terms of CPU time. */
11188 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11189 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11190 long long time_delta =
11191 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11192 / 1000LL;
11193
11194 /* "time_delta" considers which message has been 'ready' for transmission
11195 for longer, if a message has a preference for low latency, increase
11196 the weight of the time_delta by 10x if it is favorable for that message */
11197 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11198 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11199 time_delta *= 10; /* increase weight (always, both are low latency) */
11200 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11201 (time_delta > 0))
11202 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11203 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11204 (time_delta < 0))
11205 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11206 if (0 != queue->mtu)
11207 {
11208 /* Grant bonus if we are below MTU, larger bonus the closer we will
11209 be to the MTU */
11210 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11211 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11212 if (queue->mtu > real_overhead + pos->bytes_msg)
11213 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11214 }
11215 if (sc_score + time_delta > pm_score)
11216 {
11218 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11219 "\n",
11220 pos->logging_uuid,
11221 sc->best->logging_uuid);
11222 continue; /* sc_score larger, keep sc->best */
11223 }
11224 }
11225 sc->best = pos;
11226 sc->dvh = dvh;
11227 sc->frag = frag;
11228 sc->relb = relb;
11229 sc->real_overhead = real_overhead;
11230 }
11231}
11232
11233
11244static void
11246 struct Neighbour *next_hop,
11247 const struct GNUNET_MessageHeader *hdr,
11249{
11250 struct PendingMessageScoreContext *sc = cls;
11251 struct PendingMessage *pm = sc->best;
11252 struct PendingMessage *bpm;
11253 uint16_t bsize = ntohs (hdr->size);
11254
11255 GNUNET_assert (NULL == pm->bpm);
11256 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11258 "5 created pm %p storing vl %p from pm %p\n",
11259 bpm,
11260 pm->vl,
11261 pm);
11263 bpm->pmt = PMT_DV_BOX;
11264 bpm->vl = pm->vl;
11265 bpm->timeout = pm->timeout;
11266 bpm->bytes_msg = bsize;
11267 bpm->frag_parent = pm;
11270 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11271 " (next hop is %s)\n",
11273 pm->logging_uuid,
11274 GNUNET_i2s (&next_hop->pid));
11275 memcpy (&bpm[1], hdr, bsize);
11276 pm->bpm = bpm;
11277}
11278
11279
11295static void
11297{
11298 struct Queue *queue = cls;
11299 struct Neighbour *n = queue->neighbour;
11301 struct PendingMessage *pm;
11302
11303 queue->transmit_task = NULL;
11304 if (NULL == n->vl)
11305 {
11307 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11308 GNUNET_i2s (&n->pid),
11309 queue->address);
11310 queue->idle = GNUNET_YES;
11311 return;
11312 }
11313 memset (&sc, 0, sizeof(sc));
11314 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11315 if (NULL == sc.best)
11316 {
11317 /* Also look at DVH that have the n as first hop! */
11318 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11319 dvh = dvh->next_neighbour)
11320 {
11322 queue,
11323 dvh->dv->vl,
11324 dvh,
11325 sizeof(struct GNUNET_PeerIdentity)
11326 * (1 + dvh->distance)
11327 + sizeof(struct TransportDVBoxMessage)
11328 + sizeof(struct TransportDVBoxPayloadP));
11329 }
11330 }
11331 if (NULL == sc.best)
11332 {
11333 /* no message pending, nothing to do here! */
11335 "No pending messages, queue `%s' to %s now idle\n",
11336 queue->address,
11337 GNUNET_i2s (&n->pid));
11338 if (GNUNET_YES == sc.to_early)
11339 schedule_transmit_on_queue (sc.to_early_retry_delay,
11340 queue,
11342 queue->idle = GNUNET_YES;
11343 return;
11344 }
11345 /* There is a message pending, we are certainly not idle */
11346 queue->idle = GNUNET_NO;
11347
11348 /* Given selection in `sc`, do transmission */
11349 pm = sc.best;
11351 "Selected message <%" PRIu64 ">\n",
11352 pm->logging_uuid);
11353 if (NULL != sc.dvh)
11354 {
11356 "Is this %u a DV box?\n",
11357 pm->pmt);
11358 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11359 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11360 {
11362 "Discard old box, because we have a new DV path.\n");
11363 free_pending_message (sc.best->bpm);
11364 sc.best->bpm = NULL;
11365 }
11366
11367 if (NULL == sc.best->bpm)
11368 {
11370 "encapsulate_for_dv 2\n");
11371 encapsulate_for_dv (sc.dvh->dv,
11372 1,
11373 &sc.dvh,
11374 (const struct GNUNET_MessageHeader *) &sc.best[1],
11376 &sc,
11377 RMO_NONE,
11378 GNUNET_NO);
11379 GNUNET_assert (NULL != sc.best->bpm);
11381 "%lu %lu %lu %lu %u\n",
11382 sizeof(struct GNUNET_PeerIdentity),
11383 sizeof(struct TransportDVBoxMessage),
11384 sizeof(struct TransportDVBoxPayloadP),
11385 sizeof(struct TransportFragmentBoxMessage),
11386 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11387 sc.best->bpm->used_dvh = sc.dvh;
11388 }
11389 pm = sc.best->bpm;
11390 }
11391 if (GNUNET_YES == sc.frag)
11392 {
11393 pm = fragment_message (queue, sc.dvh, pm);
11394 if (NULL == pm)
11395 {
11397 "Fragmentation failed queue %s to %s for <%" PRIu64
11398 ">, trying again\n",
11399 queue->address,
11400 GNUNET_i2s (&n->pid),
11401 sc.best->logging_uuid);
11403 queue,
11405 return;
11406 }
11407 }
11408 else if (GNUNET_YES == sc.relb)
11409 {
11411 if (NULL == pm)
11412 {
11413 /* Reliability boxing failed, try next message... */
11414 GNUNET_log (
11416 "Reliability boxing failed queue %s to %s for <%" PRIu64
11417 ">, trying again\n",
11418 queue->address,
11419 GNUNET_i2s (&n->pid),
11420 sc.best->logging_uuid);
11422 queue,
11424 return;
11425 }
11426 }
11427
11428 /* Pass 'pm' for transission to the communicator */
11429 GNUNET_log (
11431 "Passing message <%" PRIu64
11432 "> to queue %s for peer %s (considered %u others)\n",
11433 pm->logging_uuid,
11434 queue->address,
11435 GNUNET_i2s (&n->pid),
11436 sc.consideration_counter);
11437
11438 /* Flow control: increment amount of traffic sent; if we are routing
11439 via DV (and thus the ultimate target of the pending message is for
11440 a different virtual link than the one of the queue), then we need
11441 to use up not only the window of the direct link but also the
11442 flow control window for the DV link! */
11443 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11444
11445 if (pm->vl != queue->neighbour->vl)
11446 {
11447 /* If the virtual link of the queue differs, this better be distance
11448 vector routing! */
11449 GNUNET_assert (NULL != sc.dvh);
11450 /* If we do distance vector routing, we better not do this for a
11451 message that was itself DV-routed */
11452 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11453 /* We use the size of the unboxed message here, to avoid counting
11454 the DV-Box header which is eaten up on the way by intermediaries */
11455 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11456 }
11457 else
11458 {
11459 GNUNET_assert (NULL == sc.dvh);
11460 }
11461
11462 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11463
11464 /* Check if this transmission somehow conclusively finished handing 'pm'
11465 even without any explicit ACKs */
11466 if ((PMT_CORE == pm->pmt) ||
11467 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11468 {
11470 }
11471 else
11472 {
11473 struct GNUNET_TIME_Relative wait_duration;
11474 unsigned int wait_multiplier;
11475
11476 if (PMT_FRAGMENT_BOX == pm->pmt)
11477 {
11478 struct PendingMessage *root;
11479
11480 root = pm->frag_parent;
11481 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11482 root = root->frag_parent;
11483
11484 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11485 / ((double) root->frag_off
11486 / (double) root->frag_count))
11487 * 4;
11488 }
11489 else
11490 {
11491 // No fragments, we use 4 RTT before retransmitting.
11492 wait_multiplier = 4;
11493 }
11494
11495 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11496 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11497
11499 "Wait multiplier %u\n",
11500 wait_multiplier);
11501
11502 /* Message not finished, waiting for acknowledgement.
11503 Update time by which we might retransmit 's' based on queue
11504 characteristics (i.e. RTT); it takes one RTT for the message to
11505 arrive and the ACK to come back in the best case; but the other
11506 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11507 retransmitting.
11508
11509 OPTIMIZE: Note that in the future this heuristic should likely
11510 be improved further (measure RTT stability, consider message
11511 urgency and size when delaying ACKs, etc.) */
11512
11513 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11514 queue->pd.aged_rtt.rel_value_us)
11515 wait_duration = queue->pd.aged_rtt;
11516 else
11517 {
11518 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11519 wait_multiplier = 4;
11520 }
11521 {
11524 wait_duration, wait_multiplier));
11526 wait_duration, wait_multiplier);
11528 "Waiting %s for ACK until %s\n",
11533 GNUNET_TIME_relative_multiply (wait_duration,
11534 wait_multiplier))
11535 );
11536 }
11537 }
11538 /* finally, re-schedule queue transmission task itself */
11540 queue,
11542}
11543
11544
11551static void
11553 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11554{
11555 struct TransportClient *tc = cls;
11556
11557 if (CT_COMMUNICATOR != tc->type)
11558 {
11559 GNUNET_break (0);
11561 return;
11562 }
11563 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11564 queue = queue->next_client)
11565 {
11566 struct Neighbour *neighbour = queue->neighbour;
11567
11568 if ((ntohl (dqm->qid) != queue->qid) ||
11569 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11570 continue;
11572 "Dropped queue %s to peer %s\n",
11573 queue->address,
11574 GNUNET_i2s (&neighbour->pid));
11575 free_queue (queue);
11577 return;
11578 }
11579 GNUNET_break (0);
11581}
11582
11583
11584static void
11586 struct TransportClient *tc)
11587{
11588 struct PendingMessage *pm;
11589
11590 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11591 qe->queue->queue_tail,
11592 qe);
11593 qe->queue->queue_length--;
11594 tc->details.communicator.total_queue_length--;
11596 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11597 qe->queue->address,
11598 qe->queue->qid,
11599 GNUNET_i2s (&qe->queue->neighbour->pid),
11600 qe->queue->queue_length,
11601 tc->details.communicator.total_queue_length);
11602
11603 /* if applicable, resume transmissions that waited on ACK */
11605 tc->details.communicator.total_queue_length)
11606 {
11607 /* Communicator dropped below threshold, resume all queues
11608 incident with this client! */
11610 GST_stats,
11611 "# Transmission throttled due to communicator queue limit",
11612 -1,
11613 GNUNET_NO);
11614 for (struct Queue *queue = tc->details.communicator.queue_head;
11615 NULL != queue;
11616 queue = queue->next_client)
11617 {
11619 queue,
11621 }
11622 }
11623 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11624 {
11625 /* queue dropped below threshold; only resume this one queue */
11627 "# Transmission throttled due to queue queue limit",
11628 -1,
11629 GNUNET_NO);
11631 qe->queue,
11633 }
11634 else if (1 == qe->queue->q_capacity)
11635 {
11636 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11638 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11639 PRIu64 ".\n",
11640 qe->queue->qid,
11641 qe->queue->q_capacity);
11642 /* message queue has capacity; only resume this one queue */
11643 /* queue dropped below threshold; only resume this one queue */
11645 "# Transmission throttled due to message queue capacity",
11646 -1,
11647 GNUNET_NO);
11649 qe->queue,
11651 }
11652
11653 if (NULL != (pm = qe->pm))
11654 {
11655 struct VirtualLink *vl;
11656
11657 // GNUNET_assert (qe == pm->qe);
11658 pm->qe = NULL;
11659 /* If waiting for this communicator may have blocked transmission
11660 of pm on other queues for this neighbour, force schedule
11661 transmit on queue for queues of the neighbour */
11662 if (NULL == pm->frag_parent)
11663 {
11664 vl = pm->vl;
11665 if ((NULL != vl) &&
11666 (NULL != vl->pending_msg_head) &&
11667 (vl->pending_msg_head == pm))
11669 }
11670 }
11671 GNUNET_free (qe);
11672}
11673
11674
11681static void
11683 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11684{
11685 struct TransportClient *tc = cls;
11686 struct QueueEntry *qe;
11687
11688 if (CT_COMMUNICATOR != tc->type)
11689 {
11690 GNUNET_break (0);
11692 return;
11693 }
11694
11695 /* find our queue entry matching the ACK */
11696 qe = NULL;
11698 "Looking for queue for PID %s\n",
11699 GNUNET_i2s (&sma->receiver));
11700 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11701 queue = queue->next_client)
11702 {
11703 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11704 continue;
11706 "Found PID %s\n",
11707 GNUNET_i2s (&queue->neighbour->pid));
11708
11709
11710 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11711 qep = qep->next)
11712 {
11713 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11714 sma->qid))
11715 continue;
11717 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11718 PRIu64 " Ack QID %u\n",
11719 qep->mid,
11720 queue->qid,
11721 GNUNET_ntohll (sma->mid),
11722 ntohl (sma->qid));
11723 qe = qep;
11724 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11726 "For pending message %" PRIu64 " we had retransmissions.\n",
11727 qe->pm->logging_uuid);
11728 break;
11729 }
11730 }
11731 if (NULL == qe)
11732 {
11734 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11735 GNUNET_ntohll (sma->mid),
11736 ntohl (sma->qid));
11737 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11738 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11739 /* this should never happen */
11740 // GNUNET_break (0);
11741 // GNUNET_SERVICE_client_drop (tc->client);
11743 return;
11744 }
11747}
11748
11749
11755static void
11757 const struct GNUNET_TRANSPORT_BurstFinished *bf)
11758{
11760}
11761
11762
11772static int
11774 const struct GNUNET_PeerIdentity *pid,
11775 void *value)
11776{
11777 struct TransportClient *tc = cls;
11778 struct Neighbour *neighbour = value;
11779
11780 GNUNET_assert (CT_MONITOR == tc->type);
11781 for (struct Queue *q = neighbour->queue_head; NULL != q;
11782 q = q->next_neighbour)
11783 {
11784 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11785 .cs = q->cs,
11786 .num_msg_pending = q->num_msg_pending,
11787 .num_bytes_pending = q->num_bytes_pending };
11788
11789 notify_monitor (tc, pid, q->address, q->nt, &me);
11790 }
11791 return GNUNET_OK;
11792}
11793
11794
11801static void
11804{
11805 struct TransportClient *tc = cls;
11806
11807 if (CT_NONE != tc->type)
11808 {
11809 GNUNET_break (0);
11811 return;
11812 }
11813 tc->type = CT_MONITOR;
11814 tc->details.monitor.peer = start->peer;
11815 tc->details.monitor.one_shot = ntohl (start->one_shot);
11819}
11820
11821
11829static struct TransportClient *
11831{
11832 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11833 {
11834 if (CT_COMMUNICATOR != tc->type)
11835 continue;
11836 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11837 return tc;
11838 }
11839 GNUNET_log (
11841 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11842 prefix);
11843 return NULL;
11844}
11845
11846
11854static void
11856{
11857 static uint32_t idgen = 0;
11858 struct TransportClient *tc;
11859 char *prefix;
11860 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11861 struct GNUNET_MQ_Envelope *env;
11862 size_t alen;
11863
11865 if (NULL == prefix)
11866 {
11867 GNUNET_break (0); /* We got an invalid address!? */
11868 return;
11869 }
11871 if (NULL == tc)
11872 {
11874 "# Suggestions ignored due to missing communicator",
11875 1,
11876 GNUNET_NO);
11878 "Cannot connect to %s at `%s', no matching communicator present\n",
11879 GNUNET_i2s (pid),
11880 address);
11882 return;
11883 }
11884 /* forward suggestion for queue creation to communicator */
11886 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11887 (unsigned int) idgen,
11888 prefix,
11889 GNUNET_i2s (pid),
11890 address);
11892 alen = strlen (address) + 1;
11893 env =
11895 cqm->request_id = htonl (idgen++);
11896 cqm->receiver = *pid;
11897 memcpy (&cqm[1], address, alen);
11898 GNUNET_MQ_send (tc->mq, env);
11899}
11900
11901
11909static void
11911{
11913 struct GNUNET_TIME_Absolute monotonic_time;
11914
11915 if (NULL != vs->revalidation_task)
11916 {
11917 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
11918 vs->revalidation_task = NULL;
11919 }
11920 /*memcpy (&hkey,
11921 &hc,
11922 sizeof (hkey));*/
11924 "Remove key %s for address %s map size %u contains %u\n",
11925 GNUNET_h2s (&vs->hc),
11926 vs->address,
11929 &vs->hc));
11931
11933 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
11934 vs->last_challenge_use.abs_value_us)
11935 {
11936 vs->first_challenge_use = monotonic_time;
11937 }
11938 vs->last_challenge_use = monotonic_time;
11939 tvc.header.type =
11941 tvc.header.size = htons (sizeof(tvc));
11942 tvc.reserved = htonl (0);
11943 tvc.challenge = vs->challenge;
11944 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
11946 "Sending address validation challenge %s to %s\n",
11948 GNUNET_i2s (&q->neighbour->pid));
11949 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
11950}
11951
11952
11958static void
11960{
11961 struct ValidationState *vs;
11962 struct Queue *q;
11964 GST_cfg);
11965
11966 (void) cls;
11967 validation_task = NULL;
11969 /* drop validations past their expiration */
11970 while (
11971 (NULL != vs) &&
11973 {
11975 "Validation response %s cleaned up\n",
11976 GNUNET_sh2s (&vs->challenge.value));
11979 }
11980 if (NULL == vs)
11981 {
11983 "Address validation task not scheduled anymore, nothing to do\n");
11984 return; /* woopsie, no more addresses known, should only
11985 happen if we're really a lonely peer */
11986 }
11987 q = find_queue (&vs->pid, vs->address);
11988 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
11989 {
11991 "To early to start next address validation for challenge %s\n",
11992 GNUNET_sh2s (&vs->challenge.value));
11993 return;
11994 }
11995 if (NULL == q)
11996 {
11997 vs->awaiting_queue = GNUNET_YES;
11998 suggest_to_connect (&vs->pid, vs->address);
11999 }
12000 else
12002 /* Finally, reschedule next attempt */
12003 vs->challenge_backoff =
12004 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12007 "Address validation task will run again in %s\n",
12008 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12009 GNUNET_YES));
12012 vs->challenge_backoff));
12013}
12014
12015
12020{
12024 struct Queue *q;
12025
12029 unsigned int quality_count;
12030
12034 unsigned int num_queues;
12035
12040 unsigned int k;
12041};
12042
12043
12055static int
12057 const struct GNUNET_PeerIdentity *pid,
12058 void *value)
12059{
12060 struct QueueQualityContext *ctx = cls;
12061 struct Neighbour *n = value;
12062 int do_inc;
12063
12064 (void) pid;
12065 do_inc = GNUNET_NO;
12066 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12067 {
12068 ctx->num_queues++;
12069 if (0 == ctx->k--)
12070 ctx->q = q;
12071 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12072 statistics and consider those as well here? */
12073 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12074 do_inc = GNUNET_YES;
12075 }
12076 if (GNUNET_YES == do_inc)
12077 ctx->quality_count++;
12078 return GNUNET_OK;
12079}
12080
12081
12093static void
12094start_dv_learn (void *cls);
12095
12096
12104
12105
12106static void
12108 const struct GNUNET_PeerIdentity *pid,
12109 const struct GNUNET_CRYPTO_EddsaSignature *sig)
12110{
12111 const struct GNUNET_PeerIdentity *my_identity;
12112 struct SignDvInitCls *sign_dv_init_cls = cls;
12113 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12114 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12115 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12116
12119
12120 sign_dv_init_cls->pr->op = NULL;
12123 sign_dv_init_cls->pr);
12124 GNUNET_free (sign_dv_init_cls->pr);
12125
12126 dvl.init_sig = *sig;
12127 dvl.initiator = *my_identity;
12128 dvl.challenge = lle->challenge;
12129
12130 qqc.quality_count = 0;
12132 qqc.num_queues = 0;
12133 qqc.q = NULL;
12136 &qqc);
12137 GNUNET_assert (NULL != qqc.q);
12138
12139 /* Do this as close to transmission time as possible! */
12141
12142 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12143 /* reschedule this job, randomizing the time it runs (but no
12144 actual backoff!) */
12145 if (NULL != dvlearn_task)
12150 NULL);
12151}
12152
12153
12165static void
12167{
12168 struct LearnLaunchEntry *lle;
12169 struct QueueQualityContext qqc;
12170 struct TransportDVLearnMessage dvl;
12171 const struct GNUNET_PeerIdentity *my_identity;
12172
12173 (void) cls;
12174 dvlearn_task = NULL;
12176 return; /* lost all connectivity, cannot do learning */
12177 qqc.quality_count = 0;
12178 qqc.num_queues = 0;
12182 &qqc);
12184 {
12185 struct GNUNET_TIME_Relative delay;
12186 unsigned int factor;
12187
12188 /* scale our retries by how far we are above the threshold */
12192 "At connection quality %u, will launch DV learn in %s\n",
12193 qqc.quality_count,
12196 return;
12197 }
12198 /* remove old entries in #dvlearn_map if it has grown too big */
12199 while (MAX_DV_LEARN_PENDING <=
12201 {
12202 lle = lle_tail;
12205 &lle->challenge.value,
12206 lle));
12208 GNUNET_free (lle);
12209 }
12210 /* setup data structure for learning */
12211 lle = GNUNET_new (struct LearnLaunchEntry);
12213 sizeof(lle->challenge));
12215 "Starting launch DV learn with challenge %s\n",
12216 GNUNET_sh2s (&lle->challenge.value));
12221 &lle->challenge.value,
12222 lle,
12227 dvl.header.size = htons (sizeof(dvl));
12228 dvl.num_hops = htons (0);
12229 dvl.bidirectional = htons (0);
12231 dvl.monotonic_time =
12233 // We will set the below again later
12234 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12235 dvl.challenge = lle->challenge;
12236 dvl.initiator = *my_identity;
12237 {
12238 struct DvInitPS dvip = {
12239 .purpose.purpose = htonl (
12241 .purpose.size = htonl (sizeof(dvip)),
12242 .monotonic_time = dvl.monotonic_time,
12243 .challenge = lle->challenge
12244 };
12245 struct SignDvInitCls *sign_dv_init_cls;
12246
12247 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12248 sign_dv_init_cls->dvl = dvl;
12249 sign_dv_init_cls->lle = lle;
12250 sign_dv_init_cls->qqc = qqc;
12251 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12254 sign_dv_init_cls->pr);
12255 sign_dv_init_cls->pr->op =
12257 &dvip.purpose,
12259 sign_dv_init_cls);
12260 }
12261}
12262
12263
12271static char *
12273{
12274 const char *colon;
12275 char *colon_rest;
12276 size_t colon_rest_length;
12277 char *address_without_port;
12278
12279 colon = strchr (address,':');
12280 colon_rest = GNUNET_strndup (address, colon - address);
12281 colon_rest_length = strlen (colon_rest);
12282 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12283 GNUNET_free (colon_rest);
12284
12285 return address_without_port;
12286}
12287
12288
12298static int
12300 const struct GNUNET_PeerIdentity *pid,
12301 void *value)
12302{
12303 struct Queue *q = cls;
12304 struct ValidationState *vs = value;
12305 char *address_without_port_vs;
12306 char *address_without_port_q;
12307 int success = GNUNET_YES;
12308
12309 // TODO Check if this is really necessary.
12310 address_without_port_vs = get_address_without_port (vs->address);
12311 address_without_port_q = get_address_without_port (q->address);
12312
12314 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12315 GNUNET_i2s (pid),
12316 address_without_port_vs,
12317 address_without_port_q);
12318 (void) pid;
12319 if ((GNUNET_YES == vs->awaiting_queue) &&
12320 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12321 {
12322
12323 vs->awaiting_queue = GNUNET_NO;
12325 success = GNUNET_NO;
12326 }
12327
12328 GNUNET_free (address_without_port_vs);
12329 GNUNET_free (address_without_port_q);
12330 return success;
12331}
12332
12333
12342static void
12344 const struct GNUNET_PEERSTORE_Record *record,
12345 const char *emsg)
12346{
12347 struct Neighbour *n = cls;
12348 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12349
12350 (void) emsg;
12351 if (NULL == record)
12352 {
12353 /* we're done with #neighbour_dv_monotime_cb() invocations,
12354 continue normal processing */
12355 n->get = NULL;
12357 return;
12358 }
12359 if (0 == record->value_size)
12360 {
12362 GNUNET_break (0);
12363 return;
12364 }
12365 mtbe = record->value;
12370}
12371
12372
12373static void
12375 const struct GNUNET_PeerIdentity *pid,
12376 const char *uri)
12377{
12378 struct Queue *queue = cls;
12379 struct sockaddr_in v4;
12380 const char *slash;
12381 char *address_uri;
12382 char *prefix;
12383 char *uri_without_port;
12384 char *address_uri_without_port;
12385
12386 slash = strrchr (uri, '/');
12387 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12388 GNUNET_assert (NULL != slash);
12389 slash++;
12390 GNUNET_asprintf (&address_uri,
12391 "%s-%s",
12392 prefix,
12393 slash);
12394
12396 "1 not global natted_address %u %s %s %s\n",
12397 queue->is_global_natted,
12398 uri,
12399 queue->address,
12400 slash);
12401
12402 uri_without_port = get_address_without_port (address_uri);
12403 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12404 {
12406 GNUNET_free (address_uri);
12407 GNUNET_free (uri_without_port);
12408 return;
12409 }
12410
12412 "2 not global natted_address %u %s %s\n",
12413 queue->is_global_natted,
12414 uri,
12415 queue->address);
12416
12417 if (GNUNET_NO == queue->is_global_natted)
12418 {
12420 GNUNET_free (address_uri);
12421 GNUNET_free (uri_without_port);
12422 return;
12423 }
12424
12426 "3 not global natted_address %u %s %s\n",
12427 queue->is_global_natted,
12428 uri,
12429 queue->address);
12430
12431 if (0 == strcmp (uri_without_port, address_uri))
12432 {
12434 GNUNET_free (address_uri);
12435 GNUNET_free (uri_without_port);
12436 return;
12437 }
12438
12440 "4 not global natted_address %u %s %s\n",
12441 queue->is_global_natted,
12442 uri,
12443 queue->address);
12444
12445 address_uri_without_port = get_address_without_port (queue->address);
12446 if (0 == strcmp (uri_without_port, address_uri_without_port))
12447 {
12448 queue->is_global_natted = GNUNET_NO;
12449 }
12450
12452 "not global natted_address %u %s %s %s %s %s %u\n",
12453 queue->is_global_natted,
12454 uri,
12455 queue->address,
12456 uri_without_port,
12457 address_uri_without_port,
12458 prefix,
12459 GNUNET_NO);
12461 GNUNET_free (address_uri);
12462 GNUNET_free (address_uri_without_port);
12463 GNUNET_free (uri_without_port);
12464}
12465
12466
12479
12480
12481static enum GNUNET_GenericReturnValue
12483 const struct GNUNET_PeerIdentity *pid,
12484 void *value)
12485{
12486 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12487 struct TransportGlobalNattedAddress *tgna = value;
12488 char *addr = (char *) &tgna[1];
12489
12491 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12492 tgna,
12493 addr,
12494 ntohl (tgna->address_length),
12495 strlen (tgna_cls->addr));
12496 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12497 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12498 {
12499 tgna_cls->tgna = tgna;
12500 return GNUNET_NO;
12501 }
12502 return GNUNET_YES;
12503}
12504
12505
12506static void
12508{
12510 "Error in PEERSTORE monitoring for checking global natted\n");
12511}
12512
12513
12514static void
12516{
12518 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12519}
12520
12521
12522static void
12524 const struct GNUNET_PEERSTORE_Record *record,
12525 const char *emsg)
12526{
12527 struct Queue *queue = cls;
12528 struct Neighbour *neighbour = queue->neighbour;
12529 struct GNUNET_HELLO_Parser *parser;
12530 struct GNUNET_MessageHeader *hello;
12532 size_t address_len_without_port;
12533
12534 if (NULL != emsg)
12535 {
12537 "Got failure from PEERSTORE: %s\n",
12538 emsg);
12539 return;
12540 }
12541 if (0 == record->value_size)
12542 {
12544 GNUNET_break (0);
12545 return;
12546 }
12547 queue->is_global_natted = GNUNET_YES;
12548 hello = record->value;
12549 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
12551 "before not global natted %u\n",
12552 queue->is_global_natted);
12555 queue);
12557 "after not global natted %u\n",
12558 queue->is_global_natted);
12559 GNUNET_HELLO_parser_free (parser);
12560
12561 tgna_cls.addr = get_address_without_port (queue->address);
12562 address_len_without_port = strlen (tgna_cls.addr);
12563 /*{
12564 char buf[address_len_without_port + 1];
12565
12566 GNUNET_memcpy (&buf, addr, address_len_without_port);
12567 buf[address_len_without_port] = '\0';
12568 GNUNET_free (addr);
12569 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12570 }*/
12571 tgna_cls.tgna = NULL;
12573 &neighbour->pid,
12575 &tgna_cls);
12576 if (NULL != tgna_cls.tgna)
12578 " tgna_cls.tgna tgna %p %lu %u %u\n",
12579 tgna_cls.tgna,
12580 neighbour->size_of_global_addresses,
12581 ntohl (tgna_cls.tgna->address_length),
12582 neighbour->number_of_addresses);
12583 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12584 {
12585 struct TransportGlobalNattedAddress *tgna;
12586
12587 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12588 + address_len_without_port);
12589 tgna->address_length = htonl (address_len_without_port);
12590 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12592 &neighbour->pid,
12593 tgna,
12595 neighbour->number_of_addresses++;
12596 neighbour->size_of_global_addresses += address_len_without_port + 1;
12598 "Created tgna %p with address %s and length %lu\n",
12599 tgna,
12600 tgna_cls.addr,
12601 address_len_without_port + 1);
12602 }
12603 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12604 {
12606 &neighbour->pid,
12607 tgna_cls.tgna);
12608 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12610 );
12611 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12612 ;
12613 GNUNET_assert (0 < neighbour->number_of_addresses);
12614 neighbour->number_of_addresses--;
12616 "removed tgna %p\n",
12617 tgna_cls.tgna);
12618 GNUNET_free (tgna_cls.tgna);
12619 }
12621 GNUNET_free (tgna_cls.addr);
12622}
12623
12624
12631static void
12633 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12634{
12635 struct TransportClient *tc = cls;
12636 struct Queue *queue;
12637 struct Neighbour *neighbour;
12638 const char *addr;
12639 uint16_t addr_len;
12640
12641 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12642 {
12643 /* MTU so small as to be useless for transmissions,
12644 required for #fragment_message()! */
12645 GNUNET_break_op (0);
12647 return;
12648 }
12649 /* This may simply be a queue update */
12650 for (queue = tc->details.communicator.queue_head;
12651 NULL != queue;
12652 queue = queue->next_client)
12653 {
12654 if (queue->qid != ntohl (aqm->qid))
12655 continue;
12656 break;
12657 }
12658
12659 if (NULL != queue)
12660 {
12661 neighbour = queue->neighbour;
12662 }
12663 else
12664 {
12665 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12666
12667 neighbour = lookup_neighbour (&aqm->receiver);
12668 if (NULL == neighbour)
12669 {
12670 neighbour = GNUNET_new (struct Neighbour);
12672 GNUNET_YES);
12673 neighbour->pid = aqm->receiver;
12676 neighbours,
12677 &neighbour->pid,
12678 neighbour,
12680 neighbour->get =
12682 "transport",
12683 &neighbour->pid,
12686 neighbour);
12687 }
12688 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12689 addr = (const char *) &aqm[1];
12691 "New queue %s to %s available with QID %u and q_len %" PRIu64
12692 " and mtu %u\n",
12693 addr,
12694 GNUNET_i2s (&aqm->receiver),
12695 ntohl (aqm->qid),
12696 GNUNET_ntohll (aqm->q_len),
12697 ntohl (aqm->mtu));
12698 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12699 queue->tc = tc;
12700 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12701 next_neighbour)
12702 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12703 validated_until);
12704 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12705 {
12707 "New queue with QID %u inherit validated until\n",
12708 ntohl (aqm->qid));
12709 queue->validated_until = validated_until;
12710 }
12711 queue->address = (const char *) &queue[1];
12712 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12713 queue->qid = ntohl (aqm->qid);
12714 queue->neighbour = neighbour;
12716 queue->unlimited_length = GNUNET_YES;
12717 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12718 memcpy (&queue[1], addr, addr_len);
12719 /* notify monitors about new queue */
12720 {
12721 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12722
12723 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12724 }
12726 neighbour->queue_head,
12727 neighbour->queue_tail,
12728 queue);
12730 tc->details.communicator.queue_head,
12731 tc->details.communicator.queue_tail,
12732 queue);
12733
12734 }
12735 queue->mtu = ntohl (aqm->mtu);
12736 queue->nt = ntohl (aqm->nt);
12737 queue->cs = ntohl (aqm->cs);
12738 queue->idle = GNUNET_YES;
12739
12740 {
12741 struct sockaddr_in v4;
12742 char *addr_without = get_address_without_port (queue->address);
12743 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12744 {
12746 "start not global natted\n");
12748 GNUNET_YES,
12749 "peerstore",
12750 &neighbour->pid,
12752 &
12754 NULL,
12755 &
12757 NULL,
12759 queue);
12760 }
12761 GNUNET_free (addr_without);
12762 }
12763 /* check if valdiations are waiting for the queue */
12765 &aqm->receiver))
12766 {
12769 &aqm->
12770 receiver,
12771 &
12773 queue))
12774 start_address_validation (&aqm->receiver, queue->address);
12775 }
12776 else
12777 start_address_validation (&aqm->receiver, queue->address);
12778 /* look for traffic for this queue */
12779 // TODO Check whether this makes any sense at all.
12780 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12781 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12782 /* might be our first queue, try launching DV learning */
12783 if (NULL == dvlearn_task)
12786}
12787
12788
12795static void
12797 const struct
12799{
12800 struct TransportClient *tc = cls;
12801 struct Queue *target_queue = NULL;
12802
12804 "Received queue update message for %u with q_len %llu and mtu %u\n",
12805 ntohl (msg->qid),
12806 (unsigned long long) GNUNET_ntohll (msg->q_len),
12807 ntohl (msg->mtu));
12808 for (target_queue = tc->details.communicator.queue_head;
12809 NULL != target_queue;
12810 target_queue = target_queue->next_client)
12811 {
12812 if (ntohl (msg->qid) == target_queue->qid)
12813 break;
12814 }
12815 if (NULL == target_queue)
12816 {
12818 "Queue to update no longer exists! Discarding update.\n");
12819 return;
12820 }
12821
12822 target_queue->nt = msg->nt;
12823 target_queue->mtu = ntohl (msg->mtu);
12824 target_queue->cs = msg->cs;
12825 target_queue->priority = ntohl (msg->priority);
12826 /* The update message indicates how many messages
12827 * the queue should be able to handle.
12828 */
12830 target_queue->unlimited_length = GNUNET_YES;
12831 else
12832 target_queue->unlimited_length = GNUNET_NO;
12833 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12834 if (0 < target_queue->q_capacity)
12836 target_queue,
12839}
12840
12841
12849static void
12851 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12852{
12853 struct TransportClient *tc = cls;
12854
12855 if (CT_COMMUNICATOR != tc->type)
12856 {
12857 GNUNET_break (0);
12859 return;
12860 }
12862 "# Suggestions succeeded at communicator",
12863 1,
12864 GNUNET_NO);
12866 "Request #%u for communicator to create queue succeeded\n",
12867 (unsigned int) ntohs (cqr->request_id));
12869}
12870
12871
12880static void
12882 void *cls,
12883 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12884{
12885 struct TransportClient *tc = cls;
12886
12887 if (CT_COMMUNICATOR != tc->type)
12888 {
12889 GNUNET_break (0);
12891 return;
12892 }
12894 "Request #%u for communicator to create queue failed\n",
12895 (unsigned int) ntohl (cqr->request_id));
12897 "# Suggestions failed in queue creation at communicator",
12898 1,
12899 GNUNET_NO);
12901}
12902
12903
12911static void
12913{
12914 struct TransportClient *tc = cls;
12915 struct PeerRequest *pr;
12916
12917 if (CT_APPLICATION != tc->type)
12918 {
12919 GNUNET_break (0);
12921 return;
12922 }
12923 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
12924 &msg->peer);
12925 if (NULL == pr)
12926 {
12927 GNUNET_break (0);
12929 return;
12930 }
12931 (void) stop_peer_request (tc, &pr->pid, pr);
12933}
12934
12935
12936static void
12938 const struct GNUNET_PeerIdentity *pid,
12939 const char *uri)
12940{
12941 struct Queue *q;
12942 int pfx_len;
12943 const char *eou;
12944 char *address;
12945 (void) cls;
12946
12947 eou = strstr (uri,
12948 "://");
12949 pfx_len = eou - uri;
12950 eou += 3;
12952 "%.*s-%s",
12953 pfx_len,
12954 uri,
12955 eou);
12956
12958 "hello for client %s\n",
12959 address);
12960
12961 q = find_queue (pid, address);
12962 if (NULL == q)
12963 {
12965 }
12966 else
12969}
12970
12971
12979static void
12981 const struct GNUNET_PEERSTORE_Record *record,
12982 const char *emsg)
12983{
12984 const struct GNUNET_PeerIdentity *my_identity;
12985 struct PeerRequest *pr = cls;
12986 struct GNUNET_HELLO_Parser *parser;
12987 struct GNUNET_MessageHeader *hello;
12988
12989 if (NULL != emsg)
12990 {
12992 "Got failure from PEERSTORE: %s\n",
12993 emsg);
12994 return;
12995 }
12997 if (NULL == my_identity)
12998 {
13000 "No identity given yet!\n");
13001 return;
13002 }
13003 hello = record->value;
13004 if (0 == GNUNET_memcmp (&record->peer, my_identity))
13005 {
13007 return;
13008 }
13009 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
13010 if (NULL == parser)
13011 {
13013 "HELLO cannot be parsed!\n");
13014 return;
13015 }
13017 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13021 NULL);
13022 GNUNET_HELLO_parser_free (parser);
13023}
13024
13025
13026static void
13028{
13030 "Error in PEERSTORE monitoring\n");
13031}
13032
13033
13034static void
13036{
13038 "Done with initial PEERSTORE iteration during monitoring\n");
13039}
13040
13041
13049static void
13051{
13052 struct TransportClient *tc = cls;
13053 const struct GNUNET_PeerIdentity *my_identity;
13054 struct PeerRequest *pr;
13055
13056 if (CT_NONE == tc->type)
13057 {
13058 tc->type = CT_APPLICATION;
13059 tc->details.application.requests =
13061 }
13062 if (CT_APPLICATION != tc->type)
13063 {
13064 GNUNET_break (0);
13066 return;
13067 }
13069 if (NULL == my_identity)
13070 {
13072 "Still waiting for own identity!\n");
13074 return;
13075 }
13077 "Client suggested we talk to %s with preference %d at rate %u\n",
13078 GNUNET_i2s (&msg->peer),
13079 (int) ntohl (msg->pk),
13080 (int) ntohl (msg->bw.value__));
13081 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
13082 {
13084 "Client suggested connection to ourselves, ignoring...\n");
13086 return;
13087 }
13088 pr = GNUNET_new (struct PeerRequest);
13089 pr->tc = tc;
13090 pr->pid = msg->peer;
13091 pr->bw = msg->bw;
13092 pr->pk = ntohl (msg->pk);
13094 tc->details.application.requests,
13095 &pr->pid,
13096 pr,
13098 {
13099 GNUNET_break (0);
13100 GNUNET_free (pr);
13102 return;
13103 }
13104 pr->nc =
13106 GNUNET_YES,
13107 "peerstore",
13108 NULL,
13111 NULL,
13113 NULL,
13115 pr);
13117}
13118
13119
13128static int
13130 const struct RequestHelloValidationMessage *m)
13131{
13132 (void) cls;
13134 return GNUNET_OK;
13135}
13136
13137
13145static void
13147 const struct RequestHelloValidationMessage *m)
13148{
13149 struct TransportClient *tc = cls;
13150 struct Queue *q;
13151
13152 q = find_queue (&m->peer, (const char *) &m[1]);
13153 if (NULL == q)
13154 {
13155 suggest_to_connect (&m->peer, (const char *) &m[1]);
13156 }
13157 else
13158 start_address_validation (&m->peer, (const char *) &m[1]);
13160}
13161
13162
13171static int
13173 const struct GNUNET_PeerIdentity *pid,
13174 void *value)
13175{
13176 struct Neighbour *neighbour = value;
13177
13178 (void) cls;
13179 (void) pid;
13180 GNUNET_break (0); // should this ever happen?
13181 free_neighbour (neighbour, GNUNET_YES);
13182
13183 return GNUNET_OK;
13184}
13185
13186
13195static int
13197 const struct GNUNET_PeerIdentity *pid,
13198 void *value)
13199{
13200 struct DistanceVector *dv = value;
13201
13202 (void) cls;
13203 (void) pid;
13204 free_dv_route (dv);
13205
13206 return GNUNET_OK;
13207}
13208
13209
13218static int
13220 const struct GNUNET_PeerIdentity *pid,
13221 void *value)
13222{
13223 struct ValidationState *vs = value;
13224
13225 (void) cls;
13226 (void) pid;
13228 return GNUNET_OK;
13229}
13230
13231
13240static int
13241free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
13242{
13243 struct PendingAcknowledgement *pa = value;
13244
13245 (void) cls;
13246 (void) key;
13248 return GNUNET_OK;
13249}
13250
13251
13260static int
13262 const struct GNUNET_PeerIdentity *pid,
13263 void *value)
13264{
13265 struct AcknowledgementCummulator *ac = value;
13266
13267 (void) cls;
13268 (void) pid;
13270 GNUNET_free (ac);
13271 return GNUNET_OK;
13272}
13273
13274
13281static void
13282do_shutdown (void *cls)
13283{
13284 struct LearnLaunchEntry *lle;
13285 struct PilsRequest *pr;
13286 (void) cls;
13287
13289 "shutdown logic\n");
13292 &free_neighbour_cb, NULL);
13293 if (NULL != validation_task)
13294 {
13296 validation_task = NULL;
13297 }
13298 if (NULL != dvlearn_task)
13299 {
13301 dvlearn_task = NULL;
13302 }
13303 if (NULL != burst_task)
13304 {
13306 burst_task = NULL;
13307 }
13308 if (NULL != burst_timeout_task)
13309 {
13311 burst_timeout_task = NULL;
13312 }
13315 dvlearn_map = NULL;
13318 dv_routes = NULL;
13319 if (NULL != GST_stats)
13320 {
13322 GST_stats = NULL;
13323 }
13324 if (NULL != GST_my_hello)
13325 {
13327 GST_my_hello = NULL;
13328 }
13331 NULL);
13333 ack_cummulators = NULL;
13336 NULL);
13338 pending_acks = NULL;
13341 neighbours = NULL;
13344 links = NULL;
13347 NULL);
13349 backtalkers = NULL;
13352 NULL);
13354 validation_map = NULL;
13356 validation_heap = NULL;
13358 revalidation_map = NULL;
13359 while (NULL != ir_head)
13361 GNUNET_assert (0 == ir_total);
13362 while (NULL != (lle = lle_head))
13363 {
13365 GNUNET_free (lle);
13366 }
13367 while (NULL != (pr = pils_requests_head))
13368 {
13371 pr);
13372 if (NULL != pr->op)
13373 GNUNET_PILS_cancel (pr->op);
13374 GNUNET_free (pr);
13375 }
13376 if (NULL != pils_feed_task)
13377 {
13379 pils_feed_task = NULL;
13380 }
13381 if (NULL != pils)
13382 {
13384 pils = NULL;
13385 }
13386 if (NULL != peerstore)
13387 {
13389 "Disconnecting from PEERSTORE service\n");
13391 peerstore = NULL;
13392 }
13394}
13395
13396
13397static const char*
13399{
13400 switch (type)
13401 {
13402 case CT_CORE:
13403 return "CORE";
13404 case CT_MONITOR:
13405 return "MONITOR";
13406 case CT_COMMUNICATOR:
13407 return "COMMUNICATOR";
13408 case CT_APPLICATION:
13409 return "APPLICATION";
13410 default:
13411 return "UNKNOWN";
13412 }
13413}
13414
13415
13416static void
13417shutdown_task (void *cls)
13418{
13420
13422 "Shutdown task executed\n");
13423 if (NULL != clients_head)
13424 {
13425 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13426 {
13428 "Client still connected: %s\n",
13429 get_client_type_name (tc->type));
13430 }
13431 }
13432 else
13433 do_shutdown (cls);
13434
13435}
13436
13437
13442
13443static void
13444update_hello_from_pid_change_cb (void *cls, int success)
13445{
13446 struct UpdateHelloFromPidCtx *pc = cls;
13447
13448 if (GNUNET_OK != success)
13449 {
13451 "Failed to store our new hello with peerstore\n");
13452 }
13453 GNUNET_free (pc);
13455 "Stored our new hello with peerstore\n");
13456}
13457
13458
13459void
13461 const struct GNUNET_PeerIdentity *pid,
13462 const char *uri)
13463{
13465 "%s\n", uri);
13466}
13467
13468
13478static void
13480 const struct GNUNET_HELLO_Parser *parser,
13481 const struct GNUNET_HashCode *hash)
13482{
13483 const struct GNUNET_PeerIdentity *my_identity;
13484 struct GNUNET_MQ_Envelope *env;
13485 const struct GNUNET_MessageHeader *msg;
13486 struct UpdateHelloFromPidCtx *sc;
13487 struct GNUNET_HELLO_Builder *nbuilder;
13488 struct GNUNET_PeerIdentity npid;
13489
13492
13493 if (NULL == GST_my_hello)
13496 "My current identity is `%s'\n",
13508 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13509 &npid);
13510 if (GNUNET_NO ==
13512 {
13514 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
13516 "Proposed address list:\n");
13519 "Current address list:\n");
13521 GNUNET_HELLO_builder_free (nbuilder);
13522 return;
13523 }
13525 GST_my_hello = nbuilder;
13527 "My new identity is `%s'\n",
13533 msg,
13535 sc);
13536 GNUNET_free (env);
13537}
13538
13539
13547static void
13548run (void *cls,
13549 const struct GNUNET_CONFIGURATION_Handle *c,
13551{
13552 (void) cls;
13553 (void) service;
13554 /* setup globals */
13557 GST_cfg = c;
13565 GNUNET_YES);
13570 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13572 "transport",
13573 "USE_BURST_NAT");
13574 if (GNUNET_SYSERR == use_burst)
13576 "Could not configure burst nat use. Default to no.\n");
13582 "transport",
13583 0,
13584 0,
13585 NULL,
13586 0,
13587 NULL,
13588 NULL,
13589 NULL);
13590 if (NULL == peerstore)
13591 {
13592 GNUNET_break (0);
13594 return;
13595 }
13598 NULL); // FIXME we need to wait for
13599 // our first peer id before
13600 // we can start the service
13601 // completely - PILS in turn
13602 // waits for the first
13603 // addresses from the
13604 // communicators in order to
13605 // be able to generate a
13606 // peer id
13607 if (NULL == pils)
13608 {
13609 GNUNET_break (0);
13611 return;
13612 }
13613}
13614
13615
13621 "transport",
13623 &run,
13626 NULL,
13627 /* communication with applications */
13628 GNUNET_MQ_hd_fixed_size (suggest,
13631 NULL),
13632 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13635 NULL),
13636 GNUNET_MQ_hd_var_size (request_hello_validation,
13639 NULL),
13640 /* communication with core */
13641 GNUNET_MQ_hd_fixed_size (client_start,
13643 struct StartMessage,
13644 NULL),
13645 GNUNET_MQ_hd_var_size (client_send,
13647 struct OutboundMessage,
13648 NULL),
13649 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13651 struct RecvOkMessage,
13652 NULL),
13653 /* communication with communicators */
13654 GNUNET_MQ_hd_var_size (communicator_available,
13657 NULL),
13658 GNUNET_MQ_hd_var_size (communicator_backchannel,
13661 NULL),
13662 GNUNET_MQ_hd_var_size (add_address,
13665 NULL),
13666 GNUNET_MQ_hd_fixed_size (del_address,
13669 NULL),
13670 GNUNET_MQ_hd_var_size (incoming_msg,
13673 NULL),
13674 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13677 NULL),
13678 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13681 NULL),
13682 GNUNET_MQ_hd_var_size (add_queue_message,
13685 NULL),
13686 GNUNET_MQ_hd_fixed_size (update_queue_message,
13689 NULL),
13690 GNUNET_MQ_hd_fixed_size (del_queue_message,
13693 NULL),
13694 GNUNET_MQ_hd_fixed_size (send_message_ack,
13697 NULL),
13698 GNUNET_MQ_hd_fixed_size (burst_finished,
13701 NULL),
13702 /* communication with monitors */
13703 GNUNET_MQ_hd_fixed_size (monitor_start,
13706 NULL),
13708
13709
13710/* 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.
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
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 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 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 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 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 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 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(uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_decrypt(size_t ct_len, const unsigned char ct[ct_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, const struct GNUNET_CRYPTO_AeadMac *mac, void *pt)
Decrypt the given data using XChaCha20-Poly1305.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_encrypt(size_t pt_len, const unsigned char pt[pt_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, void *ct, struct GNUNET_CRYPTO_AeadMac *mac)
Encrypt the given data using XChaCha20-Poly1305.
void GNUNET_CRYPTO_random_block(void *buffer, size_t length)
Fill block with a random values.
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.
uint32_t GNUNET_CRYPTO_random_u32(uint32_t i)
Produce a random value.
#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:40
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:1003
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:1022
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:950
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:1378
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:979
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:671
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:1109
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:1189
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
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_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:1629
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:610
#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:671
#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
static 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.
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 session keys
type for session 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_CRYPTO_AeadNonce iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
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_CRYPTO_AeadMac mac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
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